Dice Game Simulation - python

I have this question for an assignment:
Your friend has devised a game with two players. The two players,
called A and B, take turns rolling an ordinary six-sided die, with A being
the first to roll.
The first player who rolls a six wins the game.
You and your friend do not agree about what the probability of A winning
the game is, and you therefore decide to simulate the game with a
computer.
Thus: write a Python program that performs 10 trials, each consisting of
10000 games, and for each trial prints the fraction of the games won by
player A.
This is the code I've gotten so far, it's just returning a number in and around 1667 every time. I'm mainly wondering how to differentiate between A or B winning the game.
Any help would be appreciated!
EDITED CODE
import random
def rollDie():
return random.choice([1,2,3,4,5,6])
def roll_first():
if random.choice([0,1]) == 0:
return 'A'
else:
return 'B'
def rollSim():
while True:
turn = roll_first()
numTrials = 10
numThrows = 10000
totalThrows = numTrials*numThrows
game_on = True
winsA = 0
winsB = 0
while game_on:
for n in range(numTrials):
games = 0
for i in range(numThrows):
throw = rollDie()
if turn == 'A':
if throw == 6:
winsA += 1
games += 1
break
else:
turn = 'B'
else:
if throw == 6:
winsB += 1
games += 1
break
else:
turn = 'A'
return winsA/totalThrows

