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 have explicit permission
  1. to get help from othee 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). Resources that might specifically address this project, say looking through code that implements blackjack or other card games, are not allowed. You are very specifically not allowed to look at previous semesters' IC210 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:

Part 1 [Up to 15pts] - Name your source code file part1.cpp

A part 1 solution will create and optionally shuffle a deck of cards, printing out the cards (one per line) represented as integers, as described below. Here are specifications:
  1. The user is presented with message: Shuffle: [n | s | u <seed>]: If they enter n, no shuffling will take place. Otherwise, we'll shuffle using a random number generator, which of course needs to be seeded. If they enter s then time(0) is used as the seed, as in part 2 of lab 6. Otherwise, the user must've given the u option followed by a number; this number is then used as the seed.
  2. Cards are represented by a single integer in the following way:

    1. represent suits by number according to these rules: 1 = ♣, 2 = ♦, 3 = ♥, 4 = ♠
    2. represent face values by number according to these rules: 2 = 2, 3 = 3, ..., 10 = 10, 11 = J(jack), 12 = Q(queen), 13 = K(king), 14 = A(ace)
    3. represent cards by number as follows: cardvalue = 100 × suitvalue + facevalue (which also means suitvalue = cardvalue / 100, and facevalue = cardvalue % 100)

    Example: K♠ → (facevalue=13,suitvalue=4) → 100*4 + 13 → 413
  3. The unshuffled deck (i.e. prior to shuffling, if shuffling is to occur) must be ordered by suit — clubs, then diamonds, then hearts, then spades — and cards of the same suit must be ordered from smallest (2) to largest (A).
  4. Shuffling must be done exactly as follows: assuming the cards are ordered as described above, and indexed from zero to 51:
      for i from 0 up to 51 do                                         Disclaimer: This is not a good enough shuffling algorithm for
        set j to rand() % 52                                                       "real" applications.  Some shuffled orders are
        swap the index i element of the deck with the index j element              more likely than others.
Sample runs: red text represents user input, brown text is explanatory and not part of the output
~/$ ./p1
Shuffle: [n | s | u <seed>]: n  
102 ← 100*1 + 2 ← 2♣
103 ← 100*1 + 3 ← 3♣
104 ← 100*1 + 4 ← 4♣
105 ← 100*1 + 5 ← 5♣

410 ← 100*4 + 10 ←10♠
411 ← 100*4 + 11 ← J♠
412 ← 100*4 + 12 ← Q♠
413 ← 100*4 + 13 ← K♠
414 ← 100*4 + 14 ← A♠
~/$ ./p1
Shuffle: [n | s | u <seed>]: u 2019  
107 ← 100*1 + 7 ← 7♣
403 ← 100*4 + 3 ← 3♠
203 ← 100*2 + 3 ← 3♦
408 ← 100*4 + 8 ← 8♠

413 ← 100*4 + 13 ← K♠
412 ← 100*4 + 12 ← Q♠
407 ← 100*4 + 7 ← 7♠
213 ← 100*2 + 13 ← K♦
414 ← 100*4 + 14 ← A♠
~/$ ./p1
Shuffle: [n | s | u <seed>]: u 2018  
310 ← 100*3 + 10 ←10♥
410 ← 100*4 + 10 ←10♠
313 ← 100*3 + 13 ← K♥
411 ← 100*4 + 11 ← J♠

208 ← 100*2 + 8 ← 8♦
308 ← 100*3 + 8 ← 8♥
205 ← 100*2 + 5 ← 5♦
111 ← 100*1 + 11 ← J♣
302 ← 100*3 + 2 ← 2♥
~/$ ./p1
Shuffle: [n | s | u <seed>]: s  
410
407
113  DIFFERENT
202  EVERY
   TIME
114  YOU
413  RUN IT
205
208
103

Part 2 [Up to 30pts] - Name your source code file part2.cpp

A part 2 solution should be exactly like the part 1 solution except that instead of printing the integer "cardvalues," you will print proper cards, e.g. instead of the integer 310 you'll print out the card 10♥. Here's how to do that: The only catch is that what you print out needs to be right justified, i.e. all the suit values (which come second) have to line up in the same column.

Sample runs: red text represents user input, brown text is explanatory and not part of the output
~/$ ./p2
Shuffle: [n | s | u <seed>]: n  
 2♣
 3♣
 4♣
 5♣

