Blackjack

Executive Summary

You will implement a fully functioning game of Blackjack. No prior knowledge of the game is needed. However, you will need to know what cards appear in a standard deck of playing cards. See your instructor if you have any questions on that account.

Blackjack (also called "21") is basically a game between an individual player and a dealer. There's a gambling side to the game that this project does not address. The project simply plays the game with the user as "Player" and program as "Dealer", and determines the winner and loser.

Honor:
The course policy and the instructions it references, most pertinently COMPSCIDEPTINST 1531.1C, spell out what kinds of assistance are permissible for programming projects. The instructor can give explicit permission for things that would otherwise not be allowed. For this project, you are allowed
  1. to get help from other current SI204 instructors as well as your own and from current SI204 MGSP leaders (any assistance must be documented though), and
  2. to use general purpose C++ resources online (though such use must be documented).
For this project, you are not allowed to do the following:
  1. Resources that might specifically address this project, say looking through code that implements blackjack or other card games, are not allowed.
  2. You are very specifically not allowed to look at previous semesters' SI204 or IC210 programming projects or lab solutions that may have addressed similar issues.
Combining the instructions referenced in the course policy and the explicit permissions above, what you get is summarized as:

Grading

70% of your grade will be based on functionality (i.e., whether your program works as specified), mostly based on the test cases that you see when you submit, but perhaps also extra test cases according to the specifications of the project. The code you submit must work if you expect to earn a passing grade.

30% of your grade will be based on coding style, which includes:

Deadlines

Early bonus and late penalty

Submit

Submit your work with the command
~/bin/submit -c=SI204 -p=proj02 *.cpp

Part 1 [up to 10pts] / Printing out a deck of cards

A part 1 solution (p1.cpp) will create a deck of cards, printing out the cards represented as integers.

Sample run

~/$ ./p1
[102 103 104 105 106 107 108 109 110 111 112 113 114 202 203 204 205 206 207 208 209 210 211 212 213 214 302 303 304 305 306 307 308 309 310 311 312 313 314 402 403 404 405 406 407 408 409 410 411 412 413 414]

Explanation: Storing a card as an integer

Each card will be represented by a single integer cardvalue in the following way:

Ordering of the cards in the deck

The card numbers in your deck should be ordered numerically in increasing order. In other words, your program should work as follows:
  1. The deck will start with the 2 of clubs up to the ace of clubs;
  2. then all the diamonds;
  3. then all the hearts;
  4. then all the spades (ending with the ace of spades).

Part 2 [up to 35pts] / Simulation of Dealing Cards

Copy p1.cpp to p2.cpp.
Now, after creating a deck as in Part 1, let's simulate dealing cards to a "Player" and a "Dealer".
Dealing a card:
  1. Take the card on the top of the deck. In our context, the top card is the first card printed in Part 1.
  2. Hand the card to the player (or the dealer).
  3. Needless to say, the next card on the deck becomes the top card.

Your program should be able to handle the following commands:

  • print-p: print the hand of the player.
  • print-d: print the hand of the dealer.
  • deal-p: deal a card from the deck to the player.
  • deal-d: deal a card from the deck to the dealer.
  • quit: quit the program

Sample run

Carefully inspect the sample run on the right and make sure to fully understand how the program should work.

Programming tips

  1. It is fine to create a large array (or arrays) and then use only some of the entries. As long as they take less than 1 MB space, your program uses only a tiny amount of memory space. Needless to say, it is also fine to use all of the entries for a large array!
  2. Make sure you do a good job of handling commands in functions.
    • These functions will serve as a good tool set for future parts!
~/$ ./p2
[102 103 104 105 106 107 108 109 110 
111 112 113 114 202 203 204 205 206 
207 208 209 210 211 212 213 214 302 
303 304 305 306 307 308 309 310 311 
312 313 314 402 403 404 405 406 407 
408 409 410 411 412 413 414]
>  print-p
[]
>  print-d
[]
>  deal-p
>  print-p
[102]
>  deal-p
>  print-p
[102 103]
>  deal-d
>  print-d
[104]
>  print-p
[102 103]
>  deal-d
>  deal-d
>  deal-d
>  print-p
[102 103]
>  print-d
[104 105 106 107]
>  deal-p
>  print-d
[104 105 106 107]
>  print-d
[104 105 106 107]
>  deal-p
>  deal-p
>  deal-p
>  print-p
[102 103 108 109 110 111]
>  deal-d
>  print-d
[104 105 106 107 112]
>  quit

