dice roll simulation in python - python

I am writing a program that is to repeatedly roll two dice until the user input target value is reached. I can not figure out how to make the dice roll happen repeatedly. Please, help...
from random import randrange
print ("This program rolls two 6-sided dice until their sum is a given target value.")
input = int (input("Enter the target sum to roll for:"))
#def main():
dice1 = randrange (1,7)
dice2 = randrange (1,7)
sumofRoll = dice1 + dice2
output = "Roll: {} and {}, sum is {}".format (dice1,dice2,sumofRoll)
print (output)
if sumofRoll == input:
print ("All done!!")
if sumofRoll != input:
#how do I make this repeatedly run until input number is reached?!

Here is a complete working code which takes care of invalid sum entered as input as well. The sum of two dice rolls cannot be either less than 2 or more than 13. So a check for this condition makes your code slightly more robust. You need to initialize sumofRoll = 0 before entering the while loop as this would be needed to first enter the while loop. The value of 0 is a safe value because we excluded the value of 0 entered by user to be a valid sum.
from random import randrange
print ("This program rolls two 6-sided dice until their sum is a given target value.")
input_sum = int(input("Enter the target sum to roll for:"))
def main():
sumofRoll = 0
if input_sum < 2 or input_sum > 13:
print ("Enter a valid sum of dices")
return
while sumofRoll != input_sum:
dice1 = randrange (1,7)
dice2 = randrange (1,7)
sumofRoll = dice1 + dice2
output = "Roll: {} and {}, sum is {}".format (dice1,dice2,sumofRoll)
print (output)
if sumofRoll == input_sum:
print ("All done!!")
main()
This program rolls two 6-sided dice until their sum is a given target value.
Enter the target sum to roll for:10
Roll: 3 and 5, sum is 8
Roll: 6 and 6, sum is 12
Roll: 5 and 1, sum is 6
Roll: 2 and 5, sum is 7
Roll: 6 and 6, sum is 12
Roll: 3 and 5, sum is 8
Roll: 1 and 2, sum is 3
Roll: 6 and 4, sum is 10
All done!!

I took your game and added some elements for you to peek through. One is you could use random.choice and select from a die list instead of generating new random ints repeatedly. Second you can use a try/except block to only accept an int and one that is within the range of (2, 13). Next we can add a roll_count to track the amount of rolls to hit our target. Our while loop will continue until target == roll_sum and then we can print our results.
from random import choice
die = [1, 2, 3, 4, 5, 6]
print('This program rolls two 6-sided dice until their sum is a given target.')
target = 0
while target not in range(2, 13):
try:
target = int(input('Enter the target sum to roll (2- 12): '))
except ValueError:
print('Please enter a target between 2 and 12')
roll_sum = 0
roll_count = 0
while target != roll_sum:
die_1 = choice(die)
die_2 = choice(die)
roll_sum = die_1 + die_2
roll_count += 1
print('You rolled a total of {}'.format(roll_sum))
print('You hit your target {} in {} rolls'.format(target, roll_count))
...
You rolled a total of 4
You rolled a total of 12
You hit your target 12 in 29 rolls

This is a simple while loop:
sumofRoll = -1; #a starting value!
while sumofRoll != input:
#Put the code that updates the sumofRoll variable here

count = 0
while(sumOfRoll != input):
dice1 = randrange(1,7)
dice2 = rangrange(1,7)
count = count + 1
sumOfRoll = dice1 + dice2
print("sum = %s, took %s tries" % (sumOfRoll, count))

Use a do while statement
do:
dice1=randrange(1,7)
...
while(sumofroll != input)
print("all done")

Related

Python - checking a list for possible patterns and if the list meets a specific condition

