Monica and Chandler at the craps table.

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

The rand() Function

I detailed description of the game comes later, but first let's talk about computers and randomness. Quite often in programming you need random numbers. For example, a key element if a game of chance is the random nature of something like rolling the dice. How to generate a random number on a computer is a science in and of itself, but the standard library cstdlib contains a function rand() that you can use.
    
#include <cstdlib>
It returns a "random" int in the range 0,...,RAND_MAX, where RAND_MAX is a variable defined in cstdlib.

The prototype for rand is:


int rand();   // needs #include <cstdlib>
So, if you need to print out 10 random numbers in the range [0,1], you could do the following:
    
for(int i = 0; i < 10; i++)
  cout << double(rand())/RAND_MAX << " ";
cout << endl;
If I run this, I get:

0.513871 0.175726 0.308634 0.534532 0.94763 0.171728 0.702231 0.226417 0.494766 0.124699

rand() is pseudorandom (not truely random)

Unfortunately, if I run it again, I get the same sequence of numbers! As a matter of fact, every time I run it, I get the same 10 "random" numbers! The problem is this, the computer doesn't generate random numbers. Instead, it has a long sequence of numbers that it generates, which looks more or less random - i.e. there is no discernable pattern. But every time I run my program, I just start over again with that same sequence.

Seeding rand()

To combat this, you can call srand(), which seeds the random number generator. Essentially, when you give srand a seed, it uses the seed to pick a starting point in this sequence of "random" numbers. With different starting points each time you run the program, you appear to be getting different sequences of random numbers.

Choosing a different seed in every run

Typically, you use the time() function from ctime to seed your random number generator. Since the time changes each time you run the program, you should get different sequences of "random" numbers. The following program shows how this all works:

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

int main()
{
  // Seed the random number generator based on the time
  srand(time(0));

  // Print out 10 random numbers in the range [0,1]
  for(int i = 0; i < 10; i++)
    cout << double(rand())/RAND_MAX << " ";
  cout << 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: Note: Getting a random number between 1 and 6 using the method above is not the best way to do it, but it will work for this lab.
The program should output the results of 5 rolls of the two die in the following format:
Player rolled 2 + 5 = 7
Player rolled 4 + 2 = 6
Player rolled 6 + 2 = 8
Player rolled 5 + 1 = 6
Player rolled 4 + 2 = 6

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()

As we saw in the lab intro, we can "seed" our random number generator 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. This code only needs to execute once, and it should be 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 4 + 4 = 8
Player rolled 6 + 2 = 8
Player rolled 6 + 4 = 10
Player rolled 3 + 2 = 5
Player rolled 1 + 2 = 3
~/$ ./p1
Enter seed value: 20
Player rolled 2 + 1 = 3
Player rolled 6 + 4 = 10
Player rolled 3 + 2 = 5
Player rolled 5 + 6 = 11
Player rolled 5 + 2 = 7

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 roll within the game.

    Result of throwdice(): The function returns an integer according to the following rules:

    situation return value
    if the house wins (see above) -1
    if the player wins (see above) 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 2 + 5 = 7 Player wins!

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

~/$ ./p2
Enter seed value: 2018
Player rolled 2 + 6 = 8 roll again
Player rolled 6 + 3 = 9 roll again
Player rolled 6 + 1 = 7 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 (house wins) 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 (house win) (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 6 + 6 = 12 House wins!
Play again? y
Player rolled 3 + 6 = 9 setpoint is 9!
Player rolled 3 + 2 = 5 roll again
Player rolled 6 + 1 = 7 House wins!
Play again? y
Player rolled 1 + 1 = 2 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 6 + 6 = 12 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