Constructor help

  • (3 Pages)
  • +
  • 1
  • 2
  • 3

30 Replies - 6228 Views - Last Post: 24 May 2006 - 04:39 AM Rate Topic: -----

#1 Richard Goodwin  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 28
  • Joined: 09-May 06

Constructor help

Posted 16 May 2006 - 03:32 AM

Hi,
I am working on a solitaire game called Calculation.

The Foundation class provides the methods to manage and display the foundation of the Calculation game. Since the foundation contains four rows of cards, it is natural for the Foundation class to have a field that is an array of four "somethings", where each "something" represents a row of the foundation. So what I have to do is create a FoundationRow class to handle all the logic associated with one row of the foundation. Then later on when I create the Foundation class, it will have an array of four objects of the type FoundationRow.

Anyway, Im trying to write a constructor for class called FoundationRow.

public FoundationRow(int startNumber, Deck deck)

Parameters:
startNumber - the pip count for the first card in the row, which is also the difference in pip values for adjacent cards in this row. This must be a value in the range 1-4 inclusive.

deck - the deck of cards from which the first card whose pip count equals startNumber is extracted as the first card in the row. When the constructor returns, the number of cards in the deck will be one less than where it was called due to the removal of this card. It may be assumed that the gicen deck contains such a card.


The constructor should set up an array of 13 cards in which the first element is the first card in the given deck of the required pip number.

In the game calculation, a card's suit is irrelevant, only the pip count (1-13) is relevant. The game starts with a shuffled deck of cards from which an ace, two, three and four have been extracted. These four extracted cards form the start of four foundation rows. The goal of the game is to build up each foundation row from its start card through to a king. A card can only be added to a foundation row only in the first free position and only if its "pip value" differs from the card to its left by the pip value of the left-most card in the row.
Thus the first row takes cards A,2,3,4..., the second row takes 2,4,6,8,10,Q,A,3... , the third row takes 3,6,9,Q,2,5,8... and the fourth row takes 4,8,Q,3,7,J...

I am having trouble implementing the Constructor as I do not know how to write the code for the Constructors parameters.

Any suggestions?

Thanks :)

(Ive attached the outline of the FoundationRow class if it is of any help)

/**
 * A FoundationRow is a single row in a foundation. It has a start card,
 * which determines the step size in number of pips between cards in a row.
 */
public class FoundationRow
{
    private Deck deck;
    
    /**
     *Constructor for objects of class FoundationRow that will not be
     *displayed graphically.  When the constructor returns,the number of cards in the deck will be one less than when it was called due to the removal of 
     *this card.It may be assumed that the given deck contains such a card.
     *@param startNumber the pip count for the first card in the row, which is also the difference in pip values for adjacent cards
     *in this row.  This must be value in the range 1-4 inclusive.
     *@param deck the deck of cards from which the first card whose pip count equals startNumber is extracted as first card in the
     *row.
     */

    public FoundationRow(int startNumber, Deck deck)
    {
      
      deck = this.deck;
    }
    
    /**
     *An array of 13 elements, each of which is either a Card or null.  If the row contains n (1-13 inclusive) cards,
     *element 0...n-1 will be the cards, and elements n onwards will all be null.  This is just a getter method for the
     *array of cards in this foundation row.
     *@return an array of 13 elements,with the first n being the cards in this row and the remaining 13-n being null,
     *when n is the number of cards currently in this row.
     */     
    public Card[] getCards()
    {
      return null;  
    }

    /**
    * Add (or attempt to add) the given card to this row.  Returns true if the add is successful,i.e.,the difference between
    * the number of pips on this card and the number of pips on the card currently at the end of the row is equal to the 
    * number of pips on the card at the start of the row.  If the parameter is null,the method returns false
    * @param card the card to be add to the row, if possible.
    * @return true if and only if the add succeeds.
    */       
    public boolean putCard(Card card)
    {
      return true;
    }

    /**
    * A string representation of the object.  This is the string representations of each card in the row, separated by single space.
    * There are no spaces at the start or end of the row -- only between the individual cards.
    * @overrides toString in class java.lang.Object
    */    
    public String toString()
    {
      return "";  
    }

}


This post has been edited by Richard Goodwin: 16 May 2006 - 06:38 AM


Is This A Good Question/Topic? 1

Replies To: Constructor help

#2 Richard Goodwin  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 28
  • Joined: 09-May 06

Re: Constructor help