I'm a novice making a small game for learning purposes.
The game rolls dice based on the inputs of the user.
The part I'm having trouble with is I want to check for patterns in the list "rolls"
patterns include:
all dice are the same value and the # of sides >=4 EXAMPLE [1, 1, 1, 1] < values are the same, atleast 4 sides. If true then mutiply user_Score by 10
at least half of the dice are >= "average_sum" with the condition that the list must have >= 5 dice
EXAMPLE if avg_sum = 2 and rolls = [2,3,4,1,1,] If true then mutiply user_Score by 5
all of the dice are different values with the conditions # of dice > 4 and # of sides > # of dice
[10, 11, 12, 13, 14]
No pattern matches. -> Multiply user_Score by 1
number_dice = int( input( "How many dice are you using? Must be between 3-6 inclusive" ) )
faces = int( input( "how many sides are on your die? enter a number between 2-20 inclusive: "))
# Set range for number of dice
#generate a random number between 1 and faces
#Add dice_roll to the list
rolls = []
for die in range(number_dice):
dice_roll = random.randint(1, faces)
rolls.append(dice_roll)
#print the score from each dice rolled
print("You have rolled: " + str(rolls))
#calculate sum of score
sum = sum(rolls)
#calculate the average and round to the nearest integer
average_sum = round(sum / number_dice)
print("These die sum to: " + str(sum) + " and have an average value of: " + str(average_sum))
#Calculate the max possible score
max_score = (number_dice * faces)
#calculate the users score
user_score = float( sum / max_score )
print("your max possible score is " + str(max_score))
print("your score is " + str(user_score))
#-----------------------------------------------------------------------------------
#now calculate the bonus factor
#Check if the list "rolls" contains the same value for each index
if rolls == {repeatingvalues???} and rolls {number_dice>=4}:
user_Score * 10
elif rolls == {half of dice > average} and {number_dice >=5}:
user_Score * 5
elif rolls == {all dice have different values} and { number_dice > 4}{faces> number_dice}:
user_score * 8
else:
user_score * 1
Not sure how to make this statement search the list for a pattern^^^^^^
Define a function to check for a repeating pattern that returns True or False
def has_repeats(my_list):
first = my_list[0]
for item in mylist:
if not item == first:
return False
return True
And then define a function to check for a no duplicates that returns True or False
def all_different(my_list):
# Remove duplicates from list
my_list2 = list(dict.fromkeys(my_list))
return len(my_list) == len(my_list2)
And finally define a function to check if half the dice are greater than the average:
def half_greater_than_averge(my_list, average):
a = 0
b = 0
for item in my_list:
if item > average:
a += 1
else:
b += 1
return a > b
So you final checks will be:
if has_repeats(rolls) and number_dice >= 4:
user_Score * 10
elif half_greater_than_averge(rolls, average_sum) and number_dice >= 5:
user_Score * 5
elif all_different(rolls) and number_dice > 4 and faces > number_dice:
user_score * 8
else:
user_score * 1
Check out my solution where add # ------ SOLUTION STARTS HERE -------
I helped refactor your code too. You shouldn't be using sum as a variable name (or identifier) in your code cos it's a reserved python keyword. So I changed it to my_sum. Check if it still works as desired.
import math # import math at the top
import random
number_dice = int( input( "How many dice are you using? Must be between 3-6 inclusive" ) )
faces = int( input( "how many sides are on your die? enter a number between 2-20 inclusive: "))
# Set range for number of dice
#generate a random number between 1 and faces
#Add dice_roll to the list
for die in range(number_dice):
dice_roll = random.randint(1, faces)
rolls.append(dice_roll)
#print the score from each dice rolled
print("You have rolled: " + str(rolls))
#calculate sum of score
my_sum = sum(rolls)
#calculate the average and round to the nearest integer
average_sum = round(my_sum / number_dice)
print("These die sum to: " + str(my_sum) + " and have an average value of: " + str(average_sum))
#Calculate the max possible score
max_score = (number_dice * faces)
#calculate the users score
user_score = float( my_sum / max_score )
print("your max possible score is " + str(max_score))
# ------ SOLUTION STARTS HERE------
rolls.sort()
rolls.reverse()
for item in rolls:
if (rolls.count(item) >= 4) and (number_dice >= 4):
user_score *= 10
break
elif (rolls[math.ceil(len(rolls)/2) -1] >= average_sum ) and (number_dice >= 5):
user_score *= 5
break
elif (sorted(rolls)==sorted(list(set(rolls))))and (number_dice > 4) and (faces > number_dice):
user_score *= 8
break
else:
user_score *= 1
# ------ SOLUTION ENDS HERE------
print("your score is " + str(user_score))
Here is a simple, faster and more 'Pythonic' way of doing it.
if all(x == rolls[0] for x in rolls):
print("Same")
elif len(rolls) == len(set(rolls)):
print("Unique")
elif number_dice/2 <= [x > avg_sum for x in rolls].count(True):
print("Half")
else:
print("No match")
The 'and' conditions are missing. Please feel free to add them.
Bonus
from random import randint
faces = int(input('Number of faces:'))
number_dice = int(input('Number of dice:'))
rolls = [randint(1, faces) for _ in range(number_dice)]
Feel free to explore

ahtzee Upper Section Scoring

