CS 101 (Fall 2002)
Lab 7b: Stacking the Deck (Part 2)

Authors: Nate Bayless and Sergey Klibanov
Lab Assigned Design Due
(In class)
10 AM
Implement
(In Lab)
Demo
(In Lab)
Lab Due
(In class)
Friday
10 AM
28 Oct None 29-30 Oct 5-6 Nov 8 Nov


Overview:

We will extend the work we did in the last lab to create a deck and a hand of cards.

Goals:

By the end of this lab, you should

Before starting:

Replace the Startup.java file you had from last lab with the one below:
  1. Problem Statement

    This lab is the second of a multiweek sequence that will culminate in the creation of a working card game.

    You have implemented a StackOfCards, which we will now use to implement a Deck.

    In fact, the Deck is-a StackOfCards, but with some extra functionality. So this will be our first time for creating one class by extenidng another: Deck extends StackOfCards in this lab.
  2. Design

    You will need to create your own .java files for the classes that we have not provided. You will probably also need to make your own Startup.java to test your code, but you will not need to turn that file in. All grading will be done with the provided Startup.java file.

    All methods below are public. You may not add other public methods. All methods you add must be private. You are encouraged to add private methods where you see fit. **See the JavaDoc for the same information presented differently**

    1. In order to have a card game at all, we must have the Deck class, which you must complete according to the API below. The Deck is an abstract data type, so as with StackOfCards, it can be implemented in many ways. Our implementation of the Deck will extend StackOfCards.
      Deck must have the following methods:
      Constructor(s)
      Deck()
      Creates a regular 52-card deck, not randomized.
      Accessors
      int getSize()
      Returns the number of cards currently in the deck.
      Card getTop()
      Returns (does not delete) the top card on the deck -- equivalent to Card peek() in StackOfCards.
      Card getBottom()
      Returns (does not delete) the bottom card.
      Card getNthFromTop(int n)
      Returns (does not delete) the nth card from the top of the deck. The top card is 0th from top.
      Mutators
      Some mutators may modify the number of cards in the deck. The value returned by int getSize() must be updated in this case.
      void push(Card c)
      Overrides the push method in StackOfCards. The Deck keeps track of the number of cards it contains, while StackOfCards does not. This method should appropriately adjust the value to be returned by getSize(), as well as performing the push() from StackOfCards.
      Card pop()
      Overrides the pop method in StackOfCards. Look at void push(Card c) for more detail on method function.
      Card removeTop()
      Equivalent to Card pop()
      Card removeBottom()
      Returns and deletes from the deck the bottom card
      Card removeNthFromTop(int n)
      Returns and deletes from the deck the nth card from the top. The top card is 0th from the top.
      void perfectShuffle()
      Performs one pass of the Perfect Shuffle algorithm. This works as follows: The deck is split into two equal halves, then reconstructed by interleaving the two halves. Specifically, the deck is cut equally into two halves. One card is taken from the first half (the half that used to be on top of the deck) and pushed onto the deck, then one is taken from the second half and pushed on, then one from the first and so on until the deck is fully reconstructed. About twenty passes of this This approach to shuffling will not randomize the deck. In fact, after a computable number of perfect shuffles, the deck will return to its original order! Even more specifically, let's assume the deck holds cards (3, 4, 5, 6, 7, 8). The first half would contain (3, 4, 5) and the second half would contain (6, 7, 8) in that order. Then a 3 would be taken from the first half, and pushed onto the now-empty deck. Then the 6 would be chosen. The final product should be a deck that holds (8, 5, 7, 4, 6, 3). If the number of cards is odd, let the second half contain the extra card.
      void selectionShuffle()
      Performs one pass of the "Selection Shuffle" algorithm, which works as follows: A random card is chosen and removed from the deck. This card is placed on top of the deck. Another randomly chosen card, but one that has not yet been touched by the algorithm, is removed and placed on top. This process is run until all cards have been touched by the algorithm. The result is a fairly randomized deck.

      While writing your code, consider carefully what methods Deck inherited from StackOfCards. These include push and pop which have been overridden. Other inherited methods are Card peek(), boolean isEmpty(), String toString. As with Card, for grading purposes, we will constrain your implementation of the Deck. When the deck is constructed, the cards in it must be in the following order, from the top of the stack down: Ace of Spades, Ace of Hearts, Ace of Diamonds, Ace of Clubs, King of Spades, Hearts, Diamonds, Clubs, etc. The bottom 4 cards should be Two of Spades, Two of Hearts, Two of Diamonds, Two of Clubs.

    2. The last item that is essential to any card game is a Hand. It is the hand of cards that is actually used to play the game, and not user as a source of cards (like the Deck is). Our Hand class has-a ListOfCards that keeps track of all the Card objects currently in the hand. Here's the API for Hand:
      Constructor(s)
      Hand()
      creates an empty Hand with an empty DrawingPane and ListOfCards. Cards in the hand are invisible (face down) by default.
      Accessors
      DrawingPane getDrawingPane()
      returns the DrawingPane on which the Hand draws itself.
      int getSize()
      returns how many cards are in the hand.
      boolean isEmpty()
      Returns whether or not the hand is empty (has 0 cards)
      boolean isVisible()
      Returns whether or not the cards in the hand are visible (face up)
      Card getCard(int n)
      Returns the nth card in the hand. 0 is the first card.
      Mutators
      void add(Card c)
      adds the specified Card to the Hand. This constitutes adding both to the ListOfCards and to the Hand's DrawingPane. More recently added cards go to the end of the hand.
      void remove(Card c)
      removes the specified Card from the Hand and the Card's PictureComponent the DrawingPane. Prints an error message if the card is not in the hand or if the hand is empty.
      Card remove(int n)
      Removes the nth card in the hand. 0 is the first card.
      void setVisible(boolean visible)
      sets each Card's visibility to the specified visibility.
      void clear()
      Removes all images from the Hand's DrawingPane and empties its ListOfCards.
      void sort()
      sorts the Hand by rank (i.e. from high to low, with Aces high). Changes in order are reflected both visually and internally.

      This method is worth 5 lab points of extra credit. It is tested from Startup, so you must include at least a stub for this method if not the actual implementation.

      Other method(s)
      String toString()
      Prints out all the cards in the hand. Same format as specified above, using parentheses and commas.

    3. Finally, you will need the Startup class to demonstrate that your classes work. To ease grading, this class is provided for you. Ideally, the transcript generated by the reference implementation and your code will be identical. You should not, however, rely solely on our Startup code entirely during your own testing. After, for example, you finish the Card class, you should make completely sure that it works as expected before moving on.
      Constructor(s)
      Startup()
      Creates a Startup object which tests the other classes in this lab.

    Implementation

    Read the following carefully, and be sure to complete all parts below.

    1. You must implement the classes described in the design. For this lab, you are constrained to following this design. Specific implementation steps are given at the end of this document.
    2. Do not expect the given Startup.java file to compile until you are finished with the lab.
    3. Once you have the Startup.java file compiling, compare the behavior of your implementation with the behavior of the reference implemenation. Any output that does not use the selectionShuffle method should be *exactly* the same between the two implementations.

What to turn in:

  1. Complete a code cover sheet.
  2. Provide a printout of any files you have modified (see approach below).
  3. Provide the transcript from the tests on Deck and Hand generated by the given Startup.java

Suggested implementation approach:

  1. Implement Deck.
  2. Implement Hand

Test as you go. The wrong approach is to write all of one class, then to try to get it to compile, and then to try to get it to work, in three separate stages. The correct way is to write your code in one-method increments, testing as you go.

Good Luck!



Last modified 21:16:37 CST 31 October 2002 by Ron K. Cytron