SI 204 Spring 2017 / Labs


This is the archived website of SI 204 from the Spring 2017 semester. Feel free to browse around; you may also find more recent offerings at my teaching page.

Lab 05: Vegas Baby!

For this lab, you will build a version of the dice game “craps”. This will require you to write some useful functions and make use of C’s built-in random number generator function rand().

1 Let’s Roll

In this part, you will write a program called roll.c that simulates the roll of two six-sided die.

1.1 A new header file

Your program will use a new header file <stdlib.h> that has (among other useful things) the following functions:

  • void exit(int status)

    This exists your program at the given spot with the given return code. So doing exit(2) for example is the same as calling return 2 from your main. The difference is, you can call exit from anywhere! So it’s useful when you need to exit the program from the middle of a function call.

    You don’t necessarily need exit for this lab but it’s good to know about.

  • int rand()

    This function returns a random-looking number between 0 and RAND_MAX. (RAND_MAX is a constant defined in the header file that is \(2^{31}-1\) on your computer but might be bigger or larger in some other C implementation.)

    Note that rand() returns a different number every time you call it in your program - that’s the whole point!

  • void srand(int seed)

    Well it turns out rand() isn’t so random after all. Every time you call rand() within your program it gives a different number, but that sequence of random numbers is the same every time you run the program! To get a different random (looking) sequence, you have to set a different starting point, or “seed”, using srand. So for example to set the seed to 7, you would do the following near the beginning of your program:

    srand(7);

    Important: Remember that this is just starting rand() out on an appropriate sequence of random looking numbers. You should (in general) only call srand once in a given run of the program — otherwise you might go back in the sequence and start seeing repeats!

1.2 A function to roll a die

Start your roll.c program with the usual stuff and be sure to #include <stdlib.h> as well.

Now we want to write a function that uses rand() to simulate the roll of a single 6-sided die. This function doesn’t need any arguments, and it should return an int between 1 and 6. So the prototype that goes above your main() will be:

int rolldie();

and the definition that goes below your main block will look like

int rolldie() {
  // The code for rolldie goes in here.
  // It should end with a return statement!
}

Now how do we get a random number between 1 and 6? Remember that rand() returns a number between 0 and RAND_MAX. 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. However, since (on your computer at least) RAND_MAX % 6 equals 1, that means there’s an ever so slightly larger chance that rand() % 6 will equal 0 or 1, and hence your die would be “weighted” in favor of rolling a 1 or a 2. That’s no good!

If instead 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.

Roughly speaking, your rolldie() function will follow this approach:

compute 1 + rand()%8
if that number is <= 6, then return it.
otherwise, compute a new 1 + rand()%8 and start over until it is <= 6

Ask your instructor if you get stuck here!

1.3 Rolling two dice

Now that you have your int rolldie() function all set, it’s time to actually write a main that uses it.

Your program should first ask the user for what seed value they want to use, and call srand to “seed” the random number generator with that value.

Then use your rolldie() function to repeatedly simulate rolling two die and show them added up. For your roll.c program, roll two dice 5 times and then quit. For example:

roche@ubuntu$ ./roll
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
roche@ubuntu$ ./roll
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

Note: The numbers you see with those seed values should be exactly what is shown above. If not, there may be a problem with your rolldie() function — ask your instructor for help if necessary.

2 Oh craps

Now it’s time to write a simplified version of the craps game. Start by copying your perfectly-working rolldie.c to a new file craps.c. Your main() will change quite a bit for this part, but the rolldie() function you wrote should stay exactly the same!

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 “throwdice” (which you’ll create) that simulates a single throw of two die and the processing of that roll within the game. It must have the following prototype:

// throwdice() 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 throwdice();

Using the function throwdice(), your program will simulate craps up until either the player or the house wins.

Note: You’re going to have to give some thought to what gets printed inside main and what gets printed inside throwdice.

Examples:

roche@ubuntu$ ./craps
Enter seed value: 10
Player rolled 1 + 6 = 7 Player wins!
roche@ubuntu$ ./craps
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!
roche@ubuntu$ ./craps
Enter seed value: 1984
Player rolled 6 + 2 = 8 roll again
Player rolled 6 + 5 = 11 Player wins!

3 You’re Fired! (going further)

Copy your craps.c program to a new file realcraps.c.

The owner of the casino runs an 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:

  • On the first roll, you win on 7 or 11, and you lose with 2, 3, or 12. (This is the same as before.)
  • 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 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.

roche@ubuntu$ ./realcraps
Enter seed value: 107
Player rolled 6 + 6 = 12 House wins!
Play again? y
Player rolled 5 + 5 = 10 roll again
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 roll again
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
roche@ubuntu$ ./realcraps
Enter seed value: 100
Player rolled 1 + 6 = 7 Player wins!
Play again? y
Player rolled 5 + 1 = 6 roll again
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 roll again
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.

4 Rigging the game (Bonus!)

Come up with a seed value that wins as many games in a row as you can, in the program realcraps from the last part. For example, a seed value of 9 wins 3 games in a row.

In a CLEAR COMMENT at the beginning of your realcraps.c file, indicate the seed value to use, and tell me how many games in a row you would win with that seed value.

The winningest seed in your section will win a small prize!

Hint: If I were you, I would make a new program to help with this part. But I’m not going to tell you how that program should work! If you do that, you should call your program brute.c and submit it along with the rest of your code. There are no auto-tests for brute because it’s up to you how it works - just be sure to include the magic seed value in comments at the beginning of realcraps.c.