Description
The game of Yahtzee is played by rolling five 6-sided dice, and scoring the results in a number of ways. You are given a Yahtzee dice roll, represented as a sorted list of 5 integers, each of which is between 1 and 6 inclusive. Your task is to find the maximum possible score for this roll in the upper section of the Yahtzee score card. Here's what that means.
For the purpose of this challenge, the upper section of Yahtzee gives you six possible ways to score a roll. 1 times the number of 1's in the roll, 2 times the number of 2's, 3 times the number of 3's, and so on up to 6 times the number of 6's. For instance, consider the roll [2, 3, 5, 5, 6]. If you scored this as 1's, the score would be 0, since there are no 1's in the roll. If you scored it as 2's, the score would be 2, since there's one 2 in the roll. Scoring the roll in each of the six ways gives you the six possible scores:
0 2 3 0 10 6
it has been 3 days i am trying to program it right, but i have a problem in the elif len() == 1, when there is for example [1,1,2,6,4] it prints out 6 while it has to print 2 (bcs 1 is repeated twice)
import random
dice1 = random.randint(1,6)
dice2 = random.randint(1,6)
dice3 = random.randint(1,6)
dice4 = random.randint(1,6)
dice5 = random.randint(1,6)
result = [dice1,dice2,dice3,dice4,dice5]
one_rep = result.count(1)
two_rep = result.count(2)
three_rep = result.count(3)
four_rep = result.count(4)
five_rep = result.count(5)
six_rep = result.count(6)
reps = [one_rep,two_rep,three_rep,four_rep,five_rep,six_rep]
repsnum = [one_rep*1,two_rep*2,three_rep*3,four_rep*4,five_rep*5,six_rep*6]
repeated= []
test = [1]
def yahtzee():
for x in reps:
if x > 1:
repeated.append(x*(reps.index(x)+1))
s = repeated[0]
if reps.count(1) == 5:
score = max(result)
elif len(repeated) == len(test):
score = s
else:
score = max(repsnum)
return f'Your result is {dice1},{dice2},{dice3},{dice4},{dice5}\nYour score is {score}'
yahtzee()
print(yahtzee())
i have found the solution and here is the code:
import random
def yahtzee(result = [random.randint(1,6),random.randint(1,6),random.randint(1,6),random.randint(1,6),random.randint(1,6)]):
reps = [result.count(1),result.count(2),result.count(3),result.count(4),result.count(5),result.count(6)]
repsnum = [result.count(1)*1,result.count(2)*2,result.count(3)*3,result.count(4)*4,result.count(5)*5,result.count(6)*6]
repeated= []
for x in reps:
if x > 1:
repeated.append(x)
if reps.count(1) == 5:
score = max(result)
elif len(repeated) == 1:
score = repeated[0]*(reps.index(repeated[0])+1)
else:
score = max(repsnum)
return f'Your result is {result[0]},{result[1]},{result[2]},{result[3]},{result[4]}\nYour score is {score}'
print(yahtzee())

Python Dice Rolling game - How to check separate rolls and add total

Hi guys I am in the midst of creating a dice in game in python. Below is my working code. So far if a player were to roll the dice one time, I can easily check if the rolled number is 1, however how can I make it so that if I want to roll lets say 10 times, I want to be able to check if any of those 10 rolls, any of them equaled 1, and then stop it, if none equaled 1, I would add them all up.
Basically How do I check the result of each seperate roll, and adding them up if a 1 is not rolled.
import random
import sys
def rollingdice(roll): #define function
total = 0 #starting count
for i in range(roll):
total+= random.randint(1, 6)
if total == 1:
print("You rolled a 1: You have zero points for the round")
else:
print(total)
main()
def main():
roll=int(input("Player 1: How many times will you roll "))
rollingdice(roll)
main()
Just add a variable to hold the rolled number and check if it is 1, then break out of the loop if it is
def rollingdice(roll): #define function
total = 0 #starting count
for i in range(roll):
rolled = random.randint(1, 6)
if rolled == 1:
print("You rolled a 1: You have zero points for the round")
break
total += rolled
if rolled != 1: print(total)
main()
Another approach:
from itertools import takewhile
import random
def rollingdice(roll):
rolls = (random.randint(1, 6) for i in range(roll))
rolls = list(takewhile(lambda n: n != 1, rolls))
if len(rolls) == roll:
print(total)
else:
print("You rolled a 1: You have zero points for the round")

Calculating an average of multiple random numbers Python

