## 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
• Understand how to use subclassing to specify finer levels control and add functionality to existing classes
• Understand the rudiments of inheritance
• Be able to allocate and use one-dimensional arrays

### Before starting:

• Read over this entire document before you start.
• Study the examples in class and in the notes.
• Run the sample solution.
• If you need help, please ask.
[[[ 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.

• A card in the tableau (and all cards below it) can be placed on top of another if its rank is one less than that of the card on top of the pile and its suit is an alternate color.
• A card may be played directly to the foundations if it has no cards below it and is the next card in some foundation.

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 `ShirtFactory`Lab 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