Dice Game: Craps

Monica and Chandler at the craps table.

In this lab, you will build a version of the dice game "craps"!

Intrudction to rand()

A detailed explanation of the game comes later. First, however, a note on randomness and computer programs. A key element of any game of chance is the random nature of somthing like rolling the dice. How do we introduce "randomness" into a computer program, which is structured specifically to be "non-random"? Well, the standard library cstdlib has a function called rand which generates "random" numbers. The rand function returns an integer between 0 and RAND_MAX (a number defined in cstdlib). The number returned will at least appear to have been randomly chosen in the range.

More specifically, to use the rand function, you must include the cstdlib library. The prototype for rand is:

int rand();

For example, the following code will output a random number:

#include <iostream>
#include <cstdlib>     // include cstdlib!!
using namespace std;

int main() {
  int num = rand();       // call rand()!!
  cout << "Random number: " << num << endl;
  return 0;
}

Part 1 : "Let's Roll"

Write a code p1.cpp that simulates the roll of two six-sided die. The program should output the results of 5 rolls of the two die in the following format:
Player rolled 6 + 4 = 10
Player rolled 6 + 4 = 10
Player rolled 1 + 5 = 6
Player rolled 6 + 3 = 9
Player rolled 4 + 6 = 10
Requirement 1:

Tip. How to do you transform a random number between 0 and RAND_MAX into a random number from 1 through 6? You might be tempted to do something like 1 + (rand()%6). This would certainly give you a number in the range 1,2,3,4,5,6 - and you can do it this way if you want.

However, it turns out that what rand() gives us is 31 random bits, which means a random(ish) number between 0 and 231 - 1. Since (231 - 1) % 6 = 1, I am slightly more likely to get 0 or 1 out of this than 2,3,4,5,6.

On the other hand, if you do 1+rand()%8, there's no bias; this returns a number in the range 1,2,3,4,5,6,7,8 with equal probability (since 8 is a power of 2). But now you don't have a 6-sided die! So you keep doing this until 1 + rand()%8 is actually in the desired range of 1 up to 6.

Requirement 2: Implement your rolldie() function as follows:
  1. Compute 1 + rand()%8
  2. If the number is between 1 and 6 (inclusive), return it.
  3. Otherwise, repeat step 1.

rand() is not random! We need a random seed

Run your program three times in succession. What do you note about the output? Nothing random about it!

The reason for this repeating sequence is not accidental. In order to debug a program that uses a random number generator like rand(), it may be important to repeat the same sequence. Once the program is debugged, we can "seed" our RNG to create a changing sequence.

We use the function srand to "seed" rand. The idea is that the particular sequence of seemingly random numbers rand produces will actually depend on the seed value - different seed values will produce wildly different sequences.

Add the following code snippet to your p1.cpp before using the rand() function:

int seed;
cout << "Enter seed value: ";
cin >> seed;
srand(seed);
Your program should work exactly as follows:
~/$ ./p1
Enter seed value: 7
Player rolled 6 + 4 = 10
Player rolled 4 + 6 = 10
Player rolled 4 + 3 = 7
Player rolled 2 + 1 = 3
Player rolled 2 + 4 = 6
~/$ ./p1
Enter seed value: 20
Player rolled 3 + 2 = 5
Player rolled 1 + 6 = 7
Player rolled 2 + 1 = 3
Player rolled 2 + 5 = 7
Player rolled 2 + 1 = 3

Submission

~/bin/submit -c=si204 -p=lab06 p1.cpp

Part 2 : Craps