I am fairly new to Python and have run into a roadblock with trying to calculate an average of a bunch of random numbers.The general overview of the program is that it is a die rolling program which prompts the user to enter a certain amount of sides and it then rolls until the program outputs snake eyes. It also keeps track of the amount of doubles rolled and how long it took to get snake eyes. Then create an average of the numbers that were rolled for each die throughout the program. This is where I am lost.
EDIT: I deleted my original code and worked in Vasilis's answer:
import random
while True:
#prompts user for valid number
user_s = int (input ("How many sides on your dice? "))
if user_s < 3:
print("That is not a valid size value, please enter a positive number")
if user_s >= 3:
break
print()
print("Thanks! Here we go...")
print()
double_count = 0
roll_count = 0
sum1 = 0 # Used to calculate sum of die_1
sum2 = 0 # Used to calculate sum of die_2
while True:
roll_count += 1
die_1 = random.randint(1,user_s)
die_2 = random.randint (1,user_s)
print(roll_count,".", " Die number 1 is ", die_1 , " and die number 2 is ", die_2, ".", sep ="")
if die_1 == die_2:
double_count += 1
if die_1 == 1 and die_2 == 1:
break
# Making sum
sum1 = sum1 + die_1
sum2 = sum2 + die_2
print("You finally got snake eyes on try number", roll_count)
print("Along the way you rolled a double", double_count,"times")
print(die_1)
print(die_2)
# Integer divisions
avg_roll1 = sum1 // roll_count
avg_roll2 = sum2 // roll_count
print("The average roll for die 1 was", format(avg_roll1,".2f"))
print("The average roll for die 2 was", avg_roll2)
However like he pointed out it doesn't take all of the numbers that is recorded through all the rolls, rather the last number.
Any help to accomplish that would be appreciated.
Thanks!
I made a few changes in your code if you like to take a look. I assumed that you wanted the average to be calculated as an integer although you can change that. You use die_1 and die_2 as simple integer variables and thus they hold only the last value generated by random.randint(1,user_s):
import random
'''Skipped input part'''
print()
print("Thanks! Here we go...")
print()
double_count = 0
roll_count = 0
sum1 = 0 # Used to calculate sum of die_1
sum2 = 0 # Used to calculate sum of die_2
while True:
roll_count += 1
die_1 = random.randint(1,user_s)
die_2 = random.randint (1,user_s)
print("DIE_1: ", die_1)
print("DIE_2: ", die_2)
print(roll_count,".", " Die number 1 is ", die_1 , " and die number 2 is ", die_2, ".", sep ="")
if die_1 == die_2:
double_count += 1
if die_1 == 1 and die_2 == 1:
break
# Making sum
sum1 = sum1 + die_1
sum2 = sum2 + die_2
print("You finally got snake eyes on try number", roll_count)
print("Along the way you rolled a double", double_count,"times")
print(die_1)
print(die_2)
# Integer divisions
avg_roll1 = sum1 // roll_count
avg_roll2 = sum2 // roll_count
print("The average roll for die 1 was", avg_roll1)
print("The average roll for die 2 was", avg_roll2)
Got it myself.
Set the accumulator variable = to the die rolls. In this case sum1 and sum2 are the variables.
# make all of the functions in the "random" module available to this program
import random
while True:
#prompts user for valid number
user_s = int (input ("How many sides on your dice? "))
if user_s < 3:
print("That is not a valid size value, please enter a positive number")
if user_s >= 3:
break
print()
print("Thanks! Here we go...")
print()
double_count = 0
roll_count = 0
sum1 = 0 # Used to calculate sum of die_1
sum2 = 0 # Used to calculate sum of die_2
#while statement for die rolls
while True:
roll_count += 1
die_1 = random.randint(1,user_s)
sum1 += die_1
die_2 = random.randint (1,user_s)
sum2 += die_2
print(roll_count,".", " Die number 1 is ", die_1 , " and die number 2 is ", die_2, ".", sep ="")
if die_1 == die_2:
double_count += 1
if die_1 == 1 and die_2 == 1:
break
print("You finally got snake eyes on try number", roll_count)
print("Along the way you rolled a double", double_count,"times")
# Integer divisions
avg_roll1 = sum1 / roll_count
avg_roll2 = sum2 / roll_count
print("The average roll for die 1 was", format(avg_roll1,".2f"))
print("The average roll for die 2 was", format(avg_roll2,".2f"))

Count throws for sixes in rolling dice python