Posted 16 May 2006 - 06:37 AM

also, here is the code for the Deck class that I came up with...

import java.util.*;
import java.awt.*;

    /**
     * * A full deck of cards. It is shuffled when first constructed
     * * * and thereafter cards are removed from the deck by calls to 
     * * * * nextCard until no further cards remain. Cards can also be
     * * * * * placed back on the deck at either the start or the end.
     * * * * * */
public class Deck
{
    private java.util.List<Card> cards;      // The list of cards
    private static java.util.Random generator = null;
    
    /**
     * Constructor for a shuffled deck of cards.
     * @param seed the seed for the random number generator used to
     * shuffle the deck. A different unique shuffle is obtained for
     * each possible value of seed.
     */
    public Deck(long seed)
    {
        // Create a deck of cards in sorted order of suit then pip count.
        
        cards = new ArrayList<Card>();
        for (int suit = Card.SPADES; suit <= Card.CLUBS; suit++) {
            for (int pips = 1; pips <= Card.CARDS_IN_SUIT; pips++) {
                cards.add(new Card(suit, pips));
            }
        }
        
        // Now shuffle the deck, using a random number generator based
        // on the seed value given as a parameter.
        
        java.util.Random generator = new java.util.Random(seed); 
        java.util.Collections.shuffle(cards, generator);
    }
     
    /**
     * The number of cards still remaining in the deck.
     * @return the number of cards left in the deck.
     */
    public int numCardsRemaining()
    {
        return cards.size();
    }
    
    /**
     * Get the next card from the deck, reducing the number of cards
     * remaining in the deck by one.
     * @return the "top" card in the deck
     */
    public Card nextCard()
    {
        return cards.remove(0);
    }
    
    /**
     * Add the given card to the start (front) of the current deck.
     * @param card the card to be placed at the start of the deck
     */
    public void addAtStart(Card card)
    {
        cards.add(0, card);
    }
    
    /**
     * Add the given card to the end (back) of the current deck.
     * @param card the card to be placed on the end of the deck
     */
    public void addAtEnd(Card card)
    {
        cards.add(card);
    }
}

Was This Post Helpful? 0
  • +
  • -

#3 William_Wilson  Icon User is offline

  • lost in compilation
  • member icon

Reputation: 205
  • View blog
  • Posts: 4,807
  • Joined: 23-December 05

Re: Constructor help

Posted 16 May 2006 - 11:51 AM

First off, i would suggest naming the class and constructor parameters differently, so that they are not so easily confused.
public class FoundationRow
{
   private Deck deck;

public FoundationRow(int astartNumber, Deck aDeck)
   {
     
     deck = aDeck; //assign the variable
    }
...}


Since the deck is supposed be shuffled (in this case with a random number generator) I don't see how/why you would need a start number?
*Also i don't think i've ever heard the word 'pip' before, knowing what that means may help some, lol.
Was This Post Helpful? 0
  • +
  • -

#4 sigmazero13  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 26
  • Joined: 10-May 06

Re: Constructor help

Posted 16 May 2006 - 12:08 PM

William_Wilson - The term pip that I'm familiar with is generally used in connection with dice; the "dots" on each face of a die are called "pips".

My guess is a "pip" on the cards is probably similar. For playing cars, maybe the "pips" are the number of symbols on the card, regardless of suit?

In this case, the cards seem to be "special" cards, so I think the pips is the number of dots on the virtual cards.
Was This Post Helpful? 0
  • +
  • -

#5 William_Wilson  Icon User is offline

  • lost in compilation
  • member icon

Reputation: 205
  • View blog
  • Posts: 4,807
  • Joined: 23-December 05

Re: Constructor help

Posted 16 May 2006 - 12:16 PM

That would make sense, and i understand the game much better now (as i have played this with a real deck :))
basically the four starting cards (1,2,3,4) are already removed from this deck? Thus hold 4 arrays or vectors, of appropriate names.
As you move through the deck of cards, simply add them to the appropriate row if it is possible, you will need to create int variables which keep track of the last number added position, if you use arrays.

All a constructor does is initialize variables and do assignments so that the program can begin.

This post has been edited by William_Wilson: 16 May 2006 - 12:19 PM

Was This Post Helpful? 0
  • +
  • -

#6 Richard Goodwin  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 28
  • Joined: 09-May 06

Re: Constructor help

Posted 17 May 2006 - 02:10 AM

