-
Calculation Solitaire
source: Katrin Becker, 2000
- The course directory /home/233/Solitaire contains a number of files that may be of some help or use:
- StackStuff.cc
- StackStuff.h
- SetTestDeck.cc
- SetTestDeck.h
- Random.cc
- Random.h
- CheckMoves.o // checking and doing the moves
- CheckMoves.h
- Cards.o // the basic cards functions
- Cards.h
-
- Mymakefile (the one I used)
- makefile (one you could use)
-
- TEST (sample "input" [requests] for the stacked deck)
-
- sample_run.txt
-
- Calculation
- Making Use of the Given Code:
- You may use the above code as you wish. Suggestion: use them all initially (check the ".h" to see what globals they use). Once it's running, replace your function calls to my code with calls to your own functions one at a time.
- If you use this approach, here's what you'll have to replace:
- For a "C":
- the basic card functions, including "shuffle"
- "move", but yours doesn't need to check for a valid move
- For a "B":
- "sourceOK" (yours doesn't need to be organized like mine)
- "destOK"
- move functionality from "move"
- Checking for invalid moves: make sure that # for F / W is 1 2 3 4
- Bad Piles: make sure source is H / W (W only allowed if source = H)
- Detects win: simplest: hand empty and score = 52
- Re-deal is easy if initial set-up is done by a function call - then re-deal is simply another call to the same function.
- For an "A":
- "move" (full functionality) (yours doesn't need to be organized like mine)
- "OKforFoundation"
- Illegal moves: if source = H dest must = W / F; if source = W dest must = F
- Legal moves onto foundations:
- F1: next rank (any suit)
- F2: rank + 2 (any suit) *
- F3: rank + 3 (any suit) *
- F4: rank + 4 (any suit) *
- Note that F2 - F4 must allow a wrap-around, so : (new card's rank + N) % 13, where N = # of foundation
- "Game Over":
- hand must be empty or have only one card left
- If none of the top cards in H or W can be moved to any foundations the game is blocked.
- While working on your code:
- Get a "C" version running and save it.
- Work on a copy of your "C" version to implement the "B" stuff.
- Once that is working you can discard the "C" version; copy the "B" version and continue on with the "A"version stuff. This way, if you don't get the last part working, you can still hand in the previous, working version along with the non-working one. If you make some attempt to explain the problem on the latest version you can still get partial marks for that.
- Approach:
- This program is probably the biggest and most complicated most of you have attempted to date. If you break it up into parts properly, each part is much less complicated.
- START EARLY. The keys to the successful completion of this assignment are:
- Understanding the Problem: The assignment page contains, among other things, a link to a website that allows you to play the game of Calculation Solitaire. The display differs from our version, but because it is so much easier to get an understanding of the game from one with reasonable graphics (ours will be very crude by comparison), it is strongly recommended that you take some time to familiarize yourself with the game (it's not often you will be assigned to play solitaire as homework!!). Once you have learned how the game is played, try running the sample solution (./Calculation) in the course directory. The "display" is harder to follow so knowing how the game is played beforehand will help.
-
- Outlining the Solution: This program is complicated enough that it will be necessary to break it up into smaller, fairly self-contained tasks (such as "doing the display", "initializing a game", "doing one move", etc.). You must use stacks for the piles of cards, and with the exception of the routine(s) to do the display you are restricted to using only the pre-defined allowable stack operations. There are a number of modules that can be used by your program.
- StackStuff.cc and StackStuff.h contain the stack operations as discussed in class.
- Random.h and Random.cc is the usual random number routine (there's PC stuff left in but commented out). This version also contains a call to set the seed so all the "random" and "time" stuff is in one module.
- SetTestDeck.h and SetTestDeck.cc which contain routines to "stack the deck". The series of moves listed in the file called TEST work with this Hand and will run the game to a winning state.
-
- Cards.o and Cards.h contain some miscellaneous routines for converting between numbers (0-51) and cards (CA-HK), as well as routine to shuffle the deck.
- CheckMoves.o and CheckMoves.h contain one major routine that processes a request to move one card from one of the piles to another.
- move ( char source, char dest, int sn, int dn );
- - it uses a number of GLOBAL variables (the stacks primarily)
- - source will be a character identifying the pile we want to move a card FROM and dest is a character identifying the pile we want to move the card TO. Wastepiles and Foundations are implemented as arrays of stacks so if they are the source/dest, then a number is required (sn, dn, in the range 0-3) to identify which tableau or destination.
- - you are not required to use this routine; you are free to use it only as a guide or ignore it altogether.
- - you have access only to the executables (for Cards and CheckMoves) - the idea is to use these routines at first but replace them with your own later.
-
- SetTestDeck : Usually the deck is to be shuffled randomly at the beginning of every game. This causes several problems in testing. One of them is that it becomes difficult to test the various parts of your program. The other is that you may end up playing for a long time before you find a hand that will win. To get around these problems a function has been provided that you can use to initialize the hand instead of using a random hand. It is the one shown in sample_run.txt. It tests just about everything and will run to completion. In the sample solution you may request the test hand by typing z . Notice that z is not one of the game options. It is a "hidden feature" known only to us and used for testing purposes. Realize that most hands of Solitaire are non-deterministic, meaning there's almost always more than one way to get from the beginning to an end. Not all ways result in a win.
-
- Lastly, the course directory contains the makefile used by the instructor in her sample solution. You may use it as you see fit.
-
- Except for the stack, random number and test-deck functions, this program may consist of just one module.
- Additional Help:
- Implementing the Solution Piecemeal:
- As you outline the tasks (functions) you will need, decide on the bare minimum to get a running program (for example, maybe just the display, and main) as each task is solved
- Compile and test it. That way the amount of untested code in your program will remain at a minimum.
-
- Here are some of the tasks your program will need to perform:
- Display: print out the "game":
Foundation 1: Ace 2 3 4 5 6 7 8 9 T J Q K
Foundation 2: 2 4 6 8 T Q Ace 3 5 7 9 J K
Foundation 3: 3 6 9 Q 2 5 8 J Ace 4 7 T K
Foundation 4: 4 8 Q 3 7 J 2 6 T Ace 5 9 K
>> SCORE: 11
Hand: H5 1 2 3 4
-- -- -- --
CA C2 D5 CQ :: FOUNDATIONS
------------------------------
Left: 30 :: WASTE PILES
SK HT ST D9
HQ D8 C5 DJ
S9 H6
S6
Options:
P: play new game
M: move <s> <s#> <d> <d#>
D: deal
H: help
Q: quit
Request:
- Note that only the top cards of the foundations and the hand need to be displayed while all the cards in the wastepiles are shown.
- Main Play "Loop":
- can be in "main"
- gets the request and calls the appropriate function
- make sure to implement the "quit" function early
- Help Option:
- Example:
- Request: h
CALCULATION SOLITAIRE
This variation of Solitaire is a relatively simple one.
Layout - The hand is shuffled and the first card for
each foundation is placed as it is found.
Initial foundation cards are as follows:
F1: Ace, F2: 2, F3: 3, F4: 4
Rank is unimportant in this game.
Foundations - As they become available, move cards to the
foundations in the following order:
F1: 2,3,4,5,6,7,8,9,T,J,Q,K
F2: 4,6,8,T,Q,A,3,5,7,9,J,K
F3: 6,9,Q,2,5,8,J,A,4,7,T.K
F4: 8,Q,3,7,J,2,6,T,A,5,9,K
Rank is unimportant
Hit Any Key to continue.
Play - Wastepiles can be used as temporary locations for cards
but once placed on a wastepile, a card can ONLY be moved
to a foundation.
Cards can only be moved one at a time.
Empty Wastepiles can only be filled from the Hand.
The card in the Hand MUST be played before the next
deal can proceed.
The card in the Hand may be moved to any wastepile or to
a foundation if appropriate.
Redeal - There is no re-deal in this game.
command: p === Play (i.e. start again);
command: m <s> <s#> <d> <d#>
=== Move a card from source <s> to destination <d>;
Source may be H / W
If source is W, destination MUST be F
NOTE: <s> and <d> refer to one of the
waste piles piles (numbered 1-4)
command: d === Deal (deal the next 3 cards);
command: h === Help (display the rules);
command: q === Quit (end game);
Hit Any Key to continue.
- Play:
- shuffle the deck
- deal a new game (hint: this is easiest if you simply deal the first 4 cards of a sorted deck (Clubs A, 2, 3, 4) onto the foundations, then push the remaining cards in order onto the hand and shuffle those (there will be 48 cards)
-
- Get a request from the user
-
- Process a Move:
- Legal moves are:
- m h f # // where # is 1-4
- m w # f # // where # is 1-4
- m h w # // where # is 1-4
- Don't worry about checking legal options right away. First make sure the cards get moved as requested.
-
- The Test File:
-
- The file called: TEST contains a series of Calculation requests that can be used to test a program. the sequence of requests works with Becker's sample solution and may not work with yours without being edited.
These can be used as follows:
./Calculation < TEST
TEST contains only requests, it is not a shell script.
If you wish to make your own:
1. run a typescript of you playing the game to completion (type carefully)
script run1
etc.
2. you may need to run the typescript through dos2unix
dos2unix run1 run1
3. to pull out only the requests from the file, try this:
grep Request: run1 > out1
where "Request:" is the string you print when asking for user input (this assumes user input similar to Becker's with no additional questions). GREP is a VERY handy utility - look it up in your Solaris or UNIX book.
4. then in emacs edit out1 using regular expression search and replace:
match the beginnings of the lines something like this:
/^ *Request: /
The string to replace is the stuff between the slashes;
^ matches beginning of line
/ */ (blank-star) matches one or more blanks in a row
Request: matches the word "Request:"
if you ask to replace it with <nothing> (just hit return) emacs
will take those strings out for you, leaving just the stuff the user
typed in.
If you want to avoid having to say 'y' dozens of times for each
replacement, simply type '!' instead of 'y'. It means replace-all
These are the steps I went through to 'convert' sample_run.txt into TEST.