The best way to achieve a clean code would be to separate in functions each one of the tasks in hand, meaning:
1. Run a play -> For each dice rolling
2. Run a game -> Alternation of plays between A and B, until the first one gets a 6 on the dice (here considering that if A gets a 6, B doesn't even need to play, as A won)
3. Run a trial -> Consisting of a specific number of plays
4. Run the main program -> Consisting of playing all the number of trials required
So, below, is one of the possible solutions (here you see that my play function already returns the result, meaning if the player won or not):
import random
def play():
won = True
keepPlaying = False
rollDice = random.choice([1,2,3,4,5,6])
if rollDice == 6:
return won
return keepPlaying
def run_game(winsA, winsB):
while True:
playA = play()
playB = play()
if playA:
winsA += 1
return winsA, winsB
elif playB:
winsB += 1
return winsA, winsB
def run_trial(numGames):
winsA = 0
winsB = 0
for i in range(numGames):
wins = run_game(winsA, winsB)
winsA = wins[0]
winsB = wins[1]
print("winsA:", winsA, "| winsB:", winsB, "| Fraction of A wins:", "{} %".format(winsA / ( winsA + winsB ) * 100))
numTrials = 10
numGames = 10000
for i in range(numTrials):
run_trial(numGames)

You really only need to count wins for player A. Since you play 10000 games per trial, if you know the number of games that A won, you know the other games must have been won by B, and A+B=10000.
You seem to decide randomly who has the first turn, but the task states that it should always be player A taking the first turn.
You can use a boolean isPlayerA to know whose turn it is. Start with isPlayerA = True and then toggle it with isPlayerA = not isPlayerA.
Here is how you could code it:
import random
def rollDie():
return random.choice([1,2,3,4,5,6])
def winFraction(): # Perform one trial of 10000 games and return fraction of wins for A
winsA = 0 # only count wins for A
for numTrow in range(10000):
isPlayerA = True # Player A always takes the first turn
throw = rollDie()
while throw != 6: # While the game is not over yet:
isPlayerA = not isPlayerA # Switch to the other player
throw = rollDie()
if isPlayerA:
winsA += 1 # Only count the wins for player A
return winsA/10000.0 # This is the fraction: we know the number of played games
def sim():
for trial in range(10): # Perform 10 trials
print(winFraction()) # Print the result of the trial
sim() # Start the simulation

Related

monte carlo of a preexisting program

The python code in diceGame.py (below) contains a python implementation of the dice game we discussed in class. Assume we run the code N times and estimate the probability of a certain event A, P r{A}, based on the number of times A occurs divided by N. We then repeat this process M times collecting the probabilities pi, i = 1, . . . , M. Under the assumption that both dices are fair, modify the main routine of diceGame.py using N = 10, 100, 1000 and M = 100 for the following probabilities:
The probability of winning the game at the first dice roll.
The probability of winning the game if the first roll gives a 4.
The probability of winning the game.
The probability of a game to require more than 5 dice rolls.
I know that all of these answers can easily be supplied through the code itself. My problem is that I have no idea how to edit the python code to give these desired outputs.
Here is the code:
# ===============================
# IMPORTS RANDOM NUMBER GENERATOR
# ===============================
import random
# ================================================================
# GENERATES RANDOMLY THE SUM OF TWO INTEGERS IN THE [1,6] INTERVAL
# ================================================================
def rollDices():
return int(random.randint(1,6) + random.randint(1,6))
# ================================================
# RETURN THE OUTCOME STRING GIVEN AN INTEGER STATE
# ================================================
def getOutcome(outcome):
if(outcome == 0):
result = "Lost at first roll."
elif(outcome == 1):
result = "Won at first roll."
elif(outcome == 2):
result = "Won on [4,5,6,8,9,10]"
elif(outcome == 3):
result = "Lost on [4,5,6,8,9,10]"
return result
# ==============
# PLAYS THE GAME
# ==============
def playGame():
# Define Variables
gameFinished = False
wonGame = False
totRolls = 0
while (not(gameFinished)):
# ROLL DICES
totScore = rollDices()
totRolls += 1;
# GAME IS LOST
if(totScore in [2,3,12]):
gameFinished = True
wonGame = False
return 0,wonGame,totRolls,totScore
# GAME IS WON
if(totScore in [7,11]):
gameFinished = True
wonGame = True
return 1,wonGame,totRolls,totScore
# JUST CONTINUE PLAYING
if(totScore in [4,5,6,8,9,10]):
# REPEAT UNTIL YOU FIND THE SCORE AGAIN OR 7
newScore = 0
while((newScore != totScore)and(newScore != 7)):
newScore = rollDices()
totRolls += 1;
# CHECK IF YOU WIN OR LOOSE
if(newScore == totScore):
gameFinished = True
wonGame = True
return 2,wonGame,totRolls,totScore
if(newScore == 7):
gameFinished = True
wonGame = False
return 3,wonGame,totRolls,totScore
# ============
# MAIN PROGRAM
# ============
if __name__ == "__main__":
intVal,wonGame,numRolls,lastScore = playGame()
print("Outcome: %s" % (getOutcome(intVal)))
if(wonGame):
print("You have won the game.")
else:
print("You have lost the game.")
print("Total rolls needed for this game: %d" % (numRolls))
print("Last outcome: %d" % (lastScore))
New main function as I attempt the problem:
if __name__ == "__main__":
m = 100
n = 10
FRwins = 0
for i in range(m):
for j in range(n):
intVal,wonGame,numRolls,lastScore = playGame()
if getOutcome(intVal) == 1:
FRwins += 1
FRwins = FRwins/float(n)
print(FRwins)
Currently this programme is playing the game once. If you look at the final 10 lines of code, that is what you want to adjust in order to do this. The important line is this:
intVal,wonGame,numRolls,lastScore = playGame()
It is only being called once, so you only get one result out of it. Since you need to do a Monte Carlo simulation (i.e. playing over and over again and tracking the probabilities), you just need to replay this line lots of times, and keep track of the results each time.
From there, you will need to set up some for loops, such as:
for i in range(m):
and keep track of results from each simulation. Since you are working with m and n, you will need nested loops surrounding your playGame(). Then you just need to tally the results as you go, and divide by the total attempts to get your probabilities.
Hopefully this is helpful. Feel free to ask further questions - I'm trying to keep it general enough that I'm not actually writing the code for what seems to be your homework!

How to break multiple while loops

I'm making a program that is a game of pick up sticks. I'm still quite confused with the logic of the entire thing. My biggest problem is I have multiple nested while loops and want to end all of them. Heres my code.
x = 1
while x == 1:
sticks = int(input('How many sticks are on the tables (10 to 100): '))
if sticks not in range(10,101):
print('Invalid.')
continue
while x == 1:
print('There are',sticks,'sticks on the table.')
print('Player 1')
p1 = int(input('How many sticks do you want to remove?'))
if p1 == sticks:
print('Player one wins.')
x == 2
break
elif p1 not in range(1,4):
print('Invalid.')
continue
else:
while x == 1:
sticks -= p1
print('There are',sticks,'sticks on the table.')
print('Player 2.')
p2 = int(input('How many sticks do you want to remove?'))
if p2 == sticks:
print('Player two wins.')
x == 2
break
elif p2 not in range(1,4):
print('Invalid.')
continue
else:
sticks -= p2
My output continues to prompt player 1 and 2 for input.
I want the program to end after printing "Player _ wins".
Any helps/ tips would be greatly appreciated! Or even a simpler way to write the program.
I always find building a state machine for a multi-player turn-based game helps a lot. Because it provides a clear and easy way to decompose the logic and avoid using a lot of break and continue or even goto in nested loops.
For example, here is a state machine which has 4 states:
For each state, there's a handler function, it will decide which state to go next(even itself) based on current player, sticks and user input:
def initialize():
global sticks, state
n = int(input('How many sticks are on the tables (10 to 100): '))
if n not in range(10, 101):
print('Invalid. It should be between 10 ~ 100.')
else:
state = 'ask_player1'
sticks = n
def ask_player1():
global sticks, state
print('There are', sticks, 'sticks on the table.')
print('Player 1')
n = int(input('How many sticks do you want to remove?'))
if n not in range(1, 4):
print('Invalid. It should be between 1 ~ 4')
else:
sticks -= n
if sticks == 0:
print('Player one wins.')
state = 'end'
else:
state = 'ask_player2'
def ask_player2():
global sticks, state
print('There are', sticks, 'sticks on the table.')
print('Player 2')
n = int(input('How many sticks do you want to remove?'))
if n not in range(1, 4):
print('Invalid. It should be between 1 ~ 4')
else:
sticks -= n
if sticks == 0:
print('Player two wins.')
state = 'end'
else:
state = 'ask_player1'
state_machine = {
'initialize': initialize,
'ask_player1': ask_player1,
'ask_player2': ask_player2,
}
sticks = 0
state = 'initialize'
while state != 'end':
state_machine[state]()
Your best bet is probably to move the code into a function that returns. Multi-breaks have been proposed multiple times and have been rejected. You can put this whole code into a function that returns after "Player _ wins", so it doesn't keep running. Other alternatives are using a flag variable that is set after a player wins and raising an exception that is subsequently handled.

How can I check an array with a list of array values?

I'm trying to solve a programming challenge that is based on Rock Paper Scissors. My goal is given a list of game moves, determine at what move the game was won. My issue is checking if the game is won or not. I have a list of winning combinations, say for example the game grid is:
1, 2, 3,
4, 5, 6,
6, 7, 8,
Then a winning combination would be for example: 4, 5, 6 because it is 3 in a row.
My problem is I don't know how to check all these winning combinations efficiently. I tried to make a list of winning combinations and then just run the game board through that to check for winners, which would be fantastic, only it doesn't work and I don't know how else to approach it reasonably.
Here's my code:
def is_winner(grid):
player1_wins = ['X','X','X']
player2_wins = ['O','O','O']
player_win = [player1_wins, player2_wins]
win1 = [0,3,6] #[1,4,7]
win2 = [1,4,7] #[2,5,8]
win3 = [2,5,8] #[3,6,9]
win4 = [0,4,8] #[1,5,9]
win5 = [6,7,8] #[7,8,9]
win6 = [3,4,5] #[4,5,6]
win7 = [0,1,2] #[1,2,3]
win8 = [6,7,8] #[7,8,9]
winning_grids = [win1, win2, win3, win4, win5, win6, win7, win8]
if any(grid[winning_grids]) == any(player_win): # !!!! Broken code here !!!!
return True # Game won
else:
return False
def tic_tac_toe(games):
for game in range(games):
grid = ['1','2','3',
'4','5','6',
'7','8','9']
moves = [int(x) for x in raw_input().split()]
turn = 1
for move in moves:
if turn % 2 != 0:
grid[move-1] = 'X'
elif turn % 2 == 0:
grid[move-1] = 'O'
if is_winner(grid):
print("Game over on turn %d" % turn)
print(grid)
tic_tac_toe(input())
Sample input looks like this:
3
7 5 4 1 9 2 8 3 6
5 1 3 7 6 4 2 9 8
5 1 2 8 6 4 7 3 9
Where that is 3 games, player 1 goes first and player 2 is the next number in each string.
The answer would be: Game 1 - move 7. Game 2 - Move 6, Game 3 - Tie. (Not yet implemented)
What can I do to check for the winning move / does anyone have any suggestions on how to fix my code?
I think what you need is to use a class. I could have tried to fix your code, but I think you need to re-think it completely.
Logically, you could break it up into a game object that keeps track of the moves made for a single game. You can simply make a move, then check after each move to see if the game has been won.
I'm not sure if you are familiar with classes, but I think a tic tac toe game is better implemented as an object. You could also re-use the game class in many other scenarios. Not just for determining on what move each game was won. In a complex program, you could even pass the game object to other objects so that they can interact with it in their own way. This is beyond the scope of this answer, but hopefully, you get my point.
Try the code below, I purposely commented it heavily and made it (hopefully) easy to understand. It's long, but it breaks down each task so that it is easy to follow what's going on. (At least for me it is)
You could use the concepts in this code to fix your implementation. Either use bits and pieces of my code to fix yours or just use my version if you like.
With this code, the game object keeps track of whose turn it is, the moves each player has made, whether or not the game has been won, whether or not the game is over, who the winning player is, and the number of moves played.
Also, I purposefully wrote the code so that it works on both Python 2.7 and 3.4. Usually, I try to write only for Python 3x, but that is my preference.
class TicTacToeGame:
"""
A class that implements a tic tac toe game
"""
# This is a class variable that contains
# a list of all the winning combos
winningCombos = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[1, 4, 7],
[2, 5, 8],
[3, 6, 9],
[1, 5, 9],
[3, 5, 7]
]
def __init__(self):
"""
Init method. This gets called when you create a new game object
We simply use this method to initialize all our instance variables
"""
# The current player. Either X or O
self.currentPlayer = 'X'
# List of player x moves
self.playerXMoves = []
# List of player o moves
self.playerOMoves = []
# Whether or not the game has been won
self.isWon = False
# Whether or not the game is over
self.isOver = False
# The winning player
self.winningPlayer = None
# The number of moves played
self.numberOfMovesPlayed = 0
def doMakeAMoveAtPos(self, pos):
"""
Makes a move in the game at the specified position
1 is the first position, 5 is the center position, etc
#param pos: The position (1 through 9)
#type pos: int
#rtype: None
"""
# If the game has already been won
if self.isWon:
raise ValueError('The game has been won')
# If the game is over, nobody won
if self.isOver:
raise ValueError('The game is a tie')
# Make sure that the position is within range
if pos < 1 or pos > 9:
raise ValueError('Invalid position. Should be between 1 and 9')
# Make sure the position isn't already taken
if pos in self.playerXMoves or pos in self.playerOMoves:
raise ValueError('The position: ' + str(pos) + ' is already taken')
# Get the current player
currentPlayer = self.currentPlayer
# If the current player is X
if currentPlayer == 'X':
# Add the move and switch to player O
currentPlayerMoves = self.playerXMoves
currentPlayerMoves.append(pos)
self.currentPlayer = 'O'
# Otherwise, the current player is O
else:
# Add the move and switch to player X
currentPlayerMoves = self.playerOMoves
currentPlayerMoves.append(pos)
self.currentPlayer = 'X'
# Increment the number of plays.. You could just check the length of
# playerXMoves and playerOMoves to get the total number of moves, but
# we are going to keep track to avoid more code later
self.numberOfMovesPlayed += 1
# If the number of plays is 9, the game is over
if self.numberOfMovesPlayed == 9:
self.isOver = True
# See if the game has been won
# If there hasn't been enough moves to win yet, no winner
if len(currentPlayerMoves) < 3:
return
# Iterate through each winning combo
for winningCombo in self.winningCombos:
# If each number is in the player's moves, the game has been won
if set(winningCombo) <= set(currentPlayerMoves):
self.isWon = True
self.winningPlayer = currentPlayer
return
# OK... Our Class has been defined.
# Now it's time to play tic tac toe.
# Define an input string. How you get this is up to you
# Change this to different numbers to see what you get.
inputString = '3 7 5 4 1 9 2 8 3 6 5 1 3 7 6 4 2 9 8 5 1 2 8 6 4 7 3 9'
# Parse the input string into a list of integers
moves = [int(move) for move in inputString.split()]
# Create the initial game
game = TicTacToeGame()
# Set the number of games to 1 (This is the first game after all)
numberOfGames = 1
# Go through all the moves 1 by 1
for pos in moves:
# Try to make a move in the current game
try:
game.doMakeAMoveAtPos(pos)
# But, since the input is unpredictable, we need to catch errors
# What's to stop the input from being '1 1 1 1 1 1 1 1 1', etc
# You can't keep playing position number 1 over and over
except ValueError as exc:
# Do what you want with the exception.
# For this example, I'm just gonna print it
# and move on the the next move
print(exc)
continue
# If the game has been won
if game.isWon:
print('Game ' + str(numberOfGames) + ' Won On Move: ' + str(game.numberOfMovesPlayed) + ' Winning Player: ' + str(game.winningPlayer))
# Since the game was won, create a new game
game = TicTacToeGame()
# And increment the game number
numberOfGames += 1
# If the game is a tie
elif game.isOver:
print('Game ' + str(numberOfGames) + ' Tie')
# Since the game was a tie, create a new game
game = TicTacToeGame()
# And increment the game number
numberOfGames += 1
# If there is an unfinished game, we can report this as well
if game.numberOfMovesPlayed > 0:
print('Game ' + str(numberOfGames) + ' was not finished')
There are plenty of improvements that could be made, but you get the point (I hope) When I ran this code I get the following output:
Game 1 Won On Move: 7 Winning Player: X
The position: 3 is already taken
Game 2 Won On Move: 6 Winning Player: O
The position: 2 is already taken
The position: 8 is already taken
The position: 6 is already taken
The position: 4 is already taken
Game 3 Won On Move: 9 Winning Player: X
Game 4 was not finished
#RayPerea made a great answer. But in a case you can't use classes by your requirements or just don't want to, I will follow a different approach.
The idea behind this post is to show a functional side of python. One of the main concepts of "functional" programming is that you don't have any access to the outer scope of the function. I have cheated by adding player_one and player_two to the global namespace. But it is easily transformed into 100% functonal code. Here's a good tutorial.
This code can be runned on both pythons 2 and 3.
The only thing to do is to change saved inputs to actual inputs.
player_one = 'X'
player_two = 'O'
# You can add "HAZ THE MOVEZ" joke here:
def has_the_moves(player, moves):
if len(moves) <= 2:
return None
win1 = (0,3,6) #[1,4,7]
win2 = (1,4,7) #[2,5,8]
win3 = (2,5,8) #[3,6,9]
win4 = (0,4,8) #[1,5,9]
win5 = (6,7,8) #[7,8,9]
win6 = (3,4,5) #[4,5,6]
win7 = (0,1,2) #[1,2,3]
win8 = (6,7,8) #[7,8,9]
winning_grids = [win1, win2, win3, win4, win5, win6, win7, win8]
# We will return a player name (not bool) if he is a winner.
# This name will be used later.
tried = [set(posibility) <= set(moves) for posibility in winning_grids]
return player if any(tried) else None
def is_winner(grid):
player_one_moves = [i for i, x in enumerate(grid) if x == player_one]
player_two_moves = [i for i, x in enumerate(grid) if x == player_two]
player_one_won = has_the_moves(player_one, player_one_moves)
player_two_won = has_the_moves(player_two, player_two_moves)
# If we a have a winner:
if player_one_won or player_two_won:
return player_one_won if player_one_won else player_two_won
return None
def end_game(winner=None, last_turn=False):
""" This function can be used when you find a winner,
or when the end of the game is reached.
"""
if last_turn:
print('Game ended in a draw.')
if winner:
print('Player {} won.'.format(winner))
def tic_tac_toe(games):
# For testing purposes let's save user's input:
saved_moves = ['7 5 4 1 9 2 8 3 6', '5 1 3 7 6 4 2 9 8', '5 1 2 8 6 4 7 3 9']
for game in range(games):
grid = [str(x) for x in range(1, 10)] # one-liner
moves = [int(x) for x in saved_moves[game].split()] # TODO: make sure to change saved_moves[game]
for turn, move in enumerate(moves):
grid[move - 1] = player_one if turn % 2 == 0 else player_two
# Stop the game?
winner = is_winner(grid)
if winner:
print('Game over on turn {}.'.format(turn + 1))
end_game(winner=winner)
break; # no more iterations required.
if turn == len(moves) - 1:
end_game(last_turn=True)
if __name__ == '__main__':
# We running 3 games:
saved_games_number = 3
tic_tac_toe(saved_games_number)
Result is:
Game over on turn 7.
Player X won.
Game over on turn 6.
Player O won.
Game ended in a draw.

