Executive Summary

You will build a version of the dice game "craps". 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 that is at least 32,767). The number returned will at least appear to have been randomly chosen in the range.

to submit: Please call your source code files p1.cpp, p2.cpp, ...p5.cpp. Then, to submit give the command:

~/bin/submit  -c=IC210 -p=Lab06 p?.cpp

Part 1 : "Let's Roll"

Write a program 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
You must ... define and use in your program a function with prototype int roll1(); that simulates a single roll of a single 6-sided die!
To use the rand function, you must include the cstdlib library. The prototype for rand is:
int rand();
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() really gives us is 31 random bits, which means a random(ish) number between 0 and 2^31 - 1.. Since (2^31 - 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, since 8 divides 2^31 evenly, if I take rand() % 8 I am equally likely to get any of 0,1,2,3,4,5,6,7. So, a better approach is to take rand() % 8 over and over until I get something in the range 0,1,2,3,4,5, and then add one to the result. Do it the other way, and your dice are ever-so-slightly loaded!

Part 2 : "Why am I going to Jail?

Run your program from Part 1 three times in succession. What do you note about the output? Nothing random about it! You will be brought up on charges by the Gaming Commission if you implement a "craps" game using this random number generator. 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 to your code from Part 1 the following code:

int seed;
cout << "Enter a seed value: ";
cin >> seed;
srand(seed);
so that it appears as the first thing in "main". Execute your program three times using different seed values. Your results will be different for each new seed.

Execute your program three times using the same seed value. You will observe the same sequence! Here comes the Gaming Commission again! We do not want to have the user generate the "seed" because output can be predicted based on the seed value.

How can we seed our RNG without input from the user and have unpredictable seed values? Let's use a function from the ctime library. The function call time(0) returns an integer that is the number of seconds ellapsed since 00:00 hours, Jan 1, 1970. This is a continuously changing value that does not repeat, so it makes a great seed value. modify your Part 1 solution by including the ctime function and adding the line

srand(time(0));
... as the first statement in your main() function. Run your program several times. You should no longer notice any predictable patterns in the results. Note: Only seed the random number generator once, typically at the beginning of a program. If you seed it before every call to rand, you'll be resetting the sequence constantly, and it won't look very random.

Part 3 : Craps

The rules for your game of craps are as follows: If the player rolls a 7 or 11 then the player wins. If the player rolls a 2, 3, or 12 the house wins. The player will continue to roll until either the player or the house wins. Your main program must use a function named "throw1" (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:
// throw1() returns -1, 0 or a positive number.
// -1 means house wins, 0 means player wins, a positive number
// means neither won, and the number is the sum of the two dice rolls
int throw1();
Using the function throw1(), 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!
~/$ ./p3
Round 1: Player rolled 1 + 4 = 5 ... no winner, roll again!
Round 2: Player rolled 1 + 2 = 3 House wins!
~/$ ./p3
Round 1: Player rolled 6 + 3 = 9 ... no winner, roll again!
Round 2: Player rolled 2 + 4 = 6 ... no winner, roll again!
Round 3: Player rolled 6 + 1 = 7 Player wins!
~/$ ./p3
Round 1: Player rolled 5 + 2 = 7 Player wins!

Part 4 : "You're Fired!"

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 2, 3, 7, or 12 for a loss (7 is a loser for the player unless rolled on the first try).
Below are some sample outputs.
Note: Once again, your output format must match these exmples exactly!
~/$ ./p4
Round 1: Player rolled 2 + 3 = 5 ... no winner, setpoint is 5!
Round 2: Player rolled 1 + 3 = 4 ... no winner, roll again!
Round 3: Player rolled 1 + 3 = 4 ... no winner, roll again!
Round 4: Player rolled 4 + 1 = 5 Player wins!
~/$ ./p4
Round 1: Player rolled 1 + 2 = 3 House wins!
~/$ ./p4
Round 1: Player rolled 3 + 5 = 8 ... no winner, setpoint is 8!
Round 2: Player rolled 6 + 6 = 12 House wins!
~/$ ./p4
Round 1: Player rolled 5 + 6 = 11 Player wins!
Hint: think about adding a parameter setpoint to your throw1() 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 throw1() to determine which case you're in. Or you might do something altogether different.

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

The last thing to do is deal with multiple games and money.
  1. After each game, ask the player if he wants to play again, and continue to play until the player wants to quit.
  2. 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".
Note: you must create and use a function with the following prototype:
// reports to user, asks whether they want to continue, returns true
// if they do, and false if they want to stop.
bool playAgainQuery(int win, int loss);
Below are some sample outputs.
Note: Once again, your output format must match these exmples exactly!
$ ./p5
Round 1: Player rolled 4 + 2 = 6 ... no winner, setpoint is 6!
Round 2: Player rolled 6 + 6 = 12 House wins!
You've played 1 times, and are down $5.
Would you like to play again? (y/n)  y
Round 1: Player rolled 5 + 6 = 11 Player wins!
You've played 2 times, and are dead even.
Would you like to play again? (y/n)  y
Round 1: Player rolled 4 + 3 = 7 Player wins!
You've played 3 times, and are up $5.
Would you like to play again? (y/n)  y
Round 1: Player rolled 5 + 1 = 6 ... no winner, setpoint is 6!
Round 2: Player rolled 3 + 2 = 5 ... no winner, roll again!
Round 3: Player rolled 2 + 4 = 6 Player wins!
You've played 4 times, and are up $10.
Would you like to play again? (y/n)  n