You should implement a "Kozel" card game for two players: a user and a computer/game. The user should operate cards in its hand using the provided graphical user interface (GUI) while the game's hand should operate automatically (you can build-in any simple strategy). The implementation should be done in C++ using principles of object oriented design. The GUI is provided to you in a form of an executable file KozelGameGUI.exe. In order to work, this executable requires a dynamic link library [url removed, login to view] (placed in the same directory) that should include a compiled implementation of a KozelGame class. An object of class KozelGame is a "master of ceremonies" that keeps the Kozel game going; it sets up each round, makes sure that the user follows the rules, computes "automatic" response from computer's hand (also referred as a game's hand), and draws all cards in the game on a screen. One KozelGame object is created inside the GUI (using your .dll) when you start running the executable file. Its public functions are called when a user makes mouse clicks (for moves or for hand sorting), presses ENTER key (to indicate round end), or when the GUI refreshes the screen after each user interaction (see KozelGame.h for more details). The UML below outlines the relationship between the GUI and the KozelGame object.
Using Classes Implemented as Templates
In this home work you are supposed to use List and Bag data structures. We provided template-based implementations for objects of these classes (Bag.h, [url removed, login to view], List.h, [url removed, login to view]). "Templates" will be covered in class shortly. In the mean time you can look up the basic use of templates in the text book (p. 297). Note that you would not see any difference when using two bags of pointers
except that [url removed, login to view]()returns KozelGameCard*pointers which can be immediately dereferenced in order to access the actual card objects they point at. Remember that this is not the case with generic void*pointers returned by [url removed, login to view]()which have to be explicitely recast by expression (KozelGameCard*)before you can dereference them in your code. The difference is illustrated by two valid C++ expressions obtaining suit of a card randomly drawn from a bag
((KozelGameCard*) [url removed, login to view]())->getSuit();
[url removed, login to view]()->getSuit();
Which one is easier to use in your code?
'Kozel' means a 'goat' and it is a very common card game in Eastern Europe where often it becomes a first card game that kids learn to play. Normally, it is played with an incomplete deck of 36 cards using only cards of denomination 6 and higher. Any number of players between 2 and 6 is possible. Below, we descibe the rules only for the case of two players (you have to implement this basic case when the players are a "user" and a "computer"). You can also check out a working demo of the game.
* Initially, the deck of 36 cards is shuffled and placed in a "bank". The bottom card is turned face-up to display the trump suit. Then each player draws 6 cards from the top of the bank and puts them in their "hands". Now they are ready for a first round of the game. Players do not show cards in their hands to each other.
* In each given round of the game one of the players "leads" cards (one at a time). Each "lead" should be placed face-up in front of the other (defending) player. The defending player tries to cover (or to "beat") each open "lead" with a more valuable card. A valid "beat" card can have a higher denomination and the same suit as the "lead". Also, any trump-suit card beats any non-trump card. Each "beat" card should be placed face-up on a top of the corresponding "lead" card. Each such pair (a "lead" and its "beat") is called a "trick". A "lead" without a "beat" can be referred to as an "open lead" or an "open trick".
* A player that "leads" in a given round MUST "lead" one of his/her card in the beginning of the round. A first "lead" in each new round of the game could be any card in the "leading" player's hand. If a defending player "beats" an open "lead", this pair of cards is called a closed "trick".
* The defending player/hand does not have to "beat" a given open "lead" (even if he/she has a valid card). If a "beat" is not placed on an open "lead" then the round ends "unsuccessfully". The player/hand that could not defend itself has to take all current tricks (including all closed ones and the last open "lead").
* If the defending player "beats" an outstanding open "lead" then the "leading" player may open a new trick by advancing another "lead" card. Except for a first trick of each round, the "leads" for additional tricks should match in denomination one of the cards among the current tricks (either "leads" or "beats"). The "leading" player does not have to add tricks even if he/she has some "lead" cards that qualify, it is entirely up to the player.
* If all outstanding "leads" are "beat" (all tricks are closed) and the "leading" player cannot or does not want to add a new "lead", then the round ends "successfully" and the player/hand that beats could defend itself. In this case all current (closed) tricks are descarded from the game.
* The players switch their roles ("leader" vs. "beater") after each "successful" round where all tricks were closed. If the round ends "unsuccesfully" for the defending side, it has to defend in the next round again.
* In the beginning of each new round the players replenish their hands from the top of the bank. Each player should have at least 6 cards. If the player already has more than 6 cards then he/she does not have to take any more cards from the bank. When the bank becomes empty, the players do not replenish their hands anymore. By the time when only a few cards are left in the bank, the order in which the players replenish their hands may be important. For this reason the rules dictate that a player that "led" in the previous round should replenish his hand first.
* The winner is the first player that ends up without any cards in his/her hand (which is possible only after the bank gets empty). The other player becomes a 'goat' and he/she is supposed to get under a table (e.g. where the game was played) and to say "mmme-e-e-e" loudly. You do not have to implement this last rule in your C++ project :)
Your goal is to write C++ code for KozelGame class consistent with the UML diagram above. You should use KozelGame.h and [url removed, login to view] files from code samples page. KozelGame.h provides declarations and general textual descriptions of all public and private member attributes. GUI uses only public functions (shown in UML) while a number of private functions of KozelGame class (not shown in UML) should help to break implementations of these public methods into small clear steps/tasks. A number of private member variables of KozelGame class are used to contain necessary KozelGameCard objects and for internal book-keeping. The UML above shows only the main containers for the cards in the user's and in the game's hands, for the cards in the "bank", and for the cards in a pool of tricks.
File [url removed, login to view] contains detailed instructions/hints on implementing all public and private functions. The actual C++ code should be written by you following these instructions. Note that you MUST NOT change declarations of any KozelGame attributes (member functions or member variables) included in the KozelGame.h header file. Otherwise, the provided GUI will not find functions it expects from KozelGame objects and [url removed, login to view] will not run properly with your library. Changing private attributes may cause instabilities as well (GUI was compiled with the provided KozelGame header file). Thus, we recommend that you DO NOT EDIT "KozelGame.h" FILE at all!
As indicated in the UML diagram, your implementation of KozelGame class must use/contain objects of additional classes: KozelGameCard, Card, Bag, and List. All necessary C++ files (Bag.h, [url removed, login to view], List.h, [url removed, login to view], KozelGameCard.h, [url removed, login to view], Card.h, [url removed, login to view]) are available at code samples page. You should only implement functions inside [url removed, login to view] following the instructions inside.
To complete your assignment, you should use Microsoft Visual C++ Studio .NET to generate [url removed, login to view] dynamic link library file that is required for running KozelGameGUI.exe. To generate such file, start a new "MFC dll" project inside C++ Studio and call it "KozelGameDLL". While inside the "KozelGameDLL" project environment, you should add existing .h and .cpp files(for Bag, List, KozelGame, KozelGameCard, and Card classes)