Part 3 [up to 45pts] Hit or Stand

Copy p2.cpp to p3.cpp. Now let's play something that actually looks like a game. Sample run: red text represents user input.
~/$ ./p3
[102 103 104 105 106 107 108 109 110 111 112 
113 114 202 203 204 205 206 207 208 209 210 
211 212 213 214 302 303 304 305 306 307 308 
309 310 311 312 313 314 402 403 404 405 406 
407 408 409 410 411 412 413 414]

Player: [102 104]
Dealer: [103 105]

Round 1 Player's turn
hit or stand ? [h/s] h

Player: [102 104 106]
Dealer: [103 105]

Round 1 Dealer's turn
hit or stand ? [h/s] s

Player: [102 104 106]
Dealer: [103 105]

Round 2 Player's turn
hit or stand ? [h/s] h

Player: [102 104 106 107]
Dealer: [103 105]

Round 2 Dealer's turn
hit or stand ? [h/s] s

Player: [102 104 106 107]
Dealer: [103 105]

Round 3 Player's turn
hit or stand ? [h/s] s

Player: [102 104 106 107]
Dealer: [103 105]

Round 3 Dealer's turn
hit or stand ? [h/s] h

Player: [102 104 106 107]
Dealer: [103 105 108]
~/$ ./p3
[102 103 104 105 106 107 108 109 110 111 112 
113 114 202 203 204 205 206 207 208 209 210 
211 212 213 214 302 303 304 305 306 307 308 
309 310 311 312 313 314 402 403 404 405 406 
407 408 409 410 411 412 413 414]

Player: [102 104]
Dealer: [103 105]

Round 1 Player's turn
hit or stand ? [h/s] s

Player: [102 104]
Dealer: [103 105]

Round 1 Dealer's turn
hit or stand ? [h/s] h

Player: [102 104]
Dealer: [103 105 106]

Round 2 Player's turn
hit or stand ? [h/s] h

Player: [102 104 107]
Dealer: [103 105 106]

Round 2 Dealer's turn
hit or stand ? [h/s] h

Player: [102 104 107]
Dealer: [103 105 106 108]

Round 3 Player's turn
hit or stand ? [h/s] h

Player: [102 104 107 109]
Dealer: [103 105 106 108]

Round 3 Dealer's turn
hit or stand ? [h/s] s

Player: [102 104 107 109]
Dealer: [103 105 106 108]

Part 4 [up to 55pts] Shuffling the deck

Copy p3.cpp to p4.cpp.
Shuffle: [n | u <seed>]: u 103
[307 212 313 402 111 104 314 207 211 203 205 
303 204 202 206 405 214 410 304 108 308 213 
408 107 413 112 105 309 208 411 302 404 305 
312 113 114 414 109 106 110 407 103 209 311 
409 210 403 412 102 306 406 310]

Player: [307 313]
Dealer: [212 402]

Round 1 Player's turn
hit or stand ? [h/s] h

Player: [307 313 111]
Dealer: [212 402]

Round 1 Dealer's turn
hit or stand ? [h/s] h

Player: [307 313 111]
Dealer: [212 402 104]

Round 2 Player's turn
hit or stand ? [h/s] s

Player: [307 313 111]
Dealer: [212 402 104]

Round 2 Dealer's turn
hit or stand ? [h/s] h

Player: [307 313 111]
Dealer: [212 402 104 314]

Round 3 Player's turn
hit or stand ? [h/s] s

Player: [307 313 111]
Dealer: [212 402 104 314]

Round 3 Dealer's turn
hit or stand ? [h/s] h

Player: [307 313 111]
Dealer: [212 402 104 314 207]
In this part, we provide the program with the feature of shuffling the deck.

User input

When the program starts, the user is presented with the message:
Shuffle: [n | u <seed>]:
  • If the user enters n, no shuffling will take place.
  • Otherwise, we'll shuffle using a random number generator, which of course needs to be seeded. In particular, if the user uses the u option followed by a number, this number is then used as the seed. The random number generator should be seeded only once in the program!

Shuffling the deck

If the user chooses to shuffle the deck, shuffling must be done exactly as shown in the pseudo-code below:

for i from 0 up to 51 do    // so 52 times in total 
  set j to rand() % 52                                           
  swap the index i element of the deck with the index j element 