The rules for your game of craps are as follows: Your main program must use a function named throwdice (which you'll create) that simulates a single throw of two die and the processing of that role within the game. It must have the following prototype:
// throwdice() returns -1, 0 or a positive number.
// -1 means house wins, and 0 means player wins.
// A positive number means neither won, the number 
// is the actual sum of the two dice rolls
int throwdice();

Using the function throwdice(), your program will simulate craps up until either the player or the house wins.
Note 1: You're going to have to give some thought to which function is responsible for printing what.
Note 2: Your output format must match the examples exactly!

Sample runs are shown below:

~/$ ./p2
Enter seed value: 10
Player rolled 1 + 6 = 7 Player wins!

~/$ ./p2
Enter seed value: 13
Player rolled 3 + 6 = 9 roll again
Player rolled 5 + 1 = 6 roll again
Player rolled 1 + 4 = 5 roll again
Player rolled 2 + 4 = 6 roll again
Player rolled 4 + 4 = 8 roll again
Player rolled 4 + 6 = 10 roll again
Player rolled 1 + 1 = 2 House wins!

~/$ ./p2
Enter seed value: 1984
Player rolled 6 + 2 = 8 roll again
Player rolled 6 + 5 = 11 Player wins!

~/$ ./p2
Enter seed value: 10
Player rolled 1 + 6 = 7 Player wins!

Submission

~/bin/submit -c=si204 -p=lab06 p1.cpp p2.cpp

Part 3: C language

Make a copy of your p2.cpp file to p3.c. Now change your code in p3.c from C++ to the C language. It must compile with "gcc p3.c".

Remember that the included libraries must also change. You've learned that instead of iostream we now need stdio.h. But this lab also uses rand which came from #include <cstdlib>. This is actually a C++ verison of the C library: #include <stdlib.h>

When finished, check your submission:

~/bin/submit -c=si204 -p=lab06 p1.cpp p2.cpp p3.c

Part 4: "You're Fired!"

For this part, adapt your C++ version of p2.cpp to p4.cpp.

The owner of the casino, runs analysis on your craps program and sees the odds are stacked in favor of the player. He orders you to implement a version that favors the house. After showing your game to a math professor, the following rules are added to your game.

  1. On the first roll, you win on 7 or 11, and you lose with 2, 3, or 12. Game over.
  2. If the first roll is 4, 5, 6, 8, 9, or 10, then the number rolled becomes your setpoint. You then repeatedly roll the die until:
    • You either roll your setpoint for a win, or
    • you roll a 7 or 12 for a loss (7 is a loser for the player unless rolled on the first try).
Besides these rule changes, you should also let the player keep playing as long as they want. After each game ends, ask the player to enter y or n if they want to play another game or not.

Below are some sample outputs.

~/$ ./p4
Enter seed value: 107
Player rolled 6 + 6 = 12 House wins!
Play again? y
Player rolled 5 + 5 = 10 setpoint is 10! 
Player rolled 6 + 4 = 10 Player wins!
Play again? y
Player rolled 1 + 1 = 2 House wins!
Play again? y
Player rolled 3 + 2 = 5 setpoint is 5!
Player rolled 6 + 5 = 11 roll again
Player rolled 4 + 2 = 6 roll again
Player rolled 3 + 3 = 6 roll again
Player rolled 3 + 4 = 7 House wins!
Play again? n
~/$ ./p4
Enter seed value: 100
Player rolled 1 + 6 = 7 Player wins!
Play again? y
Player rolled 5 + 1 = 6 setpoint is 6!
Player rolled 2 + 6 = 8 roll again
Player rolled 4 + 5 = 9 roll again
Player rolled 5 + 6 = 11 roll again
Player rolled 4 + 3 = 7 House wins!
Play again? y
Player rolled 6 + 5 = 11 Player wins!
Play again? y
Player rolled 3 + 6 = 9 setpoint is 9!
Player rolled 5 + 3 = 8 roll again
Player rolled 6 + 4 = 10 roll again
Player rolled 2 + 4 = 6 roll again
Player rolled 5 + 5 = 10 roll again
Player rolled 2 + 6 = 8 roll again
Player rolled 1 + 2 = 3 roll again
Player rolled 5 + 3 = 8 roll again
Player rolled 1 + 2 = 3 roll again
Player rolled 6 + 5 = 11 roll again
Player rolled 6 + 3 = 9 Player wins!
Play again? n

Hint: think about adding a parameter setpoint to your throwdice() function. This would allow you to deal with throws after the first. Of course you still have to deal with the first throw. You might make different functions to distinguish the first from the following throws. Or you might use arguments to throwdice() to determine which case you're in. Or you might do something altogether different.

Submission

~/bin/submit -c=si204 -p=lab06 p1.cpp p2.cpp p3.c p4.cpp

Part 5: Going Further, "Show me the money"

Copy p4.cpp to a new file p5.cpp.

You can have the program additionally deal with money. For example:

  • For each game treat "the bet" as $5. Player wins, he gets $5. House wins, the house gets $5.
  • Before asking the player to play again, your program will report how many games have been played and where the player currently stands financially: "up $X", "down $X", or "dead even".

Submission

~/bin/submit -c=si204 -p=lab06 p1.cpp p2.cpp p3.c p4.cpp p5.cpp