10♠
 J♠
 Q♠
 K♠
 A♠
~/$ ./p2
Shuffle: [n | s | u <seed>]: u 2019  
 7♣
 3♠
 3♦
 8♠

 K♠
 Q♠
 7♠
 K♦
 A♠
~/$ ./p2
Shuffle: [n | s | u <seed>]: u 2018  
10♥
10♠
 K♥
 J♠

 8♦
 8♥
 5♦
 J♣
 2♥
~/$ ./p2
Shuffle: [n | s | u <seed>]: s  
 Q♥
 J♣
 J♥  DIFFERENT
 2♣  EVERY
   TIME
 K♥  YOU
10♦  RUN IT
 6♦
 K♦
 Q♣

Part 3 [Up to 50pts] - Name your source code file part3.cpp

A correct part 3 solution will create and shuffle a deck as in Parts 1 & 2 (but not print the deck), and then simulate dealing cards to a "Player" and a "Dealer" in the following order: deal one card to "Player," one to "Dealer", one to "Player", and one to Dealer (so both have two cards). Then display (as shown below). Then three rounds of dealing first one card to "Player," then one card to "Dealer," then displaying the hands (once again as shown below). Note that the "top" of the deck is the first card as printed out by your Part 1 & Part 2 solutions, and you must deal from the top of the deck (in the Old West, people got shot for violating this rule!). Thus, your program's output really must match what is shown below for the given examples.

Note: You really want to have your program simulate dealing a card to a hand. You should be able to point to few variables and say "those represent the player's hand," and point to a few more and say "those represent the dealer's hand."

Sample runs: red text represents user input, brown text is explanatory and not part of the output
~/$ ./p3
Shuffle: [n | s | u <seed>]: u 42  
               ← deck:K♠ 10♦ 2♦ 10♠ Q♥ 4♦ K♥ J♠ 7♥ 2♥ 8♦ Q♠ 3♥ 8♣ …
 Player Dealer
|  K♠  | 10♦  |
|  2♦  | 10♠  |
               ← deck:K♠ 10♦ 2♦ 10♠ Q♥ 4♦ K♥ J♠ 7♥ 2♥ 8♦ Q♠ 3♥ 8♣ …
 Player Dealer
|  K♠  | 10♦  |
|  2♦  | 10♠  |
|  Q♥  |  4♦  |
               ← deck:K♠ 10♦ 2♦ 10♠ Q♥ 4♦ K♥ J♠ 7♥ 2♥ 8♦ Q♠ 3♥ 8♣ …
 Player Dealer
|  K♠  | 10♦  |
|  2♦  | 10♠  |
|  Q♥  |  4♦  |
|  K♥  |  J♠  |
               ← deck:K♠ 10♦ 2♦ 10♠ Q♥ 4♦ K♥ J♠ 7♥ 2♥ 8♦ Q♠ 3♥ 8♣ …
 Player Dealer
|  K♠  | 10♦  |
|  2♦  | 10♠  |
|  Q♥  |  4♦  |
|  K♥  |  J♠  |
|  7♥  |  2♥  |
~/$ ./p3
Shuffle: [n | s | u <seed>]: u 314  

 Player Dealer
|  J♠  |  4♣  |
|  5♦  |  7♥  |

 Player Dealer
|  J♠  |  4♣  |
|  5♦  |  7♥  |
|  8♠  |  6♣  |

 Player Dealer
|  J♠  |  4♣  |
|  5♦  |  7♥  |
|  8♠  |  6♣  |
|  8♦  |  J♥  |

 Player Dealer
|  J♠  |  4♣  |
|  5♦  |  7♥  |
|  8♠  |  6♣  |
|  8♦  |  J♥  |
|  Q♦  |  Q♠  |
~/$ ./p3
Shuffle: [n | s | u <seed>]: u 9376  

 Player Dealer
|  3♦  |  9♣  |
|  Q♥  |  J♥  |

 Player Dealer
|  3♦  |  9♣  |
|  Q♥  |  J♥  |
| 10♥  |  9♠  |

 Player Dealer
|  3♦  |  9♣  |
|  Q♥  |  J♥  |
| 10♥  |  9♠  |
|  8♣  |  2♥  |

 Player Dealer
