I've overcomplicated adding variables for my dice roll game - python

I'm doing a dice roll assignment. The rules are:
The points rolled on each player’s dice are added to their score.
If the total is an even number, an additional 10 points are added to their score.
If the total is an odd number, 5 points are subtracted from their score.
If they roll a double, they get to roll one extra die and get the number of points rolled added to their score.
The score of a player cannot go below 0 at any point.
The person with the highest score at the end of the 5 rounds wins.
Basically, what I've done is created variables of what 2 separate players roll in 2 rounds of the game, now I'm trying to add these variables together so that the player can have their total for round 1 and 2 combined. My teacher had mentioned something about a while function but that was all he was allowed to say, that plus I'm not sure how to do that.
I feel like what I've done is overly complicated, plus the fact it doesn't even work.
if (round2scoreP1 % 2) == 0 + (round1scoreP1 % 2) == 0:
addedscoreround2P1even=(totalround1scoreP1even)+(totalround2scoreP1even)
print(username1,"'s total for round 1 and 2 is",addedscoreround2P1even,".")
elif (round1scoreP1 % 2) != 0 + (round2scoreP1 % 2) != 0:
addedscoreround2P1odd=(totalround1scoreodd)+(totalround2scoreodd)
print(username1,"'s total for round 1 and 2 is",addedscoreround2P1odd,".")
elif (round1scoreP1 % 2) == 0 + (round2scoreP1 % 2) != 0:
addedscoreround2P1evenodd=(totalround1scoreP1even)+(totalround1scoreP1odd)
print(username1,"'s total for round 1 and 2 is",addedscoreround2P1evenodd,".")
elif (round1scoreP1 % 2) != 0 + (round2scoreP1 % 2) == 0:
addedscoreround2P1oddeven=(totalround1scoreP1odd)+(totalround1scoreP1even)
print(username1," obtained",addedscoreround2P1oddeven,".")

I'm not going to write you the whole assignment, but you could consider using a Player-class to store the rolls and total scores in:
class Player():
def __init__(self):
self.rolls = []
self.total_score = 0
def roll_dice():
self.rolls.append(random.randint(1, 6))

Related

Making a Lottery and it seems like I can't win

