Dice statistics in Python - python

: Repeatedly asks the user for the number of times to roll the dice, quitting only when the user-entered number is less than 1. Hint: Use a while loop that will execute as long as num_rolls is greater than or equal to 1.
I did this but don't know how to do it using while loop.
import random
num_sixes = 0
num_sevens = 0
num_rolls = int(input('Enter number of rolls:\n'))
if num_rolls >= 1:
for i in range(num_rolls):
die1 = random.randint(1,6)
die2 = random.randint(1,6)
roll_total = die1 + die2
#Count number of sixes and sevens
if roll_total == 6:
num_sixes = num_sixes + 1
if roll_total == 7:
num_sevens = num_sevens + 1
print('Roll %d is %d (%d + %d)' % (i, roll_total, die1, die2))
print('\nDice roll statistics:')
print('6s:', num_sixes)
print('7s:', num_sevens)
else:
print('Invalid number of rolls. Try again.')
*

Using a while loop is a very common way to solve some problems in programming languages like C. In Python you can do that as well, but Python has it's own ways to do some things. In your case you have been using a for loop with the range() function. That is more "pythonic" than counting down with while, which is more "C-ish".
Interestingly, the range function is clever and you non't need to do an extra check. Any integer argument < 1 will result in an empty list and the for loop will not be executed. And the for has an else:
for i in range(num_rolls):
# your dicing code
else:
print('Invalid number of rolls. Exiting.')
sys.exit(1) # might be good to signal an error with a return code > 0
# your result printing code
TL;DR: Your code is fine if not better. Only change it if the teacher (?) requires while.

Related

Is there a way the get the sum of randomly generated numbers?

I'm still very new to python so this code is probably not the best way to achieve what I'm looking for.
But regardless, I basically want to create a code that will perform a dice rolling formula and output a total value I can use for data.
what I want to do is get the sum of random generated numbers, however, the amount of numbers generated varies on certain factors, so it can be anywhere from 1 to 3.
Here is a visual representation of what i want:
Roll 3x d20:
(12)(6)(14)
Roll d6 for each value that's equal or greater than 10:
(6)(N/A)(3)
Add 6 to each value"
6+6 = 12
3=6 = 9
(I got the code working up until the above step )
subtract 8 from above values:
12-8 =4
9-8 =1
total:
4+1 = 5
Also I know adding 6 and then subtracting 8 might sound stupid but there's a reason I need it this way.
This is the code I have so far:
import random
while True:
print("_______________________________")
input("press enter to start")
d201 = random.randint(1,20)
d202 = random.randint(1,20)
d203 = random.randint(1,20)
d61 = random.randint(1,6)
d62 = random.randint(1,6)
d63 = random.randint(1,6)
hit = [d201 ,d202 ,d203]
dmg = [d61 ,d62 ,d63]
db = 6
print("hit rolls")
print(hit)
print("damage rolls")
if d201 >= 10:
print(d61, '(roll 1)')
if d202 >= 10:
print(d62, '(roll 2)')
if d203 >= 10:
print(d63, '(roll 3)')
print("damage bonus:")
if d201 >= 10:
print((d61 + db), '(roll 1)+6')
if d202 >= 10:
print((d62 + db), '(roll 2)+6')
if d203 >= 10:
print((d63 + db), '(roll 3)+6')
print("damage total:")
So my first attempt was to add the (d61 + db) , (d62 + db) and (d63 + db) as variables and the creating a variable for those 3, and lastly print the sum of the variable:
dt = [(d61 + db) ,(d62 + db) ,(d63 + db)]
total = sum(dt)
And then at the end of the code:
print("damage total:")
print(total)
How ever this gives me the wrong total, its clearly not taking the results from the previous values.

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")

Dice roller having issues with second while loop