William_Wilson, on 16 May, 2006 - 11:08 AM, said:

That would make sense, and i understand the game much better now (as i have played this with a real deck :))
basically the four starting cards (1,2,3,4) are already removed from this deck? Thus hold 4 arrays or vectors, of appropriate names.
As you move through the deck of cards, simply add them to the appropriate row if it is possible, you will need to create int variables which keep track of the last number added position, if you use arrays.

All a constructor does is initialize variables and do assignments so that the program can begin.

Yes pips refer to the rank of the cards.

I am trying to write the Constructor so that it sets up an array of 13 cards in which the first element is the first card in the given deck of the required pip number. All of the other elements should be null. The card used to start the row should be removed from the deck without altering the order of the other cards in the deck. (And to make things harder, I cannot alter the Deck class in any way to achieve this).

Im recently new to learning Java, and am not sure as to how to write out the constructor.

Any help is much appreciated!

Thanks :)
Was This Post Helpful? 0
  • +
  • -

#7 William_Wilson  Icon User is offline

  • lost in compilation
  • member icon

Reputation: 205
  • View blog
  • Posts: 4,807
  • Joined: 23-December 05

Re: Constructor help

Posted 17 May 2006 - 09:26 AM

your deck class has a nextCard() method which does just that, it also removes the card from the deck (a type of arraylist) so it will not be used again. The deck class seems to have everything you need just use the methods provided :)
I assume you are looking to add the first 4 cards, as the first card of each row: if the first four cards were -> Q, 3, 5, A, then the rows would look like:
Q,null,...
3,null,...
5,null,...
A,null,...

java will do the nulls for you as it initializes all lists/collections for you with null or 0.
You will need a global variable to hold your rows, if you wish to use your getCards() method, i am assuming this returns all the cards? if so it should be a 2D array (if you plan to use an array): Cards[][]
*I don't understand the need for the startnumber, pretty sure it is not needed
Your constructor should look something like this:
private Card[][] rows; //global variable

public FoundationRow(int startNumber, Deck aDeck)
{
     deck = aDeck;
     rows = new Card[4][13];//initialize global rows object
     
     for(int i=0;i<4;++i){
          rows[i][0] = deck.nextCard(); //add first 4 cards to rows
     }
}


*this will add the first 4 cards of the deck to the rows, i think that is what you wanted?
the startnumber i would assume applies to the first row, then you rotate through the values for the other rows? if it was 3, then the rows would have pip values of:
3
4
1
2
if so, just make another global int value to hold this pip value, and use it as a refrence point for each row.
Was This Post Helpful? 0
  • +
  • -

#8 Richard Goodwin  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 28
  • Joined: 09-May 06

Re: Constructor help

Posted 17 May 2006 - 09:17 PM

Thanks for that!

Although I cannot get it to pass the unit test?

This is the unit test code...

 
public class FoundationRowTest extends junit.framework.TestCase
{
    private Deck twoCardDeck;
    private Card ace;
    private Card three;
    
    /**
     * Default constructor for test class FoundationRowTest
     */
    public FoundationRowTest()
    {
    }
    
    /**
     * Test the constructor and the getCards methods together.
     */
    public void testConstructor1()
    {
        // Construct a new row and check it has the right values in it
        FoundationRow testRow = new FoundationRow(1, twoCardDeck);
        Card[] cards = testRow.getCards();
        assertEquals(13, cards.length);
        assertEquals(ace, cards[0]);
        for (int i = 1; i < 13; i++) {
            assertEquals(null, cards[i]);
        }
        
        // Check that the ace has been removed from the deck, leaving
        // only the three.
        assertEquals(1, twoCardDeck.numCardsRemaining());
        assertEquals(three, twoCardDeck.nextCard());
    }
        
    /**
     * Test the constructor and the getCards methods together, take 2!
     * This is the same as testConstructor1 except that it starts
     * the row with the value 3.
     */
    public void testConstructor2()
    {
         // Construct a new row and check it has the right values in it
        FoundationRow testRow = new FoundationRow(3, twoCardDeck);
        Card[] cards = testRow.getCards();
        assertEquals(13, cards.length);
        assertEquals(three, cards[0]);
        for (int i = 1; i < 13; i++) {
            assertEquals(null, cards[i]);
        }
        
        // Check that the ace has been removed from the deck, leaving
        // only the three.
        assertEquals(1, twoCardDeck.numCardsRemaining());
        assertEquals(ace, twoCardDeck.nextCard());
    } 
    
