CS202 -- Lab 3: Dynamic Memory and Blackjack Simulation


Inspiration

Blackjack is a simple and popular card game. For this lab, you will implement a simplified version using C++.

This assignment reinforces key object-oriented programming concepts including dynamic memory management (new/delete), class design (especially the Rule of Three), and random number generation.

For this lab, you must implement the following simplified Blackjack rules:

If you're unfamiliar with the rules, read the first few sections of Wikipedia's Blackjack article.

Part 1: a CardDeck class

  1. Develop a C++ class named CardDeck that stores a deck of cards as an array of n integers (to practice data hiding) and a corresponding "size" variable stored as a private data member in your new class.
  2. The non-default constructor should receive a value n and then place the integers from 0 to n - 1 into the array.
  3. Please specify a "fall back" value for this non-default constructor so n is assumed to be 52 (aka CardDeck(int = 52); as a prototype).
  4. Write a public member function getSize() that returns the size of the current deck using the size variable explained above.
  5. Provide a utility function named shuffle that performs a shuffle. You can either implement this yourself or use a temporary vector and the random_shuffle algorithm of the STL (assuming C++_11). If you're familiar with C++17+, consider using std::shuffle with a random engine instead of random_shuffle, though it's not required for this lab.
  6. To streamline grading, do not call srand() in your submitted code. The default behavior (i.e., no call to srand()) ensures consistent shuffle results across submissions. If you want different behavior during your own testing, you may call srand(time(NULL)); in main.cpp.
  7. Aim to have a simple client/test program done by the end of the lab period that initializes an array of ten cards (i.e., n = 10), and prints the deck before and after a shuffle.

Part 2: Practicing dynamic memory allocation

Change the implementation completed in lab to use dynamic memory allocation (new/delete). As discussed in the video/lecture this week, in addition to the constructor you need the following functions:

  1. Destructor
  2. Copy constructor
  3. Assignment operator
Mistakes to Avoid:

You must include a small block in main.cpp (after your initial shuffle test but before Blackjack starts) that tests your copy constructor and assignment operator using all four lines above. It is possible and probably likely your program will compile and work as intended otherwise but not get points in Part 1 of the rubric below without these lines. This is why the tests above are important, and it will prepare you for real-world class design and prevents hidden bugs.

Part 3: Developing a simple card game

Implement a simple BlackJack player using CardDeck as a foundation as follows: To streamline grading, please initializes an array of ten cards (i.e., n = 10), and print the deck before and after a shuffle prior to starting the BlackJack games (see rubric). Place this test output at the beginning of your main.cpp, before the user is prompted to play Blackjack. This helps us verify your CardDeck implementation. See below for example input:

Deck before shuffle: 0 1 2 3 4 5 6 7 8 9
Deck after shuffle: 4 8 1 7 2 0 9 3 5 6

Hint: You can use the modulus (%) operator to convert cards from 0-51 to 0-12, and you can use new/delete to ensure a constructor runs or a destructor runs for your decks.

Challenge (Optional but Fun!): Implement "War" - A Childhood Game

In a historical Dr. Plank style 140/302 students would be asked to complete TopCoder challenges to further hone their coding skills, after which a TA would provide their solution on a high level (no actual code usually). These were opportunities for students who wanted more practice and/or experience to do more than the "main" assignment.

Code up a client for the children's game known as "War" (among other names; see below). The game proceeds as follows:

  1. A 52-card deck is shuffled and divvied evenly between players.
  2. Each person places a single card for the other to see.
  3. Whoever has the highest card wins both cards.
  4. If there is a tie, "war" takes place; each player places 3 cards face down and one card face up. The highest showing card takes the combined pile.
  5. The "war" procedure is repeated if there is a tie until one player runs out of cards. This means that if a war is declared and one of the players does not have 3 cards, they lose.

Aces can be either high or low depending on personal preference in your implementation.

I played this with my Pop Pop (the common nickname for grandfathers in the Philadelphia area), which he learned as a very young boy growing up in southwest Germany as "Tod und Leben."

Rubric

Part 1: 16 points

+4 Basic program structure is correct
- program commented well (2 pts)
- clean program structure with correct file names and use of header guards (2 pts)
+4 non-default constructor works as requested with a fall back value
+4 member functions are correct (2 pts each)
- getSize()
- shuffle()
+2 client prints cards pre-shuffle
+2 client prints cards after shuffle

 
Part 2: 10 points

 
+2. Functional and working destructor that calls delete properly
+4  Functional and working copy constructor that works if/when you pass 
by value to a function
+4  Functional and working assignment operator that works when you set 
one CardDeck to another, e.g., CardDeck a; CardDeck b = a;
 
Although we will review your code and these should be relatively 
straightforward, we highly recommend that you use them as described 
to remove any bugs prior to submission (even though its ** very ** 
similar to the code provided in class)

Part 3: 12 points

+1 Aces are always 11
+2 User of the client is provided with a clear hit/stand option
+4 The Blackjack game works as it should.  Refer to 
https://en.wikipedia.org/wiki/Blackjack for details.  In short:

Player always goes first. If they go over 21, they bust and the dealer 
wins no matter what Dealer must "hit" until they reach 17 or higher. If 
the dealer goes over 21, and the user doesn't, the player wins
Otherwise, whoever has the higher number wins. For purposes of this lab 
you can chose to either track ties or assign any tie to the user, aka, 
user wins
+2 correctly keeps track of how many times a player wins and the dealer 
wins in your game
+1 asks if a user wants to continue after every game
+2 fewer than 15 cards triggers a new deck allocation and shuffle in Part 3

Testing your code prior to submission

To facilitate testing, you were previously asked to clone the course Github repository as follows:

git clone https://github.com/semrich/CS202-fall24.git cs202

For this assignment, update this clone by using the following:

git pull

We'll discuss this in class but note that your client must be named main.cpp and compilable using make. Unlike other assignments this term, you will get more credit for the structure of your code and following instructions versus solving unit tests. Please refer to the final rubric for details.


Submission

The command to create a single .tar is:

tar -cvf lab3.tar CardDeck.h CardDeck.cpp main.cpp
Because this assignment is more focused on C++ syntax/class design vs. solving specific problems, and since we checked for a very similar win condition in Lab 1, most of the to-be posted rubric will be on specific syntax/code items vs. solving scripts in advance.

Note: Although submission will be faciliated by Canvas, we will compile and test on EECS lab machines!

If you develop your solution elsewhere please make sure it works on the lab computers prior to the deadline.