(Note, this is not a good enough shuffling algorithm for "real" applications because it introduces a small amount of bias in the ordering, but this is what we're going to do to keep in simple.) See an example run on the left.

Part 5 [up to 75pts] Pretty print

Copy p4.cpp to p5.cpp.
~/$ ./p5
Shuffle: [n | u <seed>]: u 103  

 Player Dealer
|  7♥  |  Q♦  |
|  K♥  |  2♠  |
Round 1 Player's turn
hit or stand? [h/s] h  

 Player Dealer
|  7♥  |  Q♦  |
|  K♥  |  2♠  |
|  J♣  |      |
Round 1 Dealer's turn
hit or stand? [h/s] h  

 Player Dealer
|  7♥  |  Q♦  |
|  K♥  |  2♠  |
|  J♣  |  4♣  |
Round 2 Player's turn
hit or stand? [h/s] s  

 Player Dealer
|  7♥  |  Q♦  |
|  K♥  |  2♠  |
|  J♣  |  4♣  |
Round 2 Dealer's turn
hit or stand? [h/s] h  
 
 Player Dealer
|  7♥  |  Q♦  |
|  K♥  |  2♠  |
|  J♣  |  4♣  |
|      |  A♥  |
Round 3 Player's turn
hit or stand? [h/s] s  

 Player Dealer
|  7♥  |  Q♦  |
|  K♥  |  2♠  |
|  J♣  |  4♣  |
|      |  A♥  |
Round 3 Dealer's turn
hit or stand? [h/s] h  

 Player Dealer
|  7♥  |  Q♦  |
|  K♥  |  2♠  |
|  J♣  |  4♣  |
|      |  A♥  |
|      |  7♦  |    

Don't print the deck

From now on, we omit printing the deck.

Print the hands vertically

As shown in the sample run on the left, you must print the hands vertically.

Note: You need to change only the printing part of your code. Please do not change any other parts in your code.

Printing out face values

To print out the numbers neatly, make sure to use two spaces for a card's face value. For example, if the face value is 2, do as follows:

cout << " " << 2;  // we need " " because 2 takes only one space
On the other hand, if the face value is 10, do as follows:

cout << 10;        // we do not need " " because 10 takes two spaces

Printing out suits

Our Unix terminal program understands "UTF-8" character encodings, which means we can print card suits to the screen. Each suit symbol is represented by a string. Carefully look at the following code and its output. Adapt the code to your need.
source code output

string clubs = "\u2663";
string diamonds = "\u2666";
string hearts = "\u2665"; 
spades = "\u2660";

cout << 10 << clubs << endl;
cout << 10 << diamonds << endl;
cout << 10 << hearts << endl;
cout << 10 << spades << endl;
10♣
10♦
10♥
10♠

Part 6: [Upto 85 pts] Scores

Copy p5.cpp to p6.cpp. A correct part 6 solution should behave exactly like a correct part 5 solution except the following:

Computing the score for a hand

  1. Add up points for each card in the hand as follows. Call this number total.
  2. If the hand has an ace (or aces) and total is less than or equal to 11, then "score" is total+10.
    For example, the total for 7♥ A♥ is 7 + 1 = 8. Since the total is at most 11, the score is 8+10 = 18.
  3. Otherwise, total becomes the "score".
    For example, the total for 8♥ A♥ J♠ A♣ is 8 + 1 + 10 + 1 = 20. Since the total is greater than 11, the score is 20.

Sample run: red text represents user input.
~/$ ./p6
Shuffle: [n | u <seed>]: u 92  

 Player Dealer 
|  Q♦  |  A♣ |
|  8♣  |  7♣ |
Player 18, Dealer 18
Round 1 Player's turn
hit or stand ? [h/s] h

 Player Dealer 
|  Q♦  |  A♣ |
|  8♣  |  7♣ |
|  6♠  |     |
Player 24, Dealer 18
Round 1 Dealer's turn
hit or stand ? [h/s] h

 Player Dealer 
|  Q♦  |  A♣ |
|  8♣  |  7♣ |
|  6♠  |  4♥ |
Player 24, Dealer 12
Round 2 Player's turn
hit or stand ? [h/s] h

 Player Dealer 
|  Q♦  |  A♣ |
|  8♣  |  7♣ |
|  6♠  |  4♥ |
|  2♣  |     |
Player 26, Dealer 12
Round 2 Dealer's turn
hit or stand ? [h/s] h

 Player Dealer 
|  Q♦  |  A♣ |
|  8♣  |  7♣ |
|  6♠  |  4♥ |
|  2♣  |  9♠ |
Player 26, Dealer 21
Round 3 Player's turn
hit or stand ? [h/s] h

 Player Dealer 
|  Q♦  |  A♣ |
|  8♣  |  7♣ |
|  6♠  |  4♥ |
|  2♣  |  9♠ |
| 10♠  |     |
Player 36, Dealer 21

Round 3 Dealer's turn
hit or stand ? [h/s] s

 Player Dealer 
|  Q♦  |  A♣ |
|  8♣  |  7♣ |
|  6♠  |  4♥ |
|  2♣  |  9♠ |
| 10♠  |     |
Player 36, Dealer 21
Round 4 Player's turn
hit or stand ? [h/s] h

 Player Dealer 
|  Q♦  |  A♣ |
|  8♣  |  7♣ |
|  6♠  |  4♥ |
|  2♣  |  9♠ |
| 10♠  |     |
|  Q♣  |     |
Player 46, Dealer 21
Round 4 Dealer's turn
hit or stand ? [h/s] s

 Player Dealer 
|  Q♦  |  A♣ |
|  8♣  |  7♣ |
|  6♠  |  4♥ |
|  2♣  |  9♠ |
| 10♠  |     |
|  Q♣  |     |
Player 46, Dealer 21
Round 5 Player's turn
hit or stand ? [h/s] s

 Player Dealer 
|  Q♦  |  A♣ |
|  8♣  |  7♣ |
|  6♠  |  4♥ |
|  2♣  |  9♠ |
| 10♠  |     |
|  Q♣  |     |
Player 46, Dealer 21

Part 7 [upto 100 pts] Play!

Copy p6.cpp to p7.cpp. A part 7 solution functions just like a part 6 solution with the following two exceptions: Sample run: red text represents user input
~/$ ./p7
Shuffle: [n | u <seed>]: u 901  

 Player Dealer
|  Q♣  |  **  |
|  K♣  |  7♦  |
Round 1 Player's turn
hit or stand? [h/s] s  

 Player Dealer
|  Q♣  |  **  |
|  K♣  |  7♦  |
Round 1 Dealer's turn
hit or stand? [h/s] s  

 Player Dealer           
|  Q♣  |  A♦  |
|  K♣  |  7♦  |
Player wins
Sample run: red text represents user input
~/$ ./p7
Shuffle: [n | u <seed>]: u 500  

 Player Dealer
|  K♠  |  **  |
|  7♣  |  2♣  |
Round 1 Player's turn
hit or stand? [h/s] s  

 Player Dealer
|  K♠  |  **  |
|  7♣  |  2♣  |
Round 1 Dealer's turn
hit or stand? [h/s] h  

 Player Dealer
|  K♠  |  **  |
|  7♣  |  2♣  |
|      |  2♠  |

Round 2 Player's turn
hit or stand? [h/s] s  

 Player Dealer
|  K♠  |  **  |
|  7♣  |  2♣  |
|      |  2♠  |
Round 2 Dealer's turn
hit or stand? [h/s] h  

 Player Dealer
|  K♠  |  **  |
|  7♣  |  2♣  |
|      |  2♠  |
|      |  3♦  |
Round 3 Player's turn
hit or stand? [h/s] s  

 Player Dealer
|  K♠  |  **  |
|  7♣  |  2♣  |
|      |  2♠  |
|      |  3♦  |
Round 3 Dealer's turn
hit or stand? [h/s] s  
      
 Player Dealer
|  K♠  |  Q♠  |
|  7♣  |  2♣  |
|      |  2♠  |
|      |  3♦  |

 Player Dealer
|  8♣  |  **  |
|  A♦  |  J♥  |
Round 1 Player's turn
hit or stand? [h/s] s  

 Player Dealer
|  8♣  |  **  |
|  A♦  |  J♥  |
Round 1 Dealer's turn
hit or stand? [h/s] h  

 Player Dealer
|  8♣  |  **  |
|  A♦  |  J♥  |
|      |  A♥  |
Round 2 Player's turn
hit or stand? [h/s] h  

 Player Dealer
|  8♣  |  **  |
|  A♦  |  J♥  |
|  6♥  |  A♥  |
Round 2 Dealer's turn
hit or stand? [h/s] h  

 Player Dealer
|  8♣  |  5♦  |
|  A♦  |  J♥  |
|  6♥  |  A♥  |
|      | 10♣  |
Dealer busts, player wins