|  3♦  |  9♣  |
|  Q♥  |  J♥  |
| 10♥  |  9♠  |
|  8♣  |  2♥  |
|  6♦  |  A♣  |

Part 4 [Up to 70pts] - Name your source code file part4.cpp

A correct part 4 solution will start to play something that actually looks like a game. Player and Dealer will both be dealt two cards (as in part 3). But then the program will proceed to ask the Player and Dealer in turns whether they want to "hit" (in which case they get dealt another card into their hand), or to "stand" in which case their hand stays the same. [Note: In this project, the player or dealer can "stand" one round, then "hit" the next — which is not allowed in real blackjack.] The player goes first, and the program should go through three rounds (i.e. the Player and the Dealer both get three turns). In between rounds (i.e. just before printing out the current hands), make the call system("clear"); to clear the terminal window, so that only the current state of the game is showing at any given time. Below is an example of how a game might play out. Your output and the way you get input from the user must match what's shown here.

Note: In the submit system, each call to system("clear") shows up as the character sequence: [H[2J

Sample run: red text represents user input
~/$ ./p4
Shuffle: [n | s | 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♦  |    

Part 5 [Up to 85pts] - Name your source code file part5.cpp

A correct part 5 solution should behave exactly like a correct part 4 solution, except that in each round the current "best scores" for both Player and Dealer hands should be shown. The "best score" for a hand is computed according to the following rules. Add up points for each card in the hand, where aces are worth one point, kings, queens and jacks are worth 10 points, and numbered cards (i.e. 2 though 10) are worth their number in points. Call this number total. If the hand has no aces, total is the "best score" for the hand. If there are aces in the hand, and total + 10 is not greater than 21, the "best score" is total + 10. Otherwise, "best score" is simply total.

Sample run: red text represents user input
~/$ ./p5
Shuffle: [n | s | u <seed>]: u 92  
 Player Dealer
|  Q♦  |  A♣  |
|  8♣  |  7♣  |
Player 18, Dealer 18
Round 1 Player's turn
hit or stand? [h/s] s  
 Player Dealer
|  Q♦  |  A♣  |
|  8♣  |  7♣  |
Player 18, Dealer 18
Round 1 Dealer's turn
hit or stand? [h/s] h  

Notice that the A♣ is
counted as 11 points
int the dealer's hand
 Player Dealer
|  Q♦  |  A♣  |
|  8♣  |  7♣  |
|      |  6♠  |
Player 18, Dealer 14
Round 2 Player's turn
hit or stand? [h/s] s  
 Player Dealer
|  Q♦  |  A♣  |
|  8♣  |  7♣  |
|      |  6♠  |
Player 18, Dealer 14
Round 2 Dealer's turn
hit or stand? [h/s] h  

Notice that the A♣ is
is now counted as
just 1 point in the
dealer's hand
 Player Dealer
|  Q♦  |  A♣  |
|  8♣  |  7♣  |
|      |  6♠  |
|      |  4♥  |
Player 18, Dealer 18
Round 3 Player's turn
hit or stand? [h/s] h  
 Player Dealer
|  Q♦  |  A♣  |
|  8♣  |  7♣  |
|  2♣  |  6♠  |
|      |  4♥  |
Player 20, Dealer 18
Round 3 Dealer's turn
hit or stand? [h/s] h  
 Player Dealer     
|  Q♦  |  A♣  |
|  8♣  |  7♣  |
|  2♣  |  6♠  |
|      |  4♥  |
|      |  9♠  |

Note: You might like to look at another worked Part 5 example.

Part 6 [Up to 95pts] - Name your source code file part6.cpp

A part 6 solution functions just like a part 5 solution with the following two exceptions:

Sample run: red text represents user input
~/$ ./p6
Shuffle: [n | s | u <seed>]: u 314  
 Player Dealer
|  J♠  |  4♣  |
|  5♦  |  7♥  |
Player 15, Dealer 11
Round 1 Player's turn
hit or stand? [h/s] s  
 Player Dealer
|  J♠  |  4♣  |
|  5♦  |  7♥  |
Player 15, Dealer 11
Round 1 Dealer's turn
hit or stand? [h/s] h  
 Player Dealer
|  J♠  |  4♣  |
|  5♦  |  7♥  |
|      |  8♠  |
Player 15, Dealer 19
Round 2 Player's turn
hit or stand? [h/s] h  
 Player Dealer
|  J♠  |  4♣  |
|  5♦  |  7♥  |
|  6♣  |  8♠  |
Player 21, Dealer 19
Round 2 Dealer's turn
hit or stand? [h/s] s  
Note: The game stops
because of consecutive
"stand" moves.
 Player Dealer
|  J♠  |  4♣  |
|  5♦  |  7♥  |
|  6♣  |  8♠  |
Player 21, Dealer 19
Round 3 Player's turn
hit or stand? [h/s] s  
 Player Dealer
|  J♠  |  4♣  |
|  5♦  |  7♥  |
|  6♣  |  8♠  |
Player 21, Dealer 19

Sample run: red text represents user input
~/$ ./p6
Shuffle: [n | s | u <seed>]: u 349  
 Player Dealer
|  J♦  |  A♠  |
|  8♣  |  6♠  |
Player 18, Dealer 17
Round 1 Player's turn
hit or stand? [h/s] h  
 Player Dealer
|  J♦  |  A♠  |
|  8♣  |  6♠  |
|  5♥  |      |
Player 23, Dealer 17

Note: The game stops
because the Player
"busts". Hitting on
18 was crazy!

Part 7 [Up to 100pts] - Name your source code file part7.cpp

A part 7 solution functions like a part 6 solution with the following modifications:

Sample run: red text represents user input
~/$ ./p7
Shuffle: [n | s | 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 | s | 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 [Up to 110pts] - Name your source code file partX.cpp

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

Your extra credit solution should play the game over and over again. Each time the player finishes a game, the program should ask whether the player wants to play again or quit. Each play the player must make a $5 bet. If the player wins, the player gets the bet plus some amount of winnings back. You may decide what the payouts are (could be as simple as getting your bet plus $5 back). You must report the players winnings / losses at the end of each round. The player must have the option of withdrawing from a game (not the table, just that game) after the initial two cards are dealt to player and dealer, but before any other play has taken place. Withdrawing means half the bet is returned to the player, but the other half goes to the house.


When to submit

Part 1 of Project 2 must be submitted electronically, and pass all Part 1 tests, by 1530 on Tuesday, October 25th. There is no paper submission at that point. You will submit with:
~/bin/submit -c=IC210 -p=proj02 part1.cpp
The full Project 2 submission is due by COB on Monday, October 31st, according to the course's particular definition of "COB". Late projects incur a penalty of 3N points, where N is the number of days late. So, a project that is not turned in by COB Monday, 31 October, but which is turned in by COB Tuesday receives a 3 point penalty. A project that is not turned in by COB Tuesday, but which is turned in by COB Wednesday receives a 9 point penalty. And so on. You will submit with:
~/bin/submit -c=IC210 -p=proj02 part1.cpp part2.cpp part3.cpp part4.cpp part5.cpp part6.cpp part7.cpp partX.cpp

What to submit

You will submit the furthest properly functioning solution. So, if your Part 7 solution works, submit the Part 7 solution. If you don't have a properly functioning Part 7 solution, but your Part 6 solution works fine, submit a Part 6 solution. And so on. Note that what you submit must work, and absolutely must compile! What gets submitted is:
  1. Your source code (i.e the .cpp file). You will submit a printout of this (use codeprint) and an electronic copy (how to do the electronic submission will be explained later).
  2. A completed copy of this coversheet on paper.

How to submit

The paper portions of your submission should be stapled together and slid under your prof's door. Instructions on electronic submission: go to the directory with the project files and type:
~/bin/submit -c=IC210 -p=proj02 part1.cpp part2.cpp part3.cpp part4.cpp part5.cpp part6.cpp part7.cpp partX.cpp

How projects are graded / how to maximize your points

Things to keep in mind to receive full marks:
  1. Submit all required items (as described above) on time.
  2. Make sure the form of your output matches the form of the example output in all ways. Of course the cards you see and decisions dealer and player make will vary from the examples you see.
  3. Make sure you follow the IC210 Style Guide. This means proper indentation, use of whitespace within lines of code, logical organization of chunks of code,
  4. Make sure you do a good job of putting things in functions. One monolithic main function is not OK, even if it works! The quality of your overall design will play a role, and a large part of that boils down to using functions well.
Most important: Look at the the grading sheet.