CS 101 (Spring 2000)
Lab 8: Subclassing: CloneLike Solitaire

Lab Assigned
Design Due
(In class)

10 AM
Implement
(In Lab)
Demo
(In Lab)
Lab Due
(In class)
Friday
10 AM
20 Mar None 21-22 Mar 28-29 Mar 31 Mar


Goals:

By the end of this lab, you should

Before starting:

[[[ Download PC zip ]]]

Zip includes: Zip does not include files from Lab 7: You have to copy your solution for those classes into your Lab 8 working directory. Or if you want my .class files for solution, unzip this

  1. Problem Statement

    This lab is the second of a two-week sequence that culminates in the creation of a working game of CloneLike Solitaire, one of the most famous one-person card games. It is the same Solitaire game that comes with the Windows operating system. For a demonstration of how the game is supposed to work, please run the Solitaire game on any Windows system, or run our sample solution.

    Now that we have successfully created our CardPile, we will use it to implement a much larger system consisting of many card piles. These card piles play different roles in the game. First, we'll look at how the game itself is played, and second, we'll look at how we might implement the game using what we have already.

    CloneLike Solitaire

    The object of the game is to divide all the cards into four piles in which all cards are of the same suit and the order of the cards is increasing by rank from top to bottom. These four piles are known as the foundations. They will appear to the right of the display for this game.

    The playing field, or tableau, consists of seven piles, increasing in size from left to right (by one card) and whose top (last) cards are turned right-side-up. The tableau will appear at the top display for this game.

    It is also important to note that foundations are built starting with the Aces, and a King may restart a tableau pile if all of its contents are transferred to other piles.

    When moves cannot be made in the current game state, one card is transferred from the face-down deck to the waste pile and turned right-side-up so it can be seen. This card may be played directly to the foundations or onto the tableau according to the rules described above. Once the deck expires, the waste pile may be turned over and reused. The game ends when all cards are transferred to the foundations, or no further moves can be made.


  2. Design

    To complete this lab you will need the APIs for Card and CardPile from the previous lab handout. The design below only describes the new classes for this lab. All methods below are public unless otherwise stated. Also, methods inherited from superclasses are not listed.

    1. The Deck class extends CardPile. In the extension, a Deck is considered to be either locked or unlocked.
      • The Deck should only be locked during actual gameplay.
      • When the deck is first generated, or when the deck is emptied and needs to be reconstituted by turning over the waste pile, the deck may be unlocked.
      Here is the API for Deck:
      Constructor(s)
      Deck()
      Constructs a complete 52-card American deck. The deck is locked after it is generated. All cards should be face down.
      Accessors
      boolean isLocked()
      Returns whether the lock has been set on this pile or not.
      boolean okToAdd(Card c)
      This overrides the okToAdd method of CardPile. Here, we return !isLocked() so that cards cannot be added once the deck is locked.
      Mutators
      void lock()
      Set the lock on this pile.
      void unlock()
      Unlock this pile.
      Other methods
      None.

    2. The Foundation class describes a foundation pile, upon which sequences of same-suit cards starting with Ace and going to King in rank order are built. The class should also extend CardPile.
      Constructor(s)
      Foundation()
      Constructs an empty Foundation pile.
      Accessors
      boolean okToAdd(Card c)
      This should return true if any one of the following is true:
      • This Foundation is empty and the Card passed in is an Ace.
      • This Foundation is not empty and the Card passed in is the rank successor of the card on top of this Foundation and is of the same suit.
      Mutators
      None.
      Other methods
      None.

    3. The Tableau class represents a single pile in the playing field.
      Constructor(s)
      Tableau()
      This should create an empty Tableau.
      Accessors
      boolean okToAdd(Card c)
      This should return true if any one of the following is true:
      • The Card c is not visible. This facilitates initialization of the Tableanu, since some cards are placed therein face-down.
      • This Tableau is empty and the Card passed in is a King.
      • This Tableau is not empty and the Card passed in is a rank predecessor of the topmost card on this Tableau, and is of the alternate suit.
      • This Tableau is not empty, and the topmost card on the Tableau is not visible.
      Mutators
      None.
      Other methods
      None.

    4. The Klondike class is the meat of the game. You will use the rules and classes described above to create a working game of Klondike.

      In many respects, the accessor methods resemble those used in classes in Lab 3, where you had n varieties of a given type of object. For example, in ShirtFactoryLab 3, the method getFabricLeft(int fabricNumber) conditionally determined what to return, based on the supplied fabricNumber. The use of if statements to accomplish this is tedious, and so we introduce the concepts of arrays to simplify matters.

      Constructor(s)
      Klondike()
      Generates a deck (as a Deck object), a waste pile (as a CardPile object), four foundations (as Foundation objects), and seven tableau piles (as Tableau objects). It should then shuffle the deck and deal out the seven Tableaux as described in the rules and demonstrated in the sample solution.
      Accessor(s)
      Deck getDeck()
      Return the deck this Klondike is using.
      CardPile getWaste()
      Return the waste pile in this Klondike.
      Foundation getFoundation(int which)
      Return the indicated foundation pile in this Klondike. Assume they are numbered from 0-3, and feel free to throw an Error if the foundation requested is out of range.
      Tableau getTableau(int which)
      Return the indicated tableau pile in this Klondike. Assume they are numbered from 0-6, and feel free to throw an Error if the tableau requested is out of range.
      Mutator(s)
      boolean drawCardFromDeck()
      Transfers the top card of the deck to the top of the waste pile, making it face-up in the process. Returns false if the deck is empty.
      boolean moveCard(Card c, CardPile source, CardPile destination)
      Should transfer the portion of the source pile from c to the source's top to the destination pile. This method must obey the rules of Klondike. Returns false if no legal move can be made.

      This method is easy to write if you depend on the destination's implementation of okToAdd. You will be graded on the elegance of this method.

      void resetGame()
      Should regenerate the deck, empty the waste and foundations, and redeal the Tableau piles. Hint: call this method from the Klondike constructor; don't duplicate its function.
      void cycleDeck()
      This flips the cards in the waste CardPile, and then transfers them to the deck.
      void autoPlay()
      This method is worth 10 points extra credit. This method should play any cards currently in the Tableau that can be played to the foundations to the foundations. You should be careful to continue to try to autoplay until no moves can be made, because sometimes one round of autoplay results in another possible round of autoplay.
      Other method(s)
      String toString()
      Returns a String reflecting the status of each of the piles in the game.

  3. 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; the files you download repeat those suggestions.

    2. Be sure to test carefully. Use the toString() in Klondike to be sure that you are getting the results you want. Be sure to turn in a transcript of your tests and a sample program execution. Poor testing will adversely affect your code grade.

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 transcript(s) from tests and runs of Klondike.

Suggested implementation approach:

Remember to test as you go, using text-based tests in Startup.

  1. Implement Foundation.
  2. Implement Deck.
  3. Implement Tableau.
  4. Implement Klondike one method at a time. The order in which the methods are listed is the suggested order of implementation. Write some test procedures in Startup using the provided KlondikeViewer class to be sure that your class works. Test as you go -- don't write the whole class and then try to test it. Test in one-method increments.


Last modified 11:09:20 CST 27 March 2000 by Ron K. Cytron