Rack-O®
- Summary
- You build a program to support playing a simple strategy game.
- Objectives
-
- Practice using list-backed stacks
- Contrast list, stack, and array suitability
- Reinforce memory-management knowledge
- Verify user input
Introduction
Game Overview
The board game Rack-O is a simple game requiring players to sort a fixed-length rack of cards through replacements from a randomized sequence. With gameplay for 2–4 players, it debuted in 1956 and remains fun and popular today.
Game play involves a deck of cards numbered 1–60. To begin, these cards are randomly shuffled. Each player has a rack in which ten cards are placed into slots. At the start of the game, the cards are dealt from the shuffled deck to alternating players' racks in increasing slot order. The remaining undealt cards get placed into a stock pile. The top card from the stock pile is turned over so it is visible and placed into the discard pile
The object of the game is to be the first player to obtain a rack with all ten cards appearing in increasing sorted order.
The game is played by alternating turns. A player chooses a card from either the stock or discard pile. If the player chooses from the discard pile, they must use it to replace an existing card in their rack: the card removed from the rack then goes on the top of the discard pile and the new card is inserted in its place. If the play instead chooses from the stock pile, they may either return that card to the discard pile or use it to replace a card in their rack.
In the full game, this play constitutes a round, with subsequent
scoring based on the card placement in the rack. However, in our
dimunition of the game, such play will alternate until one player has
simply Gone Rack-O!
(achieved a sorted rack).
Program Structure
The astute reader will have noticed the opportunities for use of the following data structures:- Stacks:
- Only the top-most card is accessible from the stock and discard piles, and the length is variable. Therefore, these collections will be represented in your program with stacks backed by linked lists.
- Racks:
- The racks have a fixed length and are accessed by an arbitrary index (rather than sequentially). This precisely fits the usage pattern of arrays.
Your game play will only support two players, and will not involve any sort of intelligent computer player. Instead the program will keep track of the piles and racks, asking the players for their choices and displaying the relevant information as it arises.
Assignment
As one might imagine, correctly using these ideas requires attention to a number of practical details.
Card Stacks
To support the two card piles, you will need to implement and test a simple stack.
Implementation
Place the following (with documentation, include guards, and
the necessary headers) declarations into cardstack.h and
implement the corresponding procedures in cardstack.c.
typedef struct node {
int card;
struct node * next;
} node_t;
bool
isEmpty (const node_t * stack);
void
push (int card, node_t ** p_stack);
int
pop (node_t ** p_stack);
int
top (const node_t * stack);
void
clear (node_t ** p_stack); // Empty the stack, freeing all memory
Your documentation should clearly identify necessary preconditions, and your implementation should verify those preconditions with assertions.
If any standard library routine fails, you may
use perror to print a contextualized error message
and exit the program from within your library.
Testing
Use preprocessor macros to contruct a simple, but comprehensive test suite for your stack.
The stack library cardstack.c will eventually be compiled
separately and linked with your game program. However, rather than
create a separate driver program (that is, a C file with
a main procedure), add a main to the bottom
of cardstack.c with a conditional inclusion dependent on the
TESTSTACK symbol to indicate testing. For example:
#ifdef STACKTEST
// Test helper routines here
int
main (void)
{
// Test program here
} // main
#endif
One would then be able to test your stack by compiling with something like the following:
clang -Wall -DSTACKTEST -o stacktest cardstack.c
Makefile
Create a Makefile for your assignment that includes the
following targets:
cardstack.o-
Builds that object file from your
cardstack.c. Note that none of the testing routines should be present in the object. stacktest-
Builds that executable program from
your
cardstack.c. Note that all of your testing routines should be present in the program and run when the program is executed. permute.o-
Builds that object from the provided
code
permute.c(which relies onpermute.h).
Your Makefile should
separate out variables CPPFLAGS, CFLAGS,
and LDFLAGS that are subsequently used in the
appropriate target rules.
You may want to add another variable FLAGS (initially
empty), as follows
# Optional, universal flags to use in all build commands (compile, link, etc)
FLAGS=
that is used in all rules, so that you can incorporate the Address
Sanitizer through that variable, i.e.,
make FLAGS=-fsanitize=address
Game Play
Complete the functions
in racko.c to implement
the full game play. Note that the main function has been
completed for you, but the rest of the functions are provided as
stubs. Completing these stubs should allow you to run the game, as
demonstrated in this
transcript. Bad user input should be handled robustly, as
demonstrated in another
transcript.
The following notes may help guide your thinking about the program structure:
-
Game play functions requiring user input should not solicit it
directly, but should instead use the helpers (currently
stubs)
get_choiceandget_slot_number. -
game_playis very simple and should make use ofprint_rack,make_move, andgone_racko. -
make_moveshould make use ofmove_from_discardormove_from_stockbased on the state of the game and/or user choices.
Makefile revisited
Add the following targets to your Makefile, including
any necessary dependencies:
racko.o-
Builds that object file from your
racko.cprogram. racko- Builds the executable game program by linking the necessary object files.
Grading
In addition to the general grading guidelines for evaluation, the assignment is worth 45 points.
- [8 points] Library
cardstack.c- [1 point] Function
isEmptyis correct - [2 points] Function
push- Adds item to stack
- Prints notice and exits if error
- [1 point] Function
topis correct - [2 points] Function
popis correct - [2 points] Function
clearis correct
- [1 point] Function
- [30 points] Program
racko.c- [2 points] Procedure
setup_game- [1 point] Shuffles a deck and populates players' racks
- [1 point] Initializes stock and discard piles
- [2 points] Procedure
clear_gameis correct - [2 points] Procedure
gone_rackois correct - [1 point] Procedure
print_rackis correct - [3 points] Procedure
get_choice- [1 point] Prints the given prompt and reads character input
- [1 point] Detects end of file and exits
- [1 point] Detects invalid input and repeats
- [4 points] Procedure
get_slot_number- [1 point] Prints detailed prompt
- [1 point] Reads integer input
- [1 point] Detects end of file and exits
- [1 point] Detects invalid input and repeats
- [2 points] Procedure
insertis correct - [4 points] Procedure
move_from_stock- [1 point] Removes and displays card from stock pile
- [3 points] Solicits user choice and takes appropriate action
- [2 points] Procedure
move_from_discardis correct - [4 points] Procedure
make_move- [1 point] Moves from stock pile (with notice) when discard pile is empty
- [3 points] Otherwise informs user of discard's top, solicits choice, and takes appropriate action
- [2 points] Procedure
game_playis correct - [2 points] Procedure
move_discardis correct
- [2 points] Procedure
- [7 points]
Makefile- [3 points] Rules for compiling source files
- [2 points] Rules for linking object files
- [2 points] Uses flags where appropriate
-
Evaluation of program Structure, Comments, Design, and Testing.
(Additional points not given, but points may be deducted.)
A five point penalty will apply to any submission that includes personally identifying information anywhere other than the references/honesty file.
To pass the assignment (with a grade of C or better), tests must demonstrate a clean diagnosis from AddressSanitizer.
Beyond those provided in the starter file, additional global variables may not be used anywhere; use of any additional global variable will result in a grade of zero.
