The Pig in Python
I came across the dice game called Pig and I have attempted an implementation here. Here's the link to the rules of the game Pig.
Simulating a dice throw in Python gives us an opportunity to learn a few things like
- randomness
- frequency distribution
- event outcomes
Let's consider the outcomes of throwing a pair of dice. It is easy to see that the sum of the outcomes can vary from 2 to the maximum of 12.
What are the combinations from which these outcomes are possible? We will go step by step, starting with a single die, then on to a pair of dies.
Event Outcomes Using Python's itertools module
from itertools import product
die = [x for x in range(1, 7)]
print(die)
# combinations of outcomes
outcomes_1 = set(product(die, repeat = 1))
print(len(outcomes_1))
print(outcomes_1)
outcomes_2 = set(product(die, repeat = 2))
print(len(outcomes_2))
print(outcomes_2)
We declare a list of numbers from 1 to 6, inclusive using the range() function. The function takes the start parameter and the end parameter minus 1.
In order to simulate a throw of dice, we need to import the product() function from the package itertools . We pass two parameters, the sequence of numbers, in this case the possible outcomes of throwing a dice event, and the second parameter repeats the event, in this case it is the number of dies to throw.
Look carefully at the outcomes when a pair of dice is thrown _outcomes2. The number of outcomes is 36 and the outcomes are captured as tuples of pairs of each die throw.
Here's the output
36
{(3, 4), (4, 3), (3, 1), (5, 4), (4, 6), (5, 1), (2, 2), (1, 6), (2, 5), (1, 3), (6, 2), (6, 5), (4, 2), (4, 5), (3, 3), (5, 6), (3, 6), (5, 3), (2, 4), (1, 2), (2, 1), (1, 5), (6, 1), (6, 4), (3, 2), (4, 1), (3, 5), (5, 2), (4, 4), (5, 5), (1, 1), (1, 4), (2, 3), (2, 6), (6, 6), (6, 3)}
These are the possible outcomes when we throw a pair of dice.
It would be interesting to see which outcomes appear more often than others when we throw N number of times, N being any natural number.
Frequency Table
Let's build a frequency table of outcomes when a pair of dice is thrown 11 times.
# throw a double dice 11 times
# associate frequency with outcomes
for key in range(1, 12):
t1 = random.randint(1, 6)
t2 = random.randint(1, 6)
total = t1 + t2
freq_count[total] += 1
# display frequency
for k, v in freq_count.items():
print(f'{k} - {v} times')
You will be surprised to see the output. Most outcomes don't appear at all!
{2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0, 10: 0, 11: 0, 12: 0}
2 - 0 times
3 - 0 times
4 - 0 times
5 - 0 times
6 - 4 times
7 - 1 times
8 - 2 times
9 - 2 times
10 - 1 times
11 - 0 times
12 - 1 times
The Game
The rules of the game from the link shown above.
Players take turns to roll both dice, they can roll as many times as they want in one turn.
A player scores the sum of the two dice thrown and gradually reaches a higher score as they continue to roll.
If a single number 1 is thrown on either die, the score for that whole turn is lost. However a double 1 counts as 25.
The first player to 100 wins unless a player scores more subsequently in the same round. This means that everyone in the game must have the same number of turns.
import random
def roll():
r1 = random.randint(1, 6)
r2 = random.randint(1, 6)
throw = r1 + r2
return (r1, r2, throw)
#outcome = roll()
#print(outcome)
player1 = input('enter name of player1: ')
player2 = input('enter name of player2: ')
print('A player may roll the dice as many times as they want in their turn.')
current_player = player1
score1 = 0
score1_prev = 0
score2_prev = 0
score2 = 0
def compute_score(outcomes, player):
global score1
global score2
r1, r2, throw = outcomes
if r1 == 1 and r2 == 1:
if player == player1:
score1 += 25
else:
score2 += 25
else:
if player == player1:
score1 += throw
else:
score2 += throw
def play():
global current_player, score1, score2, score1_prev, score2_prev
print(f'\n{current_player}, your turn.')
n = int(input('how many times do you want to throw the dice: '))
score1_prev = score1
score2_prev = score2
for i in range(0, n):
throw = roll()
r1, r2, total = throw
print( (r1, r2), end=' ')
if (r1 == 1 and r2 != 1) or (r2 == 1 and r1 != 1):
score1 = score1_prev
score2 = score2_prev
break
compute_score(throw, current_player)
print(f'\n{player1} has scored : {score1} and {player2} has scored {score2}')
if current_player == player1:
current_player = player2
elif current_player == player2:
current_player = player1
while True:
play()
if score1 >= 100 or score2 >= 100:
break
if current_player == player2:
play()
print('\nFinal scores.')
print(f'{player1} has scored : {score1}')
print(f'{player2} has scored : {score2}')
print(f'{current_player} has finished first!')
Play
Copy-paste the code into a Python IDE (I tested it on Pydroid 3 Android app). Follow the code by running it. Feel free to discuss the code or share your own enhancements. Hopefully not, but if you do find errors and bugs, let's fix'em!
Exercise
- Allow up to six players
Happy coding.
Subscribe to my newsletter
Read articles from Anand Betanabhotla directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Anand Betanabhotla
Anand Betanabhotla
Corporate trainer