Back to 111 Main Page

Mobius strip

Assignment 17: Part 2 (Deck)

Task

Now that you have a PlayingCard, you can model a deck of playing cards.

Steps

Create a class named Deck. It should contain the following public methods. Again, the (reusable) documentation explains what each should do.

/**
 * Constructs a new deck of 52 standard playing cards with no jokers.
 * If the parameter shuffled == true, the new deck will be shuffled.
 * Otherwise, it will be in sorted order.
 */
public Deck(boolean shuffled)

/**
 * Constructs a deck of 52 shuffled playing cards.
 */
public Deck()

/**
 * Removes the top card from this deck and returns it.
 * If this deck is empty, will return null instead.
 */
public PlayingCard draw()

/**
 * Returns the number of cards currently remaining in this deck.
 */
public int getSize()

/**
 * Shuffles the cards remaining in this deck.
 */
public void shuffle()

Make sure your method signatures match these exactly. Any instance variables you have should be private. (All you really need is either a PlayingCard[] and int count variable or a ArrayList<PlayingCard>.)

When constructing a Deck, you need to add cards to it in some sort of order so that you know you added one of each of the 52 cards. The particular order is up to you--all the Aces, then all the 2s, etc; or all of one suit and then all of the next suit.

The first Deck constructor allows the user of your code to ask for a deck either with or without shuffling. Most of the time, they'll probably want it shuffled though, so the second constructor makes the deck a little easier to use. [Hint: Writing the second constructor is very simple if you remember how to call one constructor from another.]

For the draw() method, we don't want the Deck to crash if some programmer accidentally tries to draw a card from an empty deck. There's not much we can do in this situation though--either document what exception the method will throw in this situation, or else return null. For this implementation, I chose the latter approach.

For the shuffle() method, check out the Fisher-Yates algorithm for a relatively easy, but efficient and effective shuffling method. (It's easiest to make sense of the algorithm by looking at the pen and pencil examples. Again, you may use code you find here only if you cite where you got it! And, once again, you'll probably need to modify the code a bit, since you won't always be shuffling a full deck.)

You may write additional methods if you desire--such as a toString() method--but only those listed above are required.

Sample Output

Depends on how much you want to test your Deck at this point.

What to Submit

Hang onto this file for now--you're not going to submit it until after you finish A17-Part 3.

Grading

See A17-Part 3.

FAQs

So, although we can create Joker playing cards, there aren't actually going to be any in the Deck?
That is correct. Mostly, the Joker was a nice clean way to handle invalid arguments to the PlayingCard constructor (since we haven't learned how to throw exceptions yet, only catch them). It is true that, for certain games, someone might actually want Jokers included in a new deck. So we could provide a third constructor: Deck(boolean shuffled, int jokers), which would allow someone to specify exactly how many jokers they want added (since sometimes you only want one, not two). But this extra code is not really necessary at this point.
How do I know if my Deck was constructed correctly?
Probably the easiest way is to temporarily print out the contents of the array or ArrayList that contains all the Deck's cards at the end of the constructor. This will verify that the constructor did its job.

If you used an array, you'll either need to use a for loop or else figure out how java.util.Arrays.toString(Object[]) works. If you used an ArrayList instance variable and named it cards, you can simply add this line as the last line of the Deck constructor:

  System.out.println(cards);

(As with printing any object, this println statement actually invokes the ArrayList's toString() method, which in turn will invoke your PlayingCard's toString() method to print each card in the list.)

Remember this printing is just for debugging purposes to see if your constructor worked. Once you're done testing, remove it!

Shuffling tips
There is a shuffle method in the API that might be handy. See java.util.Collections. (You'll have to understand inheritance and interfaces to truly understand how you can pass an ArrayList to this method, however.)

On the other hand, if you are going to try implementing the Fisher-Yates algorithm given above, note that you will have to change the code given in a number of ways:

  • First of all, the code given is for a static method that sorts a full array of ints:
        public static void shuffle(int[] array)
    
    Your shuffle method must instead be an instance method that takes no parameters:
        public void shuffle()
    
    (Note that you may overload the shuffle method--that is, define more than one shuffle method with different parameter lists--if you want to. So you could have a version of the shuffle method that takes an array or ArrayList. However, this is unnecessary and you are still required to have the version that takes nothing.)
  • You don't need to pass any parameters to the shuffle method because you already have an instance variable (either an ArrayList or array) that contains all the cards. Basically, instead of shuffling array, you'll be shuffling cards.
  • You're shuffling PlayingCards, not ints.
  • If your cards variable is a PlayingCard[]: there's not much code you need to change. Just remember that you may not always be shuffling a full deck! So don't shuffle up to cards.length, but only up to the number of cards currently in the deck.
  • If your cards variable is an ArrayList<PlayingCard>: You'll have to rewrite the algorithm to use ArrayList methods instead of array subscripts. For example, this line:
        int tmp = array[k];
    
    gets the element (an int) from index k in the array and stores it into a temp variable. You would need to change this to something like:
        PlayingCard temp = cards.get(k);
    
    Similarly, the line:
        array[n] = tmp;
    
    (which changes the value of the element at index n to tmp) would become:
        cards.set(n, temp);
    
    (I didn't talk about the set method in lab, but you can learn more about it in the API.)
According to that Wikipedia page, Java is probably only going to be able to provide a subset of all possible deck permutations. Is this okay?
Yeah, that's fine. If you're really worried, I suppose you could have your shuffle method actually shuffle the deck multiple times, but it's not required.
On to A17, Part 3 →


~ztomasze Index : TA Details: ICS111: A17-2
http://www2.hawaii.edu/~ztomasze
Last Edited: 09 Nov 2009
©2009 by Z. Tomaszewski.