Spring 2001 CS100M Project P7: FreeCell due 11:59pm, Thursday, May 3 Implement a text version of the FreeCell solitaire game. Submit your code online. =============================================================================== Cards =============================================================================== Jokers are not used. A card has 3 attributes: 1. color = red or black 2. suit = clubs, diamonds, hearts, or spades 3. value = Ace, 2, 3, 4, 5, 6, 7, 8, 9, Ten, Jack, Queen, King (we want single-character abbreviations for this project, so we use $T$ for Ten instead of $10$) A standard deck of 52 cards consists of: 13 black clubs : AC 2C 3C 4C 5C 6C 7C 8C 9C TC JC QC KC 13 red diamonds : AD 2D 3D 4D 5D 6D 7D 8D 9D TD JD QD KD 13 red hearts : AH 2H 3H 4H 5H 6H 7H 8H 9H TH JH QH KH 13 black spades : AS 2S 3S 4S 5S 6S 7S 8S 9S TS JS QS KS Observe that the color of a card can be determined from its suit. =============================================================================== Piles =============================================================================== Cards can only be moved in certain stylized ways in solitaire. Let us say that a "pile" (of cards): + is a "stack" of 0 or more cards. + only the card on the "bottom" of a stack can be removed + a new card can be added only on the bottom of a stack Example: here is a stack with 3 cards: QC <-- top card: queen of clubs TH <-- ten of hearts 3H <-- bottom card: 3 of hearts The only card that is allowed to be removed is the bottom card 3H, which would yield a stack with 2 cards: QC <-- top card: queen of clubs TH <-- bottom card: ten of hearts If we then wish to add the card KS, we must put it at the bottom, yielding a stack with 3 cards: QC <-- top card: queen of clubs TH <-- ten of hearts KS <-- bottom card: king of spades =============================================================================== FreeCell Rules =============================================================================== There are three different kinds of places where cards can be: 1. 8 Columns 2. 4 Home Cells 3. 4 Free Cells Each free cell is a pile of at most 1 card: it is either empty or holds a single card. Each home cell is a pile of at most 13 cards of the same suit, with values in increasing order starting from Ace at the top of the pile, and cards may not be removed from a home cell: once a card is added, is it never taken away. Each column is a pile of cards with 2 more restrictions on adding a new card to a non-empty column: 1. the new card's value must be the predecessor of the bottom card's value. 2. the new card's color must be different from the bottom card's color. For example, if we want to add a red 3 of diamonds to a column, then the column must be empty or the bottom card must be a black 4 of clubs or spades. Objective: move all cards to the home cells using only legal moves. Starting a new game: + Each home cell is initially empty. + Each free cell is initially empty. + Each column is initially empty, and then cards from a standard deck are dealt one by one to each column in round-robin fashion until all cards have been dealt. Thus, 4 columns will each have 7 cards, and 4 columns will have 6 cards. (4*7 + 4*6 = 4*13 = 52.) Usually the deck is scrambled (shuffled) before cards are dealt. =============================================================================== What to do =============================================================================== use/modify classes $Card$ and $Pile$ to define a class $FreeCell$: + each instance (object) represents a game in progress of FreeCell (4 free cells, 4 home cells, 8 columns, and the cards therein) + each instance has appropriate methods for playing the game, e.g. performing one move + there should be a main method to create an instance and play a game of FreeCell you *must* let the user specify a move in the form $src dst$: + $src$ = where to move the card(s) from + $dst$ = where to move the card to + $src$, $dst$ can be + a 2-letter string representing a card (core: card must be at the bottom of a pile) (bonus: can be in the middle of the pile -- the card and all cards below it are moved) + $"f"$ for any empty free cell + $"h"$ for any empty home cell + $"c"$ for any empty column + ignore case user-interface + print a suit in upper case to signal "black" + print a suit in lower case to signal "red" + print the state of the game as shown below + print helpful error messages for illegal moves + detect when the game has been won -- print a message and stop running style + make appropriate use of $private$ + use encapsulation techniques to prevent (some) illegal actions + [5/01] make it easy to change the number of free cells and/or columns + [5/01] use arrays, methods, loops, and/or inheritance to reduce redundancy hints: + use instance method $String.equalsIgnoreCase$ to compare two strings ignoring case + use instance method $String.equals$ to compare two strings -- $==$ does NOT do what you expect! + use instance method $TokenReader.readString()$ to read a string from user input bonus: + implement "macro moves" that move partial columns by using a sequence of legal single-card moves + detect if the game cannot be won (this is *not* easy) + create a window with the game shown graphically, using colors (see CUCSApplication.java for sample code)