I'm a longterm lurker first time questioner. I'm trying to teach myself Python and while I've researched my question I couldn't find an answer. My below code runs if I remove the first While loop but currently it doesn't seem to enter the second while loop. I think I might be channelling my inner VBA which I use at work and this is only second time I've tried Python.
I've tried changing the first while so it isn't just while true and tried variants on the second while.
The intent here is to investigate a dice pool mechanic for a game I'm thinking of and model rolling multiple D6s, 5-6 explode, 3+ successes and 1-2 failures. Ultimately I want it to run roll the dice return the dice list number of successes etc and then reset asking the user for number of dice to roll again.
import random
Scount = 0
Xcount = 0
Fcount = 0
rollcount = 0
cheat = 0
NoOfDice = 1
Dicelist = []
while True:
print ("Input number of dice to roll")
NoOfDice=input()
while cheat<int(NoOfDice):
rand = random.randint(1, 6)
Dicelist.append(rand)
if rand <= 4:
cheat += 1
if rand >= 3:
Scount += 1
if rand >= 2:
Fcount += 1
if rand <= 5:
Xcount += 1
print (Dicelist)
print ("We rolled " + str(NoOfDice) + " you got " + str(Scount) + " number of succeses with " + str(Xcount) + " number of dice exploded with " + str(Fcount) + " dice failed")
Thank you all and appreciate your time!
The condition for your first while loop is essentially going to always be True, meaning that it's an infinite loop.
Your second loop may not seem like it's running, but it definitely is (as long as you enter a number greater than 0).
The reason your program has no output is because your print() statements are after the infinite loop, so they'll never run. This is why your program runs as desired when you remove the infinite loop.
To fix this, just move your print() statements inside the first loop but at the end.
Note: If you want to get time to read what is being printed when you run the program, you should change the print()s to input()s as this will mean that the first loop only loops around after you've pressed Enter.
Additional Note: random.randint(1, 6) returns a value from 0 to 5 not from 1 to 6. Looking at your values in your if statements, you probably want to change code to:
rand = random.randint(1,6) + 1
Your code could further be condensed using with just 2 if statements instead of 4. Below is my proposed solution. I wrapped it in a function but you don't have to. I'll leave it for you think and decide how to escape the first "while" loop after the second while loop finished execution.
def rolldice ():
... while True:
... scount = 0
... xcount = 0
... fcount = 0
... cheat = 0
... NoOfDice = ''
... DiceList = []
... NoOfDice = input ('Number of dice to roll: ')
... while cheat < int (NoOfDice):
... rand = random.randint(1, 6)
... DiceList.append (rand)
... if rand <= 5:
... cheat += 1
... xcount += 1
... if rand >= 2:
... fcount += 1
... scount += 1
... print ('Dice List: ', DiceList)
... print ('Number of dice rolled:', NoOfDice)
... print ('Success Count: %d' % scount)
... print ('Exploded Count: %d' % xcount)
... print ('Failed Count: %d' % fcount)
...
>>> rolldice()
Number of dice to roll: >? 3
Dice List: [2, 3, 1]
Number of dice rolled: 3
Success Count: 2
Exploded Count: 3
Failed Count: 2
Number of dice to roll: >? 1
Dice List: [5]
Number of dice rolled: 1
Success Count: 1
Exploded Count: 1
Failed Count: 1
Number of dice to roll:

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)

Python - rolling a dice fairly and counting how many 4's I get

So I had to make code that roll a die fairly and counted how many 4's I got. With the help of you all on here I got it to work. Well now I have to created another die and roll them and then add they products together. This is the instructions I've been given.
"Then write another function that simulates rolling two fair dice. The
easy way is to call the function you just wrote, twice, and add the
numbers you get. This should return a number between 2 and 12. It
should calculate BOTH numbers in ONE run – you are counting two
distinct things."
And this is my code freshly fixed.
from random import randrange
def roll():
rolled = randrange(1,7)
if rolled == 1:
return "1"
if rolled == 2:
return "2"
if rolled == 3:
return "3"
if rolled == 4:
return "4"
if rolled == 5:
return "5"
if rolled == 6:
return "6"
def rollManyCountTwo(n):
twoCount = 0
for i in range (n):
if roll() == "2":
twoCount += 1
print ("In", n,"rolls of a pair of dice, there were",twoCount,"twos.")
rollManyCountTwo(6000)
Your code is bad, and hence, not as random as it should be.
randrange(low,up) includes both boundaries.
Look at what you do in the roll function:
you roll a dice. If it is 1, you return "1".
If it is not 1, you roll the dice again! That's simply wrong, and in a game would be considered cheating.
Your roll function is absolutely unnecessary, and can be replaced by
str(randrange(1,6)).
Also, why would you need the numbers as strings? You don't actually use these strings, so just stick with the result of randrange as it is -- a number.
EDIT:
You say
Yeah I'm assuming some of it is unnecessary but it's for a class and this is the way he wants it so I'm trying to keep it how he wants. I thought that's what I was doing but I could find a way around it!
All of it is unnecessary. There is a function that does what you want, so no need to encapsulate this in a class.
Well, you can just
class ash_class(object):
def roll():
return str(randrange(1,6))
For your counting problem: Python comes with all the tools.
counts = [0] * 6 # this is [0,0,0,0,0,0]
for i in range(n):
counts[randrange(1,6)] += 1
print counts
As you notice, it's really handy if the randrange numbers are numbers and not strings, as you can then use them like numbers to index an array.
As a personal advice: There should always be the freedom to discuss bad design choice. One such bad design choice is forcing you to convert numbers to strings, when you clearly need to work with them as numbers.
You shouldn't be calling randrange() inside the roll() in every if condition, instead you should call it once and save it in a variable and check.
The code would look like -
from random import randrange
def roll():
rolled = randrange(1,7)
if rolled == 1:
return "1"
if rolled == 2:
return "2"
if rolled == 3:
return "3"
if rolled == 4:
return "4"
if rolled == 5:
return "5"
if rolled == 6:
return "6"
def rollManyCountFour(n):
fourCount = 0
for i in range (n):
if roll() == "6":
fourCount += 1
print ("In", n,"rolls of a due, there were",fourCount,"fours.")
rollManyCountFour(6000)
I have used np.random.randint(1, 7, N), with N being the number of rolls and have used the following system to store it (if this helps):
R1s = 0
R2s = 0
R3s = 0
R4s = 0
R5s = 0
R6s = 0
for i in range(0, N):
if x[i] == 1:
R1s += 1
elif x[i] == 2:
R2s += 1
elif x[i] == 3:
R3s += 1
elif x[i] == 4:
R4s += 1
elif x[i] == 5:
R5s += 1
else:
R6s += 1
print(R1s)
# Ans ≈ N/6

Categories