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.1D, 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 IC210 instructors as well as your own and from current IC210 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' IC210 or SI204 programming project or lab solutions that may have addressed similar issues.
Combining the instructions referenced in the course policy and the explicit permissions above, and what you get is summarized as:
Warning: Do not even vaguely talk about the contents of the project with your colleagues.

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

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 25pts]: 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". Read the following rules slowly and carefully:
  1. Deal one card to "Player," one to "Dealer", one to "Player", and one to "Dealer" (so both have two cards). Then display the hands.
  2. Deal one card to "Player," then one card to "Dealer". Then display the hands.
  3. Deal one card to "Player," then one card to "Dealer". Then display the hands.
  4. Deal one card to "Player," then one card to "Dealer". Then display the hands.
~/$ ./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]

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

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

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

Player: [102 104 106 108 110]
Dealer: [103 105 107 109 111]
Dealing a card:

Programming Tip:

  1. You really want to have your program simulate dealing a card to a hand.
    Q: What would be a good way to represent the player's (respectively the dealer's) hand?
  2. Make sure you do a good job of putting things in functions.

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. Below is an example of how a game might play out (red text represents user input). Your output and the way you get input from the user must match what's shown here.

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 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.

Shuffling the deck

If the user chooses to shuffle the deck, shuffling must be done exactly as follows:

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 right:

Part 5 [up to 70pts]: Pretty print

Copy p4.cpp to p5.cpp.
~/$ ./p2
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.

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 [Up to 85 pts]: Best 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 best score for a hand

  1. Add up points for each card in the hand as follows. Call this number total.
  2. Depending on whether the hand has aces or not, the best score is computed as follows:

Sample run: red text represents user input.
~/$ ./p3
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 [up to 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
~/$ ./p4
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
~/$ ./p4
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

Extra Credit [+10pts]

The extra credit solution will not even be considered unless the Part 7 Full credit solution functions correctly.

Name your code px.cpp

~/$ ./px
Shuffle: [n | u <seed>]:  u 105

 Player Dealer 
|  5♣  |  ** |
|  4♦  |  7♠ |
Round 1 Player's turn
hit, stand or withdraw ? [h/s/w]  h

 Player Dealer 
|  5♣  |  ** |
|  4♦  |  7♠ |
| 10♥  |     |
Round 1 Dealer's turn
hit or stand ? [h/s] s

 Player Dealer 
|  5♣  |  ** |
|  4♦  |  7♠ |
| 10♥  |     |
Round 2 Player's turn
hit or stand? [h/s]  h

 Player Dealer 
|  5♣  |  K♣ |
|  4♦  |  7♠ |
| 10♥  |     |
|  5♥  |     |
Player busts, dealer wins
You have $6
Do you want to play again? [y/n]  y

 Player Dealer 
|  A♦  |  ** |
|  7♠  |  3♣ |
Round 1 Player's turn
hit, stand or withdraw ? [h/s/w]  w

 Player Dealer 
|  A♦  | 10♣ |
|  7♠  |  3♣ |
Player withdraws
You have $4
Do you want to play again? [y/n]  y

 Player Dealer 
|  K♠  |  ** |
|  3♠  |  J♠ |
Round 1 Player's turn
hit, stand or withdraw ? [h/s/w]  h

 Player Dealer 
|  K♠  |  5♣ |
|  3♠  |  J♠ |
|  Q♦  |     |
Player busts, dealer wins
You have $0
GAME OVER: Not enough money
 
~/$ ./px
Shuffle: [n | u <seed>]:  u 105

 Player Dealer 
|  5♣  |  ** |
|  4♦  |  7♠ |
Round 1 Player's turn
hit, stand or withdraw ? [h/s/w]  s

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

 Player Dealer 
|  5♣  |  K♣ |
|  4♦  |  7♠ |
Dealer wins
You have $6
Do you want to play again? [y/n]  n
Shuffle: [n | u <seed>]: u 500

 Player Dealer 
|  K♠  |  ** |
|  7♣  |  2♣ |
Round 1 Player's turn
hit, stand or withdraw ? [h/s/w] 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, stand or withdraw ? [h/s/w] h

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

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

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

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

 Player Dealer 
|  8♣  |  5♦ |
|  A♦  |  J♥ |
|  A♥  |  6♥ |
| 10♣  |     |
|  9♦  |     |
Player busts, dealer wins
You have $6
Do you want to play again? [y/n] n