Probability Dice Game in Python with two dices

I want to interate 1000 times over the following function to find out if you win or loose money in this game.
The game is designed as such that you throw a pair of dice and get money back or loose money. Let's say we start with 5 coins.
Throwing a 12 yields 1.5 coins.
Throwing an 11 yields 1 coins.
Throwing a 10 yields 0.5 coins.
Throwing a 9,8 or 7 yields nothing.
Throwing a 6,5,4,3,2 or 1 deducts 0.5 coins from your amount of coins.
This is what my implementation looks like so far:
def luckCalc():
amount = 5
# if 12 then 1/36 chance
if random.randrange(1,7) == 6 and random.randrange(1,7) == 6:
amount = amount + 1.5
# if 11 then 2/36 chance
elif (random.randrange(1,7) == 5 and random.randrange(1,7) == 6) or (random.randrange(1,7) == 6 and random.randrange(1,7) == 5):
amount = amount + 1
# if 10 then 3/36 chance
elif (random.randrange(1,7) == 5 and random.randrange(1,7) == 5) or (random.randrange(1,7) == 4 and random.randrange(1,7) == 6) or (random.randrange(1,7) == 6 and random.randrange(1,7) == 4):
amount = amount + 0.5
# if 9,8,7
# 4/36 + 5/36 + 6/36 chance
# 1+6, 2+5, 3+4, 4+3, 5+2, 6+1 chance
# 2+6, 3+5, 4+4, 5+3, 6+2 chance
# 3+6, 4+5, 5+4, 6+3 chance
# then no change in amount
# if 6,5,4,3,2,1
# chances...
# then amount -0.5
return amount
# Iterate over the dice throwing simulator and calculate total
total = 0.0
for a in range(1000):
total = total + luckCalc()
print (total)
I stopped coding towards the end of the function, because I recognised that there must be a more elegant solution on how to achieve this. Any interesting suggestions, what is this Monte Carlo I keep hearing about?
Each time you call random.randrange(1,7), you generate a new random number. Since you're testing a single "turn", roll twice:
def roll_die():
return random.randrange(1, 7)
total = roll_die() + roll_die()
And see if the sum is in a range:
def play_turn():
total = roll_die() + roll_die()
if total == 12:
return 1.5
elif total == 11:
return 1.0
elif total == 10:
return 0.5
elif total <= 6:
return -0.5
else: # total is 7, 8, or 9
return 0
Here's the result of 100,000 rounds:
>>> from collections import Counter
>>> counts = Counter(play_turn() for i in xrange(100000))
>>> counts
Counter({-0.5: 41823, 0: 41545, 0.5: 8361, 1.0: 5521, 1.5: 2750})
>>> probabilities = {score: count / 100000.0 for score, count in counts.items()}
>>> probabilities
{-0.5: 0.41823, 0: 0.41545, 0.5: 0.08361, 1.0: 0.05521, 1.5: 0.0275}
You can actually roll (ha!) everything you are doing into a single function:
from random import randrange
def play_game(rolls=1000, amount=5, n=6):
"""Play game 'rolls' times, starting with 'amount' on 'n'-sided dice."""
for i in range(rolls):
roll = randrange(1, n+1) + randrange(1, n+1)
if roll == 12:
amount += 1.5
elif roll == 11:
amount += 1
elif roll == 10:
amount += 0.5
elif roll < 7:
amount -= 0.5
return amount
I notice a few things in your code. First, for the 6-1 cases you're not actually subtracting 0.5 from the amount. Second, since you don't pass in the initial amount each loop you're adding between 5 and 6.5 to your total, which makes the total pretty pointless.
A more effective total would be to pass in the amount each time:
def luckCalc( amount ):
And then for your loop:
total = 5.0
for a in range(1000):
total = luckCalc(total)
Blender's answer, which just posted as I was writing this, is a great way to simplify your main function.
I personally like setting up my results table as an array (or a dictionary, but this suited my purpose better since every result was one of a small number of possible integers), with the index of each dice roll set to the value of the resulting change. See below.
import random
def luckCalc(coins=5):
diceroll = random.randint(1,6)+random.randint(1,6) #roll them bones
#here's that table I was talking about....
results_table = ['index 0 is blank',"you can't roll a one on two dice",-.5,-.5,-.5,-.5,-.5,0,0,0,.5,1,1.5]
coins += results_table[diceroll] #changes your coins value based on your roll (as an index of results_table)
if results_table[diceroll] > 0: #change the string if your result was + or -
result = "gained {}".format(results_table[diceroll])
else:
result = "lost {}".format(results_table[diceroll]*-1)
print("You {} coins, putting you at {}".format(result,coins)) #report back to the user
return coins #this is how you save your output
#CONSTANTS GO HERE -- YOU CAN CHANGE THESE TO CHANGE YOUR PROGRAM
STARTING_COINS = 5
HOW_MANY_ITERATIONS = 1000
#this way we don't modify a constant
coins = STARTING_COINS
#do it how many times?
for _ in range(HOW_MANY_ITERATIONS): #oh yeah that many times
coins = luckCalc(coins) #runs the function and saves the result back to coins
#report to the user your final result.
print("After {} rolls, your final total is {}".format(HOW_MANY_ITERATIONS,coins))