    /**
     * Test that the order of cards in the deck is not altered by
     * the construction of a new FoundationRow, except for the removal
     * of the start card.
     */
    public void testConstructor3()
    {
        Deck deck1 = new Deck(1);  // Deck to use in constructing row
        Deck deck2 = new Deck(1);  // A copy of that deck
        FoundationRow testRow = new FoundationRow(3, deck1);
        assertEquals(51, deck1.numCardsRemaining());
        boolean found = false;  // True when we've found the first occurrence of a 3
        
        // Go through both the deck used in constructing the new row
        // and the copy deck, checking that we get the same cards except for the
        // first card with a pip count of three (which should have been removed).
        while (deck2.numCardsRemaining() > 0) {
            Card c2 = deck2.nextCard();  // Card from our copy deck
            if (c2.getNumber() == 3 && !found) {
                found = true;
            }
            else {
                Card c1 = deck1.nextCard();  // Card from deck used in constructing row
                assertEquals(c2.getNumber(), c1.getNumber());
                assertEquals(c2.getSuit(), c1.getSuit());
            }
        }
        assertEquals(0, deck1.numCardsRemaining());
    }
    
   /**
     * Test the putCard method for a row starting with an ace.
     */
    public void testPutCard1()
    {
        FoundationRow row = new FoundationRow(1, twoCardDeck);
        Card twoOfClubs = new Card(Card.CLUBS, 2);
        boolean ok = row.putCard(twoOfClubs);
        assertEquals(true, ok);
        Card[] cards = row.getCards();
        assertEquals(13, cards.length);
        assertEquals(ace, cards[0]); // Make sure the first card didn't get clobbered
        assertEquals(twoOfClubs, cards[1]);  // The second should be the two
        assertEquals(null, cards[2]);  // Make sure the third is still null
        
        // Now try adding an illegal card
        
        Card fourOfHearts = new Card(Card.HEARTS, 4);
        ok = row.putCard(fourOfHearts);
        assertEquals(false, ok);
        cards = row.getCards();
        assertEquals(ace, cards[0]);
        assertEquals(twoOfClubs, cards[1]);
        assertEquals(null, cards[2]);
    }
    
    /**
     * Test the putCard method, this time for a row starting with a three.
     */
    public void testPutCard2()
    {
        FoundationRow row = new FoundationRow(3, twoCardDeck);
        Card sixOfClubs = new Card(Card.CLUBS, 6);
        boolean ok = row.putCard(sixOfClubs);
        assertEquals(true, ok);
        Card[] cards = row.getCards();
        assertEquals(13, cards.length);
        assertEquals(three, cards[0]); // Make sure the first card didn't get clobbered
        assertEquals(sixOfClubs, cards[1]);  // The second should be the six
        assertEquals(null, cards[2]);  // Make sure the third is still null
        
        // Now try adding an illegal card
        
        Card fourOfHearts = new Card(Card.HEARTS, 4);
        ok = row.putCard(fourOfHearts);
        assertEquals(false, ok);
        cards = row.getCards();
        assertEquals(three, cards[0]);
        assertEquals(sixOfClubs, cards[1]);
        assertEquals(null, cards[2]);
    }
    
    /**
     * Test that the putCard method, repeatedly applied to a row starting
     * with a three, allows us to fill up the whole row.
     */
    public void testPutCard3()
    {
        FoundationRow row = new FoundationRow(3, twoCardDeck);
        int[] numsToAdd = {6, 9, 12, 2, 5, 8, 11, 1, 4, 7, 10, 13};
        for (int i = 0; i < numsToAdd.length; i++) {
            Card card = new Card(Card.CLUBS, numsToAdd[i]); // A card of reqd pip value
            assertEquals(true, row.putCard(card));
        }
        
        // Now check that the row contains the right sequence of cards.
        
        Card[] cards = row.getCards();
        assertEquals(13, cards.length);
        assertEquals(cards[0], three);  // Check the first card
        for (int i = 1; i < 13; i++) {  // Check all the others
            assertNotNull(cards[i]);
            assertEquals(numsToAdd[i-1], cards[i].getNumber());
        }
    }
    
