CS 340 - Software Design
Machine Problem 2, Fall 2001
Gin Rummy
Due: Thursday, September 20, 2001 at 11:59 pm
For this program, you will write a program that will allow
the user to play the game of Gin Rummy against a computer
opponent. We will use the rules as written in
this link as
the official rules to be followed with one expection. The
expection will be that we will use the variation to starting
the game (i.e. the first card drawn) as described in the first paragraph of the
variations section
instead of what is described in the last paragraph in the
Play section. This change should allow for simpler agorithms to be
used.
In this program, you must use multiple source code files and you
may not use a C style struct in your code.
A good way to divide your program into multiple source code files
is according to the logical use of the code. One way to divide
the code for this program could be into three source code files.
The first source code file could contain the main() function and
all functions relating to input and output (i.e. the user commands).
The second source code file could contain the code for keeping track
of the cards, sets and hands used by the players. The third source
code file could contain the code to evalaute the hands, determine the
scoring and the algorithm used by the computer player to decide what
it should do.
With regard to the restriction on C style stucts, the following
C++ class is acceptable, even though it is semantically the
same as a C style struct:
class MyClass
{
public:
// list of all needed fields
};
In playing gin rummy, there are multiple parts. The first part
is the game. The second part is the hand. One
or more hands make up a game. The
third part is the turn. One or more turns make up a
hand. These three parts will of concern
in our program. Addition parts in gin rummy consist of
tournaments, which is made up of one or more games, will
not be a part of this program.
Your program will have three different set of user commands. One
set of commands that are valid between the playing of the hands
in a game (inter-hand commands) and
other sets of commands that are valid during the playing of the
hands (intra-hand commands). One set of these intra-hand commands will deal with
commands used when drawing a card during a turn. The other set
of these intra-hand commands will deal with the commands used
when discarding a card during a turn. Note that the three
sets of commands are not disjoint sets, about 75% of the
intra-hand commands will be in both sets.
Your program must prompt for the user commands and the prompt must
include something that informs the user which set of commands
are currently valid.
All commands will be
the first non-white space character on a line and can be given in
either upper or lower case. If an unrecognized command is given or
a command that is not properly formatted, an error message must be
printed and the command is ignored and your program is to prompt
for the next command.
The following commands are available at all times in
the program. These commands belong to all three sets of commands.
Q
-
Quit the program. If you are in the middle of a hand or
a game, prompt the user with this information and have them
comfirm whether they still wish to quit.
H
-
Display help about the program. This help should include
information about the three sets of commands and which set is the
current set of commands.
P
-
Display points scored by each player.
Refer to the
scoring section to determine the points scored. This command
should list the total points for each player and the number of points
needed to win the game. Note that gin rummy has a wierd scoring
technique that awards a 20 point bonus for each hand won, but these
bonus points do not count toward the winning of the game. Thus
the game can be won by the player who does not have the most
points.
The following commands are only valid in between hands being
played. These are the inter-hand commands.
S
-
Start a new game
This command resets all of the scoring information to zero and
randomly determines which player will deal first. When the
program initially starts, this should be automatically done
by the program without having to enter the S command. This
commands allows more hands to be played after a game has been
won where the points are added to the existing points of the
already finished game. This is useful it a player decides to
play to some other point value other than 100.
D
-
Deal a new hand
This command starts a new hand and initial deals out the cards.
This program is to use the variation in dealing as stated in the
first paragraph in the
variations section.
So the dealer is to deal 11 cards to the non-dealer and the
non-dealer just has to discard (or knock). The dealer is
randomly determined for the first hand in a game (see the S command)
and alternates during the game. After this command the intra-hand
set of commands are used until a player knocks or the stock pile
is reduced to two cards.
The following commands are valid at any time during intra-hand
play.
C
-
List the user's cards.
The cards are to be listed using a two character sequence
for each card. The first character is to specify the rank of the
card and the second character is to specify the suit. The
ranks and suits with the associated characters are given in the
table below. Use upper case letters when specifying cards.
Rank Characters |
Suit Characters |
-
A - Ace
-
2 - Two
-
3 - Three
-
4 - Four
-
5 - Five
-
6 - Six
-
7 - Seven
-
8 - Eight
-
9 - Nine
-
T - Ten
-
J - Jack
-
Q - Queen
-
K - King
|
-
C - Clubs
-
D - Diamonds
-
H - Hearts
-
S - Spades
|
Note that the ranks and suits are listed in order with Ace being
the low rank, King being the high rank, Clubs being the low suit and
Spades being the high suit.
The cards are to be listed by default in suit-major/rank-minor
sorted order from lowest to highest. This means that all clubs
are list first, then all diamonds, then all hearts and finally all
spades. Each suit is to have its cards listed in rank order with
the ace first and the king last. The cards can be arranged by
the user into sets using the O and A commands (see below). In this
case, list the sets in order indicated by the user with the
cards in each set being listed in suit-major/rank-minor order.
When the cards are listed there may be either 10 or 11 cards.
There will be 11 cards if the player has drawn a card during
a turn but not yet discarded a card. As the cards are listed,
each cards is associated with a number (from 1 to 10 or from 1
to 11 depending on the number of cards currently being held by
the player) and a letter (from a to z). The number is used to
sequentially number the cards as they are listed. The first card
list will have number 1, the second card listed will have
number 2, etc. This number is used specify individual cards for
other commands. The letters are used to specify sets of cards
as described in the
Object of the Game section.
The cards with the lowest set letter are listed first, followed
in order by the next lowest set letter. The default ordering
assumes that all cards are in the same "set" with the set letter
of a.
E
-
Peek at the Computer Player's Hand
This command is to display the computer players cards according
to the same rules as described in the C command.
This command is used to debug your program and allow the TA to
check if your algorithm for the computer player is functioning
correctly. The algorithm for the computer player is
as follows. The algorithm breaks down the cards into five
categories:
- Complete Sequences - 3 or more cards of the same suit in
consecutive rank. Remember that the Ace is always low and
the King is always high and that sequences cannot "wrap-around".
The following sequences are illegal.
- Complete Groups - 3 or more cards of the same rank (Obviously
from different suits since each of the 52 cards only appears once).
- Partial Groups - 2 cards of the same rank.
- Partial Sequences - 2 cards of the same suit in cosecutive rank.
- Deadwood - any cards that do not meet one of the first 4 categories.
The unmatched cards in a hand are all of the cards are in the last
3 categories (Partial Groups, Partial Sequences and Deadwood). The
value of the hand is the value of all of the unmatched cards in the
hand. Each card has a value as described in the
Deck section.
To arrange the computer player's hand into sets use the following
algorithm.
Note this algorithm may not work 100% correctly in all circumstances,
but it works pretty well in most circumstances. Your program MUST
use this algorithm. Any program not using this algorithm will
be considered as not functioning correctly.
- Find all complete sequences in the hand. Give each complete
sequence a different set letter. The set letters should
have the first set found be given the lowest set letter (i.e. a).
- Find all complete groups from the remaining cards in the hand.
Give each complete group a different set letter.
- Find all partial groups. Give each partial group its own
set letter. For each partial group starting with the partial
group with the highest rank, check if a complete sequence exists
that uses the rank of the partial group. If such a sequence
exists, detemine if "breaking the sequence" will result in
a lower value of unmatched cards than the value of the two cards
in the partial group. Remember that a complete sequence of 4 or
more cards could be "broken" and still result in a complete
sequence. Also a sequence of 7 or more cards could be
broken and result in two complete sequences.
- Example One: Assume the complete sequence of 4C 5C 6C exists
and the partial group of 6H 6S is found. The value of the partial
group is 12 (6+6). If the 6C is broken from the sequence, the
value of the "broken sequence" is 9 (4+5). Since 9 is less than 12,
the sequence should be broken.
- Example Two: Assume the complete sequence of 4C 5C 6C exists
and the partial group of 4H 4S is found. The value of the partial
group is 8 (4+4). If the 4C is broken from the sequence, the
value of the "broken sequence" is 11 (5+6). Since 11 is not less than 8,
the sequence should not be broken.
- Example Three: Assume the complete sequence of 4C 5C 6C exists
and the partial group of 5H 5S is found. The value of the partial
group is 10 (5+5). If the 5C is broken from the sequence, the
value of the "broken sequence" is 10 (4+6). Since 10 is equal to 10,
the sequence could be broken or not, this is up to you. You could
always break the sequence, never break the sequence or randomlly
decide to break it or not (I assume the easiest is not to break
the sequence).
- Example Four: Assume the complete sequence of 3C 4C 5C 6C exists
and the partial group of 6H 6S is found. The "broken sequence"
still results in complete sequence of 3C 4C 5C. So the value
of the "broken sequence" is 0. Since 0 is less than 12,
the sequence should be broken.
- Example Five: Assume the complete sequence of 3C 4C 5C 6C 7C 8C 9C exists
and the partial group of 6H 6S is found. The "broken sequence"
results in two complete sequences of 3C 4C 5C and 7C 8C 9C. So the value
of the "broken sequence" is 0. Since 0 is less than 12,
the sequence should be broken.
- Example Six: Assume the complete sequence of 3C 4C 5C 6C 7C exists
and the partial group of 6H 6S is found. The "broken sequence"
results in one complete sequence of 3C 4C 5C and the unmatched card of 7C.
So the value of the "broken sequence" is 7. Since 7 is less than 12,
the sequence should be broken.
- Example Seven: Assume the complete sequence of 3C 4C 5C 6C 7C 8C exists
and the partial group of 6H 6S is found. The "broken sequence"
results in one complete sequence of 3C 4C 5C and the unmatched cards of 7C and 8C.
So the value of the "broken sequence" is 15. Since 15 is not less than 12,
the sequence should not be broken.
Note: the set letters may have to be modified to deal with the
broken sequences.
- Find all partial sequences. Give each partial sequence its own
set letter. Since all complete sequences were found before any
complete groups, we will not have to worry about breaking any complete
groups.
- Find all deadwood cards. Any card that is not in one of the first
four categories is a deadwork card. The deadwoods can be combined
into one set with a single set letter or each deadwood card can be
given its own set letter.
To determine the value of the computer player's hand, sum the
value of all unmatched cards.
To determine if the computer player should draw from the top
card in the discard pile or draw the top card
in the stock pile, use the following algorithm.
- First check if the top card in the discard pile can be added to any
partial sequence or partial group, if so take the card from the
discard pile.
- Else check if the top card in the discard pile can be added to
any complete sequence or complete group, if so take the card from the
discard pile.
- Else check if the top card in the discard pile can convert a
deadwood card into a partial sequence or a partial group AND there
exists more than one deadwood card in the hand, if so take the card from the
discard pile.
- Else take the top card from the stock pile.
To determine the card to discard or knock with,
- if deadwood cards exist, select the deadwood card with the highest
point value.
- else if partial sequences or partial groups exist, select the card
from all of the partial sets with the highest point value.
- else if complete sequences of 4 or more cards exist, select the
card from a complete sequence with 4 or more cards with the highest
point value.
- else select a card from a complete group of 4 cards. It does not
matter which card from a 4 card complete group is selected.
Once the card to discard or knock with is selected, the computer
player must determine whether it will discard or knock. If the
hand value (not counting of the card selected to discard) is
ten points or less, the computer player will knock ending the
current hand and returning the program to inter-hand commands
once the points for the hand have been determined.
O
-
Organize the user player's hand.
Use the same algorithm as described above for the computer player's
hand on the user player's hand.
A <int> <letter>
-
Arrange the user player's hand according to the information given.
The <int> in the command is used to specify which card is being
"arranged". The <letter> in the command is used to specify which
set letter the card is being assigned. The <int> value is to
correspond to the positions used the last time the user's hand was
displayed. Everytime the user's hand is displayed it MUST follow the
algorithm as described in the C command.
The following commands are intra-hand commands that are used to
draw a card. These commands can only be used during the playing of a
hand, it is currently the user's turn and the user only has
10 cards in his/her hand.
S
-
Draw a card from the Stock pile
The top card from the stock pile is taken and added to the user's
hand.
T
-
Draw the top card from the Discard Pile.
The top card from the discard pile is taken and added to the user's
hand.
The following commands are intra-hand commands that are used to
discard a card. These commands can only be used during the playing
of a hand, it is currently the user's turn and the user has 11
cards in his/her hand.
D <int>
-
Discard the Indicated card.
The <int> in the command is used to specify which command is
to be discarded. The <int> value is to correspond to the positions
used the last time the user's hand was displayed. Everytime the user's
hand is displayed it MUST follow the algorithm as described in the C command.
Once the user has discarded, the computer player's turn immediate
take place with no interaction from the user. The user will see two
messages printed out during the computer player's turn. The first message
is whether the computer player drew a card from the stock pile or
from the discard pile. The second message is whether the computer
player discarded or knocked to end it turn. If the computer player
discarded, the rank and suit of the discarded card is to be shown.
If the computer player knocked, the current hand is ended and the
inter-hand commands will be used once the points for the hand have
been determined.
K <int>
-
The user Knocks and ends the hand.
The <int> in the command is used to specify which command is
to be discarded. The <int> value is to correspond to the positions
used the last time the user's hand was displayed. Everytime the user's
hand is displayed it MUST follow the algorithm as described in the C command.
The user can only knock if the unmatched cards in the user's hand
total ten points or less. The points in the user's hand are determined
by checking the sets in the user's hand. Each set is verified to
see if it contains a complete seqeunce or a complete group. The
sets that do not contain complete sequences or complete groups
are considered to be unmatched cards and are used for the hand value.
If the hand value is more than ten points, an error message is given
and the command is ignored. Otherwise the hand is over and the
inter-hand commands are used once the points for the hand have been
determined.
The points for a hand is determined once a player has knocked. Refer
to the
Knocking section and the
Scoring section for how the points are determined. You are to
automate the "laying off" of cards from the hand of the player that
did not knock to the hand of the player that did knock. When doing
this check all unmatched cards against sequences first before
checking against groups. If the
user has only one set and the computer player knocked, organize
the user's hand as if the O command was given by the user.
This program will require the use of multiple source code files and
separate compilation.
The division of the subroutines between the
multiple source code files must be logical.
Note: a "source code file"
is not the same as a "header file". Source code files will have
a file extension of .c (or .cpp, .C, .CC, etc.), while a header file
will have a file extension of .h. To perform separate compilation,
your makefile must separately compile
the source code files into ".o" files and then link the ".o" files together.
Using a #include statement with a source code file will NOT satisfy a
requirement of separate compilation.
In addition to using and submitting a makefile, this program will also require
a 1-2 page write up of the data structures
used in the program and the logical division of your program into multiple
source code files (i.e. which routines are where). Remember that
this write-up is to be written in ASCII format and is to be electronically
turned in with your program. The name of this file should be "readme.txt".
Also recall that your program will be given to another student to
write a critique. Therefore, it is suggested that you do not include
your Social Security Number in your program. Instead use your name and
your CS User ID to identify yourself.
Your program must be written in good programming style. This includes
(but is not limited to) meaningful identifier names, a file header at
the beginning of each source code file, a function header at the beginning
of the function, proper use of blank lines and indentation to aide in the
reading of your code, explanatory "value-added" in-line comments, etc.
The work you turn in must be 100% your own. You are not allowed to
share code with any other person (inside this class or not). You may
discuss the project with other persons; however, you may not show any
code you write to another person nor may you look at any other person's
written code.
You are to submit this project using the CS Department's UNIX machine's
turnin command. The project name for this assignment is mp2.
Be sure to submit all source code, header files, makefile as well as your
program description. Failure to turnin all required pieces will result
in a lower grade for the assignment.