This is my code buy no matter how many times I run it all I get is you lost. What's wrong with the code?
import random
# Creates a number to count the amount of plays
count = 1;
# Creates a variable to store the amount of starting money
money = 10;
# Creates a variable telling you how much money you start with
startingCash = "You start with $" + str(money) + "!";
while (count < 101):
# Variables for the lottery numbers
lottery1 = random.randint(1,9);
lottery2 = random.randint(1,9);
lottery3 = random.randint(1,9);
lottery4 = random.randint(1,9);
# Lottery variables in one single variable
lotteryTotal = (lottery1, lottery2, lottery3, lottery4);
# Variables for the drawn ticket
drawn1 = random.randint(1,9);
drawn2 = random.randint(1,9);
drawn3 = random.randint(1,9);
drawn4 = random.randint(1,9);
# Variable for the drawn ticket in one single variable
drawnTotal = (drawn1, drawn2, drawn3, drawn4);
# Variable that changes the money variable so the player has 2 less dollars
money = money - 2;
it seems like the == sign gets ignored or acts differently. I wanted it to do the if if they are equal to each other.
if( drawnTotal == lotteryTotal):
count = count + 1;
money = money + 5;
print ("Lottery Numbers: " + str(lotteryTotal));
print ("Your Numbers: " + str(drawnTotal));
print ("You Won $5!");
input("Press Enter to continue")
else:
print ("Lottery Numbers: " + str(lotteryTotal));
print ("Your Numbers: " + str(drawnTotal));
print ("You Lost!");
input("Press Enter to continue");
Your code is working... the results are just not what you expected.
The problem is that, to win, you need to generate the same random sequence of digits twice in a row. What is the probability of that?
The probability of repeating a toss of a single 1-9 digit is 1 out of 9. If you have two such digits, you have two 1/9 probabilities and their compound probability is 1/9 * 1/9, or 1/81. If you have four as in your case, you'll win once every 1/9 * 1/9 * 1/9 * 1/9 = 1/6561 games.
You tried "many times", but... did you try enough times? Even after one thousand games, the probability of winning at least once is less than 15%. Even after 6561 games, the probability of winning at least once is nowhere near 100% - actually it's closer to two thirds.
I modified it to only tell me the number of wins, and to only do so when indeed you do win (MarkyPython's suggestion). After some time, it tells me,
100 won in 686114 games; win rate is 95% of expected.
(The first win, by the way, was after 29172 games).
Great explanation lserni.
Khodexian, in case if you are willing to increase the number of chances of winning you can simply take the numbers into account and disregard the sequence in which they were generated.
For example,
import random
# Creates a number to count the amount of plays
count = 0;
# Creates a variable to store the amount of starting money
money = 10;
# Creates a variable telling you how much money you start with
startingCash = "You start with $" + str(money) + "!";
win, lost = 0, 0
while (win < 100):
count = count + 1;
# Variables for the lottery numbers
lotteryTotal = [random.randint(1,9), random.randint(1,9), random.randint(1,9), random.randint(1,9)]
# Variable for the drawn ticket in one single variable
drawnTotal = [random.randint(1,9), random.randint(1,9), random.randint(1,9), random.randint(1,9)]
# Variable that changes the money variable so the player has 2 less dollars
money = money - 2;
if( sorted(lotteryTotal) == sorted(drawnTotal) ):
money = money + 5;
print ("Lottery Numbers: " + str(lotteryTotal));
print ("Your Numbers: " + str(drawnTotal));
print ("You Won $5!");
win += 1
else:
print ("Lottery Numbers: " + str(lotteryTotal));
print ("Your Numbers: " + str(drawnTotal));
print ("You Lost!");
lost += 1
print ('played {}, won {} and lost {}'.format(count, win, lost))
And I get a statistics like this,
played 40170, won 100 and lost 40070

Distributing points for lottery.py

I'm trying to figure out how to get my bot to distrubute points from a pot from the lottery game when it ends each time. So each game starts out at 1 point but everytime someone buys a ticket it goes up by a random amount. At the end of fifteen minutes it's supposed to retrieve the players and the pot and based off of where you're ranked in the list your points are determined. So basically if you're first in the list you win over the pot value. And when the ranking goes down your points that you win go down and if your near or at last place you lose points. The sum of all the points that the players earn does not have to equal 0 after they are distrubuted.
For example: Tim got 1st in the lottery. He should get 5676*1.66. Also, all the points you receive from the pot should be different based on your rank in the lottery. But if you're at the end of the list in the lottery you should lose points.
This is what I have so far:
lotteryStart = time.time()
players = []
pot = 1
def buyLottery(name):
if name not in players:
amount = int("30")
if Point.getCost(name, amount) == True:
multiplier = random.randint(217, 453)
pot = int(multiplier+pot)
different = float(time.time() - lotteryStart)
years = int(different / Point.YEAR)
days = int((different % Point.YEAR) / Point.DAY)
hours = int((different % Point.DAY) / Point.HOUR)
mins = int((different % Point.HOUR) / Point.MINUTE)
secs = int(different % Point.MINUTE)
if secs <= 0:
if len(players) > 0:
random.shuffle(players)
for i in range(1,len(players)):
if i == 1:
pot2 = int(pot*1.66)
elif i == 2:
pot2 = int(pot*1.33)
elif i == 3:
pot2 = int(pot)
elif i == 4:
pot = int(pot/1.66) #And so on but i dont want to keep doing elif
I do not understand your lottery; I can't imagine a lottery where you buy a ticket for a random amount and could lose money on top of the ticket price being very popular in real life!
That being said, I think you want to do something like this:
ratios = []
for i in range(-2, len(players) - 2):
if i < 0:
ratios.append(1 - (i * 0.33)) # ratio > 1
else:
ratios.append(1 / (1 + (i * 0.33))) # ratio <= 1
winnings = [pot * r for r in ratios]
You can then easily match players[i] with their winnings[i]. Note that I have assumed that you missed out pot / 1.33 accidentally; otherwise, you will have to adjust this slightly.
For 10 players, I get:
ratios == [1.6600000000000001, 1.33, 1.0, 0.7518796992481203,
0.6024096385542168, 0.5025125628140703, 0.43103448275862066,
0.3773584905660377, 0.33557046979865773, 0.3021148036253776]

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 dice rolling simulation

I'm having trouble with a code where I need to roll a six-sided die 1000 times and then return a list of how many times each number on the die was rolled.
The code runs just fine and I can get a list at the end, but my list keeps having 0 in place of four so it appears that my function is not keeping tabs on the number 4 being rolled or it's not being rolled at all.
I'm kind of stumped and I thought maybe someone here could help. Any and all help is appreciated.
Here's my code.
def rollDie(number):
one = 0
two = 0
three = 0
four = 0
five = 0
six = 0
for i in range(0, number):
roll=int(random.randint(1,6))
if roll == 1:
one = one+1
elif roll == 2:
two = two+1
elif roll == 3:
three = three+1
elif roll == 4:
four == four+1
elif roll == 5:
five = five+1
elif roll == 6:
six = six+1
return [one,two,three,four,five,six]
You have a small typo; you are testing for equality, not assigning:
four == four+1
should be:
four = four+1
However, you already have a number between 1 and 6, why not make that into an index into the results list? That way you don't have to use so many if statements. Keep your data out of your variable names:
def rollDie(number):
counts = [0] * 6
for i in range(number):
roll = random.randint(1,6)
counts[roll - 1] += 1
return counts
I can't improve on Martijn Pieters's answer. :-) But this problem can be more conveniently solved using a list.
import random
def rollDie(number):
# create a list with 7 values; we will only use the top six
rolls = [0, 0, 0, 0, 0, 0, 0]
for i in range(0, number):
roll=int(random.randint(1,6))
rolls[roll] += 1
return rolls
if __name__ == "__main__":
result = rollDie(1000)
print(result[1:]) # print only the indices from 1 to 6
And, this is a little bit tricky, but here is a better way to create a list of 7 entries all set to zero:
rolls = [0] * 7
Why count the zeros yourself? It's easier to just make Python do the work for you. :-)
EDIT: The list is length 7 because we want to use indices 1 through 6. There is also a position 0 in the list, but we don't use it.
Another way to do it is to map the dice rolls onto indices. It's a pretty simple mapping: just subtract 1. So, a die roll of 1 would go into index 0 of the list, a die roll of 2 would go into index 1, and so on. Now we will use every position in the list.
Here's that version:
import random
def rollDie(number):
rolls = [0] * 6
for i in range(0, number):
roll=int(random.randint(1,6))
rolls[roll - 1] += 1
return rolls
if __name__ == "__main__":
result = rollDie(1000)
print(result)
You should do random.randint(1, 7), otherwise you will never get a 6.
...
roll = random.randint(1, 7)
import random
def dice():
print random.randint(1,6)
dice()

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