    /**
     * Test the toString method. Test on a row created with 
     * a single ace, then after adding a 2 and again after adding
     * a three.
     */
    public void testToString()
    {
        FoundationRow row = new FoundationRow(1, twoCardDeck);
        assertEquals("SA", row.toString()); // Should be just the ace of spades
        assertEquals(true, row.putCard(new Card(Card.CLUBS, 2)));
        assertEquals("SA C2", row.toString());
        assertEquals(true, row.putCard(new Card(Card.HEARTS, 3)));
        assertEquals("SA C2 H3", row.toString());
    }

    /**
     * Sets up the test fixture.
     *
     * Called before every test case method.
     */
    protected void setUp()
    {
        twoCardDeck = new Deck(1);  // Create a new deck
        for (int i = 0; i < 52; i++) {  // Take out all the cards from it!
            twoCardDeck.nextCard();
        }
        
        // Build a new 2-card deck with the ace of spades at the top and the three
        // of hearts below it.
        
        ace = new Card(Card.SPADES, Card.ACE);
        three = new Card(Card.HEARTS, 3);
        twoCardDeck.addAtStart(ace);
        twoCardDeck.addAtEnd(three);
    }

    /**
     * Tears down the test fixture.
     *
     * Called after every test case method.
     */
    protected void tearDown()
    {
    }
}



Can anyone see what I am missing in my FoundationRow code which will make it pass the tests?

Thanks :)
Was This Post Helpful? 0
  • +
  • -

#9 William_Wilson  Icon User is offline

  • lost in compilation
  • member icon

Reputation: 205
  • View blog
  • Posts: 4,807
  • Joined: 23-December 05

Re: Constructor help

Posted 17 May 2006 - 10:24 PM

where does it fail/generate an error, OR perhaps you could attatch all the class files (not post as code) so i can run it and see for myself?
Was This Post Helpful? 0
  • +
  • -

#10 Richard Goodwin  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 28
  • Joined: 09-May 06

Re: Constructor help

Posted 17 May 2006 - 11:35 PM

I just realised it isn't passing the testConstructor in the unit test because I haven't implemented the putCard() method yet. (The constructorTest calls upon the putCard method as well as the constructor).


So the putCard method should add the given card to the end of the current row (i.e., to the next free slot) if and only if the card is non-null and the difference between its pip count and the pip count of the card currently at the end of the row is the right amount for this row. Specifically, the pip-count difference must equal the startNumber parameter passed to the constructor (and hence must also equal the pip count of the first card in the row).
Then theres the problem that I need to deal with the cyclic behaviour of this method, i.e., I need to allow for the fact that after King we "wrap around" again to Ace, 2, 3, ... etc.
I've been thinking for the past couple hours on how I would do that. The best idea Ive come up with is to use the "modulo" operator "%" when checking if a card can legally be added.

Though so far all my attempts at writing code to achieve this feat have proven futile :(


Here is the code I have so far...

This post has been edited by Richard Goodwin: 18 May 2006 - 09:30 PM

Was This Post Helpful? 0
  • +
  • -

#11 Richard Goodwin  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 28
  • Joined: 09-May 06

Re: Constructor help

Posted 17 May 2006 - 11:35 PM

Here is another one...

Attached File(s)


Was This Post Helpful? 0
  • +
  • -

#12 Richard Goodwin  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 28
  • Joined: 09-May 06

Re: Constructor help

Posted 17 May 2006 - 11:36 PM

The FoundationRow

This post has been edited by Richard Goodwin: 18 May 2006 - 09:31 PM

Was This Post Helpful? 0
  • +
  • -

#13 Richard Goodwin  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 28
  • Joined: 09-May 06

Re: Constructor help

Posted 17 May 2006 - 11:36 PM

The stock class...

This post has been edited by Richard Goodwin: 18 May 2006 - 09:31 PM

Was This Post Helpful? 0
  • +
  • -

#14 Richard Goodwin  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 28
  • Joined: 09-May 06

Re: Constructor help

Posted 17 May 2006 - 11:38 PM

FoundationRow unit test...

Attached File(s)


Was This Post Helpful? 0
  • +
  • -

#15 William_Wilson  Icon User is offline

  • lost in compilation
  • member icon

Reputation: 205
  • View blog
  • Posts: 4,807
  • Joined: 23-December 05

Re: Constructor help

Posted 18 May 2006 - 12:21 AM

Oddly enough i have tomorrow off from work, so i will see if i can come up with a few tips for ya :)
Was This Post Helpful? 0
  • +
  • -

  • (3 Pages)
  • +
  • 1
  • 2
  • 3