For an introductionary course in Python I got an assignment to make a simulation for eolling dice
You want all of your dices (5 in total) to get the value six, and count how many throws in total it takes for a person to get all sixes. I need a loop that simulates this problem 100.000 times and then need to divide the total amount of counts by 100.000 to get the outcome. I know that the final outcome should be something around 13, but I am not getting that and I am not sure why.
I know something is wrong in my approach to this problem , but what?
import random
count1=0
count2=0
count3=0
count4=0
count5=0
loopcounter = 0
for loopcouter in range (1,100000):
dice1=int( random.random()*6)+1
if dice1 != 6:
#reroll
while dice1 != 6:
dice1=int( random.random()*6)+1
#set counter1
count1 = count1+1
else:
count1 = 1
dice2=int( random.random()*6)+1
if dice2 != 6:
#reroll while not six
while dice2 != 6:
dice2=int( random.random()*6)+1
#set counter2
count2 = count2+1
else:
count2 = 1
dice3=int( random.random()*6)+1
if dice3 != 6:
#reroll while not six
while dice3 != 6:
dice3=int( random.random()*6)+1
#set counter3
count3 = count3+1
else:
count3 = 1
dice4=int( random.random()*6)+1
if dice4 != 6:
#reroll while not six
while dice4 != 6:
dice4=int( random.random()*6)+1
#set counter4
count4 = count4+1
else:
count4 = 1
dice5=int( random.random()*6)+1
if dice5 != 6:
#reroll while not six
while dice5 != 6:
dice5=int( random.random()*6)+1
#set counter5
count5 = count5+1
else:
count5 = 1
#print (dice1)
print (count1)
#print (dice2)
print (count2)
#print (dice3)
print (count3)
#print (dice4)
print (count4)
#print (dice5)
print (count5)
allcount = count1+count2+count3+count4+count5
averagecount = int(allcount / 100000)
print ("the total number of throws is",allcount)
print ("the average number of throws is",averagecount)
So, if anyone could tell me what I am doing wrong, that would be perfect!
Here is a very different approach.
Let's make an object, die, that will roll until it hits the target:
import random
class die(object):
def __init__(self, sides=6):
self.sides=sides
self.count=0
def roll(self):
self.count+=1
return random.randint(1,self.sides)
def roll_until(self, tgt, giveup=100000):
result=0
self.tgt=tgt
while result!=tgt and self.count<giveup:
result=self.roll()
if self.count<giveup:
return self.count
Then you can just create an instance of that (a single die) and tell it to roll itself until a target is hit:
>>> d=die()
>>> d.roll_until(6)
2
>>> d.tgt
6
>>> d.count
2
2 is the number of times d needed to be rolled until 6 is the result with a 6 sided die.
Why do it this way? Now you can easily create a list of die:
>>> dice=[die().roll_until(6) for i in range(6)]
>>> dice
[15, 3, 3, 4, 5, 2]
And easily answer your questions.
Take the max of this list:
>>> max(die().roll_until(6) for i in range(6))
9
n times divided by float(n) for the result:
>>> n=100000
>>> sum(max(die().roll_until(6) for i in range(6)) for i in range(n))/float(n)
13.95879
Whoops! Only five dice in a game of Yatzee. Easy change:
>>> sum(max(die().roll_until(6) for i in range(5)) for i in range(n))/float(n)
13.0032
According to the instructions you need the maximum of count for each round as this will tell you how many rolls you needed to get all 6s.
This is a re-write of your code using a loop for each dice:
import random
allcount = 0
for loopcouter in range(100000): # 1,100000 would only loop 99999 times
count = [0]*5
for i in range(5): # 5 dice
while True:
dice = random.randint(1,6) # Use randint
count[i] += 1
if dice == 6:
break
allcount += max(count) # The number of rolls needed to get all 6s
averagecount = allcount // 100000
print("the total number of throws is", allcount)
print("the average number of throws is", averagecount)
And this seems to average in 12/13 range.
There are many ways to solve this for example you can use iter and an anonymous function lambda to replace the inner while loop. These start to use more advanced features of python (iterators and generators):
from random import randint
allcount = 0
for _ in range(100000):
counts = [1]*5
for i in range(5):
dice = list(iter(lambda: randint(1,6), 6))
counts[i] += len(dice)
allcount += max(counts)
averagecount = allcount // 100000
In fact you can completely collapse this into one line of code but it gets increasingly harder to read and breaks all sorts of manner of style:
allcount = sum(max((1 + sum(1 for _ in iter(lambda: randint(1, 6), 6)))
for _ in range(5)) for _ in range(100000))
averagecount = allcount // 100000
With your new edit, the counts should still start with 0 but you should also increase your counters once before you go into the while loop, because this already marks one roll.
Also, you should use a different function to determine your random integer. Instead of using
(random.random() * 6) + 1
use:
random.randint(1,6)

Categories