Python Programming Dice Game?

I am trying to come up with a simulation for the Pig dice game. I want it to simulate for the number of games the user wants(each game to 100 points) and report the average points and percent wins for each player. My program is running but it is only running for one game. I think there is something wrong with my loop but i cannot tell. Thank you for your help and time here is my program:
from random import randrange # Use "randrange(1, 7)" to get a random
# number between 1 and 6.
# Takes one turn in the game of pig. Keeps rolling until either
# the holdAmount is reached or a pig (1) is rolled. Returns the
# score accumulated during the turn.
def takeTurn(holdAmount):
totalScore = 0
while totalScore < holdAmount:
rollValue = randrange(1,7)
if rollValue == 1:
totalScore = 0
break
else:
totalScore = totalScore + rollValue
return totalScore
# Start with turn score equal to 0. Repeatedly roll die, adding
# roll value to score each time, until score reaches holdAmount.
# If at any time a pig (1) is rolled, set score to 0 and end the
# turn early.
# Tests the takeTurn function.
def main():
first = eval(input("How many points should the first player try for in each turn?"))
second = eval(input("How many points should the second player try for in each turn?"))
games = eval(input("How many games should be simulated?"))
firstScore = 0
secondScore = 0
turnCount = 0
score = 0
score1 = 0
won = 0
won1 = 0
for i in range(games):
while firstScore < 100 and secondScore < 100:
firstScore = takeTurn(first) + firstScore
secondScore = takeTurn(second) + secondScore
turnCount = turnCount + 1
if firstScore >= 100:
won = won + 1
elif secondScore >= 100:
won1 = won1 + 1
score = score + firstScore
score1 = score1 + secondScore
percent = won / games
percent1 = won1 / games
points = score / games
points2 = score1 / games
print("The average points for player one is",points)
print("The percent of games won for player one is",percent)
print("The average points for player two is",points2)
print("The percent of games won for player two is",percent1)
if __name__ == "__main__":
main()
I was confused for a while when I first looked at this. The reason is that each game ends with the same score since you do not reset the firstScore, etc. values each time. If you set each of those to 0 at the beginning of your for loop, you won't have any problems.
To be more specific, if you move firstScore, secondScore, and turnCount inside your for loop at the very top of it, the code runs properly.
The traditional way to gain a better understanding of what your program is doing is to add some print statements at looping and branching points.
A more advanced technique is to trace through the program using pdb.
You need firstScore and secondScore inside your for-loop.

Categories