Monica and Chandler at the craps table.

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

Introduction 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 something 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();   // needs #include <cstdlib>

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 following:
Requirement 1:
Requirement 2: Implement your rolldie() function as follows:
  1. Get a random number by computing rand()%8.
  2. If the number is between 1 and 6 (inclusive), it's good. Return the number.
  3. Otherwise, the number is not legitimate. Try again by going back to step 1.
Rationale behind Requirement 2: 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 rand()%6. This would certainly give you a number in the range 0,1,2,3,4,5 - and in fact you can do it this way and it will work (you may need to add 1 to get the range to be 1 up to 6).

However, it turns out that what rand() gives us is 31 random bits, which means a random(ish) number between 0 and 231 - 1. In other words, there are 231 possibilities. Since 231 is not a multiple of 6, I am slightly more likely to get 0 or 1 out of this than other numbers.

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

The program should output the results of 5 rolls of the two die in the following format:
Player rolled 6 + 1 = 7
Player rolled 3 + 1 = 4
Player rolled 2 + 4 = 6
Player rolled 1 + 5 = 6
Player rolled 2 + 3 = 5

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

Q: Run your program three times in succession. What do you note about the output?

Answer: The output is always the same.

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.

Seeding rand()

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.

Quick check:

  1. How many times do you call srand() in your program?
     Answer (drag a mouse): only once
  2. How may times do you call rand() in your program?
     Answer (drag a mouse): many times (i.e., every time you need to choose a random number) 
  3. When do you have to call srand() in your program?
     Answer (drag a mouse): before the the first function call of rand() 

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 5 + 3 = 8
Player rolled 3 + 5 = 8
Player rolled 3 + 2 = 5
Player rolled 1 + 1 = 2
Player rolled 3 + 1 = 4
~/$ ./p1
Enter seed value: 20
Player rolled 2 + 1 = 3
Player rolled 5 + 6 = 11
Player rolled 1 + 1 = 2
Player rolled 6 + 4 = 10
Player rolled 1 + 1 = 2

Submission

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

Part 2 : Craps

Now we will write a program that simulates a dice game Craps played by two parties: the player and the house. The rules for your game of Craps are as follows:
Requirement 3:
  • Define and use in your program a function with prototype:
    
    int throwdice();
    
    This function simulates a single throw of two dice and the processing of that role within the game.

    Output of throwdice(): The function returns an integer according to the following rule.

    situation return value
    if the house wins -1
    if the player wins 0
    if neither wins the actual sum of the two dice rolls

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: 1
Player rolled 6 + 1 = 7 Player wins!

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

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

Submission

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

Part 3: "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 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.

~/$ ./p3
Enter seed value: 107
Player rolled 5 + 5 = 10 setpoint is 10!
Player rolled 4 + 4 = 8 roll again
Player rolled 5 + 3 = 8 roll again
Player rolled 6 + 2 = 8 roll again
Player rolled 6 + 1 = 7 House wins!
Play again? y
Player rolled 5 + 4 = 9 setpoint is 9!
Player rolled 3 + 1 = 4 roll again
Player rolled 2 + 2 = 4 roll again
Player rolled 2 + 3 = 5 roll again
Player rolled 2 + 4 = 6 roll again
Player rolled 1 + 2 = 3 roll again
Player rolled 1 + 1 = 2 roll again
Player rolled 5 + 6 = 11 roll again
Player rolled 3 + 2 = 5 roll again
Player rolled 2 + 3 = 5 roll again
Player rolled 1 + 2 = 3 roll again
Player rolled 5 + 1 = 6 roll again
Player rolled 6 + 2 = 8 roll again
Player rolled 2 + 5 = 7 House wins!
Play again? y
Player rolled 5 + 3 = 8 setpoint is 8!
Player rolled 1 + 1 = 2 roll again
Player rolled 2 + 1 = 3 roll again
Player rolled 1 + 5 = 6 roll again
Player rolled 2 + 3 = 5 roll again
Player rolled 2 + 2 = 4 roll again
Player rolled 4 + 1 = 5 roll again
Player rolled 1 + 3 = 4 roll again
Player rolled 3 + 3 = 6 roll again
Player rolled 4 + 6 = 10 roll again
Player rolled 6 + 1 = 7 House wins!
Play again? y
Player rolled 2 + 1 = 3 House wins!
Play again? y
Player rolled 1 + 2 = 3 House 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=IC210 -p=lab06 p1.cpp p2.cpp p3.cpp

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

Create p4.cpp, and 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=IC210 -p=lab06 p1.cpp p2.cpp p3.cpp p4.cpp