In this section, we simulate the popular dice game known as “craps.” Here is the requirements statement:
You roll two six-sided dice, each with faces containing one, two, three, four, five and six spots, respectively. When the dice come to rest, the sum of the spots on the two upward faces is calculated. If the sum is 7 or 11 on the first roll, you win. If the sum is 2, 3 or 12 on the first roll (called “craps”), you lose (i.e., the “house” wins). If the sum is 4, 5, 6, 8, 9 or 10 on the first roll, that sum becomes your “point.” To win, you must continue rolling the dice until you “make your point” (i.e., roll that same point value). You lose by rolling a 7 before making your point.
The following script simulates the game and shows several sample executions, illustrating winning on the first roll, losing on the first roll, winning on a subsequent roll and losing on a subsequent roll.
1 # fig04_02.py 2 """Simulating the dice game Craps.""" 3 import random 4 5 def roll_dice(): 6 """Roll two dice and return their face values as a tuple.""" 7 die1 = random.randrange(1, 7) 8 die2 = random.randrange(1, 7) 9 return (die1, die2) # pack die face values into a tuple 10 11 def display_dice(dice): 12 """Display one roll of the two dice.""" 13 die1, die2 = dice # unpack the tuple into variables die1 and die2 14 print(f'Player rolled {die1} + {die2} = {sum(dice)}') 15 16 die_values = roll_dice() # first roll 17 display_dice(die_values) 18 19 # determine game status and point, based on first roll 20 sum_of_dice = sum(die_values) 21 22 if sum_of_dice in (7, 11): # win 23 game_status = 'WON' 24 elif sum_of_dice in (2, 3, 12): # lose 25 game_status = 'LOST' 26 else: # remember point 27 game_status = 'CONTINUE' 28 my_point = sum_of_dice 29 print('Point is', my_point) 30 31 # continue rolling until player wins or loses 32 while game_status == 'CONTINUE': 33 die_values = roll_dice() 34 display_dice(die_values) 35 sum_of_dice = sum(die_values) 36 37 if sum_of_dice == my_point: # win by making point 38 game_status = 'WON' 39 elif sum_of_dice == 7: # lose by rolling 7 40 game_status = 'LOST' 41 42 # display "wins" or "loses" message 43 if game_status == 'WON': 44 print('Player wins') 45 else: 46 print('Player loses')
Player rolled 2 + 5 = 7 Player wins
Player rolled 1 + 2 = 3 Player loses
Player rolled 5 + 4 = 9 Point is 9 Player rolled 4 + 4 = 8 Player rolled 2 + 3 = 5 Player rolled 5 + 4 = 9 Player wins
Player rolled 1 + 5 = 6 Point is 6 Player rolled 1 + 6 = 7 Player loses
roll_dice
—Returning Multiple Values Via a TupleFunction roll_dice
(lines 5–9) simulates rolling two dice on each roll. The function is defined once, then called from several places in the program (lines 16 and 33). The empty parameter list indicates that roll_dice
does not require arguments to perform its task.
The built-in and custom functions you’ve called so far each return one value. Sometimes it’s useful to return more than one value, as in roll_dice
, which returns both die values (line 9) as a tuple—an immutable (that is, unmodifiable) sequences of values. To create a tuple, separate its values with commas, as in line 9:
(die1, die2)
This is known as packing a tuple. The parentheses are optional, but we recommend using them for clarity. We discuss tuples in depth in the next chapter.
display_dice
To use a tuple’s values, you can assign them to a comma-separated list of variables, which unpacks the tuple. To display each roll of the dice, the function display_dice
(defined in lines 11–14 and called in lines 17 and 34) unpacks the tuple argument it receives (line 13). The number of variables to the left of =
must match the number of elements in the tuple; otherwise, a ValueError
occurs. Line 14 print
s a formatted string containing both die values and their sum. We calculate the sum of the dice by passing the tuple to the built-in sum
function—like a list, a tuple is a sequence.
Note that functions roll_dice
and display_dice
each begin their blocks with a docstring that states what the function does. Also, both functions contain local variables die1
and die2
. These variables do not “collide,” because they belong to different functions’ blocks. Each local variable is accessible only in the block that defined it.
When the script begins executing, lines 16–17 roll the dice and display the results. Line 20 calculates the sum of the dice for use in lines 22–29. You can win or lose on the first roll or any subsequent roll. The variable game_status
keeps track of the win/loss status.
The in
operator in line 22
sum_of_dice in (7, 11)
tests whether the tuple (7,
11)
contains sum_of_dice
’s value. If this condition is True
, you rolled a 7
or an 11
. In this case, you won on the first roll, so the script sets game_status
to 'WON'
. The operator’s right operand can be any iterable. There’s also a not
in
operator to determine whether a value is not in an iterable. The preceding concise condition is equivalent to
(sum_of_dice == 7) or (sum_of_dice == 11)
Similarly, the condition in line 24
sum_of_dice in (2, 3, 12)
tests whether the tuple (2,
3,
12)
contains sum_of_dice
’s value. If so, you lost on the first roll, so the script sets game_status
to 'LOST'
.
For any other sum of the dice (4
, 5
, 6
, 8
, 9
or 10
):
line 27 sets game_status
to 'CONTINUE'
so you can continue rolling
line 28 stores the sum of the dice in my_point
to keep track of what you must roll to win and
line 29 displays my_point
.
If game_status
is equal to 'CONTINUE'
(line 32), you did not win or lose, so the while
statement’s suite (lines 33–40) executes. Each loop iteration calls roll_dice
, displays the die values and calculates their sum. If sum_of_dice is equal to my_point
(line 37) or 7
(line 39), the script sets game_status
to 'WON' or
'LOST'
, respectively, and the loop terminates. Otherwise, the while
loop continues executing with the next roll.
When the loop terminates, the script proceeds to the if
…else
statement (lines 43–46), which prints 'Player
wins'
if game_status
is 'WON'
, or 'Player
loses'
otherwise.
(Fill-In) The operator tests whether its right operand’s iterable contains its left operand’s value.
Answer: in
.
(IPython Session) Pack a student
tuple with the name 'Sue'
and the list [89,
94,
85]
, display the tuple, then unpack it into variables name
and grades
, and display their values.
Answer:
In [1]: student = ('Sue', [89, 94, 85])
In [2]: student
Out[2]: ('Sue', [89, 94, 85])
In [3]: name, grades = student
In [4]: print(f'{name}: {grades}')
Sue: [89, 94, 85]