Dice
Classes
In Unit 2, we learned about types. Every object has a type, and an object's type determines what it can do. For example, adding integers works differently than adding strings. You are not limited to the built-in types; you can create new types by defining classes.
Unit 3 is all about games, and there are a number of objects which are useful for gaming. For example, dice.
💻
Open die.py
and read the code:
1 class Die:
2 def __init__(self):
3 self.roll()
4
5 def __str__(self):
6 return str(self.face)
7
8 def roll(self):
9 self.face = randint(1, 6)
10 return self.face
💻 Enter the interactive python environment and try using a die.
11 % python
12 >>> from die import Die
13 >>> d = Die()
14 >>> print(d)
15 5
16 >>> d.roll()
17 2
18 >>> d.roll()
A few things to note:
- Class names are capitalized (line 1).
- A class can contain functions (
__init__
,__str__
,roll
). The intendation structure should be familiar--you know the functions are part of the class because they are intended. When functions are contained within classes, they are called methods. - You create an instance of a class by calling its name (line 13).
- You can access things inside of a class instance using
.
. These can include attributes and methods. For example, line 9 assigns the variableself.face
, so the die keeps track of the result of its last roll. On line 16, theroll
method is called. - The first argument of every class method is an object called
self
. This is a reference to the object itself; allowing one method to access the instance's other methods and attributes. Theself
argument is provided automatically: note how we calld.roll()
on line 16 without providingself
. - There are some special method names, surrounded by double underscores. These methods
define certain behaviors of the class, and are not meant to be called directly.
__init__
gets called as soon as the class instance is created. This is a chance to set up the instance. For example, as soon as aDie
is created,Die.roll
is called to make sure every die always has a face value.__str__
defines how the class gets formatted as a string, for example when it is printed. When we printed our die (line 14) we saw its face value because of howDie.__str__
is defined (line 5).
Dice stats
What are the odds of rolling five dice and having them all turn up as ones? You could use probability to solve this, but if you haven't learned probability yet, you could just run a simulation.
💻
Run dice_stats.py
. This program takes five dice, rolls them
a million times, and counts how many times they came up all ones. It takes a moment,
so we added a nice little progress bar.
💻
Open dice_stats.py
.
1 from die import Die
2 from tqdm import tqdm
3
4 class FiveDice:
5 def __init__(self):
6 self.dice = [Die() for number in range(5)]
7
8 def roll(self):
9 for die in self.dice:
10 die.roll()
11 return self.faces()
12
13 def faces(self):
14 return [die.face for die in self.dice]
15
16 def all_ones(self):
17 for face in self.faces():
18 if face != 1:
19 return False
20 return True
21
22 dice = FiveDice()
23 successes = 0
24 trials = 1000000
25 for trial in tqdm(range(trials)):
26 dice.roll()
27 if dice.all_ones():
28 successes += 1
29
30 print(successes/trials)
To make it easier to handle five dice, we created another class
called FiveDice
. When FiveDice
is created, it creates a list of
five dice. Then FiveDice.roll
rolls all the dice, FiveDice.faces
returns a list of the die faces, and FiveDice.all_ones
checks to see
whether all the faces are ones.
Yahtzee
💻
Run play.py
. This is a Terminal-based version of Yahtzee,
a simple dice game. If you have not played Yahtzee before,
here are the rules.
This version of Yahtzee is simplified: instead of three-of-a-kind, four-of-a-kind,
full house, and all the rest, the only goals are Ones, Twos, and Threes. Still,
kind of fun? My record is 22 points.
This version of Yahtzee uses a number of different classes:
yahtzee.py
definesYahtzee
, a class for the whole Yahtzee game.yahtzee_goals.py
defines several end-of-round goals. A goal represents one row on the scoreboard. Each round of the game ends when you choose to score one of the goals. Goals have two methods:score(dice)
takes the list of dice and returns the score these dice would get. For example,GoalThrees
scores three points for each three.prompt(dice)
returns a string describing the goal and the potential score for the goal. This method is used to show options to the player.
die.py
definesDie
, which we have already met.
Adding goals
Now let's add some more goals to make this game more fun. Implement some of the following goals, as described in the rule book.
- fours
- fives
- sixes
- three of a kind
- four of a kind
- full house
- small straight
- large straight
- yahtzee
- chance
Add new classes to yahtzee_goals.py
, and then import them in play.py
so they
are included in the game.