Saint Louis University |
Computer Science 180
|
Dept. of Math & Computer Science |
Please see the general programming webpage for details about the programming environment for this course, guidelines for programming style, and details on electronic submission of assignments.
For this assignment, you must work individually in regard to the design and implementation of your project.
Please make sure you adhere to the policies on academic integrity in this regard.
The files you may need for this assignment can be downloaded here.
Your goal for this program will be to design a class Hand which will be used to simulate playing a game of cards. Every card will have a "suit" and a "value" specified. Your class must support the following routines:
Add the specified card into the hand.
This routine removes a card from the hand and returns it. More specifically, if the hand contains any cards of the desired suit, one of those cards must be played (the choice of which can be arbitrary). If the hand does not contain any cards of the desired suit, a card of some other suit should be played. If the hand is empty, this routine should throw a hand_empty exception.
For this assignment, you must ensure the robustness of your class by properly implementing the copy constructor, the overloaded assignment operators and the destructor.
For the routine insertCard(c), you may assume that the card is given with a valid suit and value. Furthermore, you do not need to worry about whether a new card is identical to an existing card. Just keep them both, as if they are two different cards. (In fact, those who have played Pinochle know that your hand may indeed have two cards with identical value and suit).
The semantics of the playDown(suit) routine is meant to model the rules of many common games (e.g., Hearts, Bridge, Pinochle) which require a player to "follow suit" when possible. Because of this requirement, players often find it convenient to organize their hand so that all cards of the same suit are consecutive in the hand (though the order of the suits, and the order of the cards within a particular suit may remain arbitrary).
A naive implementation for maintaining cards of the same suit grouped might still require a linear walk through the entire hand. When inserting a new card, one might have to walk from one end of the list until finding other cards of the same suit (or realizing that there are none). Similarly, when trying to play a card of a particular suit, one might have to scan the entire hand.
A better approach is to maintain four "fingers" into the hand, one for each suit, allowing insertions and deletions to be implemented in constant time (no matter how large the size of the hand becomes). You are required to implement this constant time approach based on the use of underlying std::list and its iterator class. A single list must be used to store all cards, and each "finger" will be represented by an iterator in that list.
All such files can be downloaded here.
For this assignment, we will be providing you with a large number of needed files for a complete program, though you will not need to modify, or even read, many of them. We will briefly discuss the purpose of each file:
Hand.h, Hand.cpp
These are the only two files that you should modify. They
define the definitions for a class Hand which you must
implement. The files we provide are stubs, which will
originally compile, yet which do not yet work properly.
hand_empty.h
You should not modify either of these files.
Defines a hand_emtpy exception class, which is to be
thrown when asked to play a card from an empty hand.
Card.h, Card.cpp
You should not modify either of these files.
These define a simple class for representing one card.
An object, c, of class Card has two public
variables c.suit and c.value. The variable
c.suit is of type Suit, which is an enumerated
type. In essence, it is an integer type, but it allows us to
draw a specific correspondence between the suit names and the
integers, with CLUB=0, DIAMOND=1, HEART=2, SPADE=3. Similarly,
c.value is of a declared type Value which is
an enumeration equating the values ACE=1, TWO=2, ..., QUEEN=12,
KING=13.
A default card is created with special settings, NOVALUE and NOSUIT, and will be displayed as "??".
test_hand.cpp, MenuDriver.cpp, MenuDriver.tcc, MenuDriver.h
You should not modify these file.
These support the main driver for testing your code.
As was the case with previous assignments, it is a low-frill,
menu-driven user interface, taking its input from the keyboard
by default, but reading input from a file instead, if you
provide the filename as a runtime argument.
makefile
This makefile should allow you to rebuild your project by
simply typing 'make' rather than in invoking the compiler
directly.
In the end, meeting the requirements for this assignment can be easy. A perfect solution can be written concisely, at the same time, past students have submitted solutions in excess of 300 additional lines of code yet flawed.
Our real goal of this programming assignment is to give you familiarity with the official STL list class and the iterator class which it defines.
We have two strict requirements for this assignment.
You must store all of the cards in a single instantiation of a list.
That is, you cannot create four separate lists for the four suits. Within that list, you should use the iterator abstraction to somehow represent where, in the large list, cards of a given suit might be found. This will allow you to insert or remove desired cards in constant time (i.e., without having to traverse the entire list).
You must ensure that your hand class properly supports a copy constructor, an overloaded assignment operator and a destructor.
Though we had left this as an extra credit challenge in past assignments, it is time that we go through the required effort, as these are necessary steps in creating robust object-oriented code. The driver's menu has explicit choices, "(C)" to test your implementation of the copy constructor, "(A)" to test your assignment operator and "(D)" to test your destructor.
The rest of the design details are left to your choice. We will add a few words of advice though.
The first advice is to note that the four suits are distinct, but the treatment of them is symmetrical. Though we talk about them as clubs, diamonds, etc. you will note that the Card class defines the suit as an enumerated type, equivalent to integers {0, 1, 2, 3}. This is for convenience. For example, rather than making four separate variables for the four positions, you should use an array of positions, with the suit value as an index. For example, this array might be defined as:
In this way, you can start writing code with syntax finger[s] rather than writing code with a variable SpadeFinger and then having to cut-and-paste that code for HeartFinger and so on.list<Card>::iterator finger[4];
Avoid the temptation to "cut-and-paste" when coding. The problem with that style of coding is that your program gets unnecessarily longer, you potentially duplicate unseen bugs to many places in your code, which you will later have to track down, and you might create new bugs as you slightly modify the pasted portions. If you ever find yourself tempted to cut-and-paste you should step back and think about whether your code could be redesigned.
There are two reasonable ways to approach the use of a finger for locating cards of a given suit. The direct approach is to have a finger for each suit which literally represents the position in the list where a card of the suit can be found. Of course, there become special cases, such as how the finger should appear when there are no cards of a given suit.
An alternative is to use a "sentinel" approach to attempt to reduce the number of special cases. For this assignment, such an approach might be to initially insert four or five "artificial" cards into the list to serve as bookmarks (or should that be bookends). In this way, even if the hand does not contains any cards of a given suit, a bookmark for that suit can still be found.
As for the housekeeping functions, keep in mind that the list class already supports similar such behavior. So copying the nodelist of a hand to another hand can be done with ease. The real challenge here is in properly managing the fingers of the (re)assigned hand. Directly copying the original fingers will not suffice because those are fingers into the wrong list.
We will again ask each student to submit a file "inputfile" which we will use in a round-robin competition. The assignment is worth 10 points. Eight points will be awarded based on our own evaluation of your assignment. One additional point will be awarded fractionally based on how well your program performs on other students' inputs. The final point will be awarded fractionally based on how well your input fools other students' programs.
You will find in developing your program that many different special case exists for this assignment. These range from how to represent a "finger" when a hand contains zero cards of a particular suit, as well as simply being careful in dealing with the NodeList interface in a way so that you do not end up with any unwanted exceptions.
Your file should be formatted perfectly to work as input to test_hand. You may use at most 100 commands, and you are not allowed to call the extra credit methods (as students are not required to implement these).
Hand.h, Hand.cpp
We expect that these are the only code files you will modify,
but if this is not the case, please submit any additional such files.
Test Input
Please submit a single file, inputfile, which we will
use as sample input when testing all of the students'
submissions. The file format for inputfiles is based on use with our driver
Your input file may use at most 100 lines.
In order to make sure that your inputfile follows the proper
format, we strongly recommend that you make sure that your
inputfile is accepted by the driver.
Readme File
A brief summary of your program, and any further comments you
wish to make to the grader.
If you are not familiar with cards or card games, do not worry. All that really matters for this assignment is that a card has a suit and a value, and the suit is the only piece of information which will effect your code. Feel free to ask if you have additional questions.
The assignment is worth 10 points. Eight points will be awarded based on our own evaluation of your assignment and the readme file. One additional point will be awarded fractionally based on how well your program performs on other students' test inputs. The final point will be awarded fractionally based on how well your test input fools other students' flawed programs.