Write at least one function to simulate the rolling of dice - python

I have been tasked to write at least one function to simulate the rolling of dice and call that function in a loop for each player, find the total sum of dice roll though find myself heavily suffering from analysis paralysis.
sample output
How many players are rolling dice? 2
How many dice does each player roll? 3
How many sides does each die have? 6
Player 1 rolled:
4
2
4
That totals: 10
Player 2 rolled:
1
3
5
That totals: 9
My code so far
import random
#User inputs
r = int(input("How many times do you want to roll the dice? "))
s = int(input("how many sides do you want "))
p = int(input("How many players are rolling dice?"))
#Function Declaration
def Rolldice(s,r):
for i in range(0,r):
die = random.randint(1, s)
print(die)
#For loop that iterates through function declaration
for num in range(1,p+1):
print(f"player {num} rolled")
Rolldice(s,r)
print(sum(Rolldice))
Though i am receiving error listed below
TypeError: 'function' object is not iterable

The error is caused by the last line print(sum(Rolldice)). Rolldice is a function, you cannot sum over function. I suppose this should solve your problem -
import random
#User inputs
r = int(input("How many times do you want to roll the dice? "))
s = int(input("how many sides do you want "))
p = int(input("How many players are rolling dice?"))
#Function Declaration
def Rolldice(s,r):
dies = []
for i in range(0,r):
die = random.randint(1, s)
print(die)
dies.append(die)
return dies
#For loop that iterates through function declaration
for num in range(1,p+1):
print(f"player {num} rolled")
dies = Rolldice(s,r)
print("That totals:", sum(dies))

The problem comes from your last line:
print(sum(Rolldice))
You are actually passing a function to the sum() function. But if you check the documentation for sum(), it actually requires an iterable to be passed as an argument.
You should actually try to sum the results of your dice direcly in the RollDice function, and return the result.
def Rolldice(s,r):
total = 0
for i in range(0,r):
die = random.randint(1, s)
print(die)
sum += die
return total
Now, you can finally print the total in your main function:
for num in range(1,p+1):
print(f"player {num} rolled")
total = Rolldice(s,r)
print(f"That totals: {total}")

You're cannot iterate over a function. However, you can iterate over it's results.
The first step to fix the code is to call the function and pass its results to sum instead of passing the function itself.
(You do call the function in the previous line but you don't use it's result in sum. This line could be removed.)
Replace print(sum(Rolldice)) with print(sum(Rolldice(s, r))).
Another problem is that you don't return value from the function. You just print it on the screen with print.
Normally returning a value is done via the keyword return but in this case you want to return multiple values. You could create an array of all the values and return it. It is nicely shown in the Vishwas Chepuri's answer.
However, in this case, you could use a generator. In simple words, it's a type of function that can be iterated over and return multiple values.
You can convert a normal function into a generator by returning value via yield keyword instead of return. In opposite to return, yield doesn't end the function.
Replace print(die) with yield die.
import random
#User inputs
r = int(input("How many times do you want to roll the dice? "))
s = int(input("how many sides do you want "))
p = int(input("How many players are rolling dice?"))
#Generator Declaration
def Rolldice(s,r):
for i in range(0,r):
die = random.randint(1, s)
yield die
#For loop that iterates through function declaration
for num in range(1,p+1):
print(f"player {num} rolled")
generator = Rolldice(s,r)
print(sum(generator))
BTW, you can write range(r), instead of range(0,r). It means the same.

Related

Im a little stuck in a dice rolling program in python, am very new to python and very confused

This is what the instructions are telling me to do...
main – This function is the main routine. It should do the following:
Ask the user how many dice they want to roll. If the user enters a number less than 1 or greater than 10, the program should continue to ask the user for a valid number between 1 and 10. Remember you can use a while loop to do input validation.
Once the program has a valid number from the user, it should use that number as an argument when calling the roll_dice function.
roll_dice – This function has one parameter, num_dice, which is the number of dice to roll.
Since the program will be displaying the total of the dice, start by initializing a variable to 0 which will keep a running total.
Use a for loop to roll each die the number of times specified.
Use the randint function from the random module to get a random digit between 1 and 6 inclusive.
Print the number of the loop iteration and the die value as indicated in the Sample Output.
Make sure to update the running total INSIDE the for loop.
After the for loop is complete, print the total value of all the dice that were rolled.
And this is the code I have so far:
import random
def main():
num_dice = int(input('How many dice do you want to roll?'))
while num_dice < 1 or num_dice > 10:
print('Enter a number between 1 and 10.')
num_dice = (input('How many dice do you want to roll?'))
roll_dice(num_dice)
def roll_dice(num_dice):
rolls = 0
for i in range(num_dice):
print(f'Roll #', rolls, random.randint(1, 6))
rolls+=1
main()
There's a few improvements:
you typically don't want to repeat code, so it would be better to only have the input statement in there once (that would have also avoided the mistake you made on the second one);
you are asked to return a sum total of rolls, but also to print each roll; you can either compute it before printing, or print the assigned value directly (with a walrus operator :=)
once you have the total, you'll need to do something with it, like print it.
Something like:
import random
def main():
# you can loop 'forever' and then break out under the right condition
while True:
# you'd forgotten one of the int()
num_dice = int(input('How many dice do you want to roll?'))
if num_dice < 1 or num_dice > 10:
print('Enter a number between 1 and 10.')
else:
break
result = roll_dice(num_dice)
print(f'The total for {num_dice} rolls was {result}.')
def roll_dice(num_dice):
rolls = 0
for i in range(1, num_dice + 1):
# you printed rolls, but you want i, starting at 1
# roll := something, causes roll to be assigned, but also returns the value
print(f'Roll #{i} = {(roll := random.randint(1, 6))}')
rolls += roll
return rolls
main()
(Edit: I noticed that you were already using an f-string in roll_dice, so you may as well make actual use of it)
I like #Blckknght's suggestion for another nice use of the walrus operator in a shorter version of main():
def main():
# you can loop 'forever' and then break out under the right condition
while (n := int(input('How many dice do you want to roll?'))) < 1 or n > 10:
print('Enter a number between 1 and 10.')
result = roll_dice(n)
print(f'The total for {n} rolls was {result}.')
Beware though: if someone asks you to explain your code, you better know what's going on here:
due to short-circuit evaluation, the first part of the or in the while is executed first, and the second part is only executed if the first part is False; that's why you can use the := in the first part and know that num_dice will have been updated for the second part;
the walrus operator assigns the righthand value, but also returns it, so it can be compared to 1
def main():
num_dice = int(input('How many dice do you want to roll?'))
while num_dice < 1 or num_dice > 10:
print('Enter a number between 1 and 10.')
num_dice = (input('How many dice do you want to roll?'))
roll_dice(num_dice)
def roll_dice(num_dice):
rolls = 0
for i in range(num_dice):
print(f'Roll #', rolls, random.randint(1, 6))
out_ran_num = random.randint(1, 6)
rolls+=out_ran_num
return rolls
main()
Please check indentation
First, we want to keep asking the user how many dice they want to roll until they give a valid input, we can do that with a while loop like so:
valid_integer = False
# While the user hasn't given a valid integer
while valid_integer == False:
# Note: this will crash if the user does not input a number
num_dice = int(input('How many dice do you want to roll?'))
# Checking if the input is valid
if num_dice < 1 or num_dice > 10:
print("Please enter a number between 1 and 10")
# Because we did not change the variable valid_integer, it will loop again
else:
valid_integer = True
print(roll_dice(num_dice))
Now we need to create the roll_dice function, it needs to take one parameter (the number of dice to roll) and return a integer (the total of the dice rolls)
import random
# num_dice: int is known as type hinting, it is used to indicate the type of a value
def roll_dice(num_dice: int):
total = 0
for i in range(num_dice):
roll = random.randint(1, 6)
total += roll
return total
Now we can put the code together! We need to put the loop in a function main() and call it. Don't forget your imports!
import random
def main():
valid_integer = False
# While the user hasn't given a valid integer
while valid_integer == False:
# Note: this will crash if the user does not input a number
num_dice = int(input('How many dice do you want to roll?'))
# Checking if the input is valid
if num_dice < 1 or num_dice > 10:
print("Please enter a number between 1 and 10")
# Because we did not change the variable valid_integer, it will loop again
else:
valid_integer = True
print(roll_dice(num_dice))
# num_dice: int is known as type hinting, it is used to indicate the type of a value
def roll_dice(num_dice: int):
total = 0
for i in range(num_dice):
roll = random.randint(1, 6)
total += roll
return total
if __name__ == "__main__":
main()
more info on if __name__ == "__main__" What does if __name__ == "__main__": do?
In main function in while loop there should int for taking input and should use roll_dice function outside while loop. there should be return word to get total as shown in figure
In roll_dies function there should should be rolls+=random.randint(1,6) and also
return rolls outside for loop

A function, adding something within a function, but printing it outside

So i'm stuck with this problem, how can i add something within a function and print it from out of the function
import random
def dieRoll():
sum = 0
for i in range (die-1):
dieThrow = random.randrange( 1, sides+1)
sum += dieThrow
print(dieThrow)
print("That totals: ", sum)
return i
players = int(input("How many players are rolling dice? "))
die = int(input("How many dice does each player roll? "))
sides = int(input("How many sides does each die have? "))
for a in range(1, players+1):
print("Player",a, "rolled: ")
print(dieRoll())
it's supposed to look something like:
Player 1 rolled:
5
4
9
that totals: 18
but i'm getting something like:
Player 1 rolled:
5
4
that totals: 9
9
i feel like the answer is right in front of me but i just can't see it
it's because you print what the function return in the end, if you want such output you have two choices :
print(i)
return("That totals: ", sum)
or the other choice :
print(i)
print("That totals: ", sum)
#replace print(dieRoll())
dieRoll()
The problem is the line
for i in range (die-1):
Try this instead:
for i in range(0, die):
The thing is, the range function by default starts at 0 and "stops" when it gets to the last number (does not execute it), meaning you are not geting to do that last dice roll you expected.
Hope it helps.

Python while loop restarting code from the beginning

Need help adding a while loop to my code to start it from the beginning again after the user agrees to it. Every time I add it at the end of the code it skips it when I run it and I'm not sure how to do it at all. Any help is welcomed. Thank you!
print('Welcome to the Dice Game')
print(" ")
print('This program will simulate rolling a dice and will track the frequency each value is rolled.')
print(" ")
print('After rolling the dice, the program will output a summary table for the session.')
print(" ")
raw_input("Press Enter to continue...")
# function to roll the dice and get a value
def roll_dice():
r=random.randint(1,6)
return r
#to track the number of times rolled the dice
rolled=0
# to track the number of remaining turns
remaining=10000
# list to store the results
result=[]
# to track the number of sessions
sessions=0
while True:
#incrementing the session variable
sessions+=1
#getting the number of turns from the user
n=int(input("How many times would you like to roll the dice? "))
#checking the number of turns greater than remaining turns or not
if n > remaining:
print('You have only remaining',remaining)
continue
#rolling the dice according to the value of n
if rolled <= 10000 and n <= remaining :
for i in range(n):
result.append(roll_dice())
#updating the remaining turns and rolled variables
remaining=remaining-n
rolled=rolled+n
#printing the results and session variable
if rolled==10000:
print('---------------')
for i in range(len(result)):
print('|{:7d} | {:d} |'.format( i+1,result[i]))
print('---------------')
print('Rolled 10000 times in %d sessions' % sessions)
sys.exit(0)
Your rolled, remaining, result and sessions variables persist on the next iteration of the while loop. You need to redefine the variables on each iteration of the loop, because you're checking against the remaining variable to check if the user's turn is over. So instead of:
def roll_dice():
# ...
rolled = 0
remaining = 10000
result = []
sessions = 0
while True:
# ...
you need:
def roll_dice():
# ...
while True:
rolled = 0
remaining = 10000
result = []
sessions = 0
# ...
I see many unnecessary variables and comparisons in your code, a cleaner code usually results less bugs and better readability.
I suggest something like this:
def do_dice_game(rounds=1000):
sessions = 0
rolls = []
while rounds > 0:
sessions += 1
user_input = rounds + 1
while user_input > rounds:
user_input = int(raw_input("..."))
rolls += [random.randint(1, 6) for i in range(user_input)]
rounds -= user_input
# print something
def do_games():
to_continue = True
while to_continue:
do_dice_game()
to_continue = raw_input("...") == "continue"
Also, according to your code, numbers of each session has no effect on the final "rolled" result. You can always just record the number of sessions and then roll 1000 random numbers at the end.

How to run a function several times for different results in Python 3

EDIT: Thanks for each very detailed explanations for the solutions, this community is golden for someone trying to learn coding!! #DYZ, #Rob
I'm a newbie in programming, and I'm trying to make a simple lotto guesses script in Python 3.
The user inputs how many guesses they need, and the program should run the function that many times.
But instead my code prints the same results that many times. Can you help me with this?
I'm pasting my code below, alternatively I guess you can run it directly from here : https://repl.it/#AEE/PersonalLottoEn
from random import randint
def loto(limit):
while len(guess) <= 6: #will continue until 6 numbers are found
num = randint(1, limit)
#and all numbers must be unique in the list
if num not in guess:
guess.append(num)
else:
continue
return guess
guess = [] #Need to create an empty list 1st
#User input to select which type of lotto (6/49 or 6/54)
while True:
choice = int(input("""Please enter your choice:
For Lotto A enter "1"
For Lotto B enter "2"
------>"""))
if choice == 1:
lim = 49 #6/49
break
elif choice == 2:
lim = 54 #6/54
break
else:
print("\n1 or 2 please!\n")
times = int(input("\nHow many guesses do you need?"))
print("\nYour lucky numbers are:\n")
for i in range(times):
result = str(sorted(loto(lim)))
print(result.strip("[]"))
Your loto function is operating on a global variable, guess. Global variables maintain their values, even across function calls. The first time loto() is called, guess is []. But the second time it is called, it still has the 6 values from the first call, so your while loop isn't executed.
A solution is to make the guess variable local to the loto() function.
Try this:
def loto(limit):
guess = [] #Need to create an empty list 1st
while len(guess) <= 6: #will continue until 6 numbers are found
num = randint(1, limit)
#and all numbers must be unique in the list
if num not in guess:
guess.append(num)
else:
continue
return guess

Produce a function that receives the die value and the total number of rolls and prints a single line of the histogram based on the values passed

"You will need to call the function once per possible die value."
I'm a programming noob and have spent about seven hours trying to figure this out.
My code is just a conglomeration of ideas and hopes that I'm headed in the right direction. I desperately need help and want to understand this stuff. I've scoured the message boards for my specific issue in vain. Please assist...
I realize my code is spitting out the result for every possible roll. When I need a program that I.E. when someone chooses to roll 50 times and designates 2 as the die value they desire to single out. The histogram would display how many times 2 was randomly rolled out of 50 rolls as asterisks on a single line of histogram.
My code thus far:
import random
def dice_sum(rolls):
results = 0
dice_sum = 0
for i in range(0, rolls):
results = random.randint(1, 6)
print("Die %d rolled %d." % (i+1, results))
dice_sum += results
print("Total of %d dice rolls is: %d" % (rolls, dice_sum))
return dice_sum
def hist_gram():
hist_gram='*'
dievalue= int(input('Which specific value between 1 and 6 are you requesting? [enter a #]'))
# get user input
rolls = int(input('How many times would you like to roll the 6 sided die? [enter a #]'))
dievalue= int(input('Which specific value between 1 and 6 are you requesting? [enter a #]'))
# pass input values to function and print result
result = dice_sum(rolls=rolls)
print(result)
You're making a mountain out of a molehill. Slow down and think about the problem. They want you to do an action a bunch of times. Then based on what each result is, do something with that information.
We can use a for loop to do the actions many times, as you've used. Then we can check the result using a simple if statement. You're trying to do the processing after the fact and it's making your life more difficult than it needs to be.
Our solution becomes very simple:
import random
def dice_count(rolls, reqValue):
count = 0
for i in range(0, rolls):
if roll_the_dice() == reqValue:
count = count + 1
#Every time we encounter the value, we count up by one
#That's it! return count.
#Apparently we want a 'single line of a histogram',
# which is kind of a pointless histogram, don't you think?
#Turns out you can multiply against strings.
return count*'*'
def roll_the_dice():
#Apparently we need to call the function more than once? Confusing instruction.
return random.randint(1,6)
And now for the input:
You can use a try..catch block to deal with bad input. If someone inputs something that's not a number, the int conversion will create a ValueError. Instead of crashing, we can decide what happens when a ValueError is raised. If an error occurs, just start over - and keep trying until the user gets it right.
def main():
doInput()
def doInput():
rolls = 0
side = 0
#set up the variables, so we can access them outside the try..catch block
try:
rolls = int(raw_input("How many times should the die be rolled? "))
except ValueError:
print "That's not a valid number. Try again!"
doInput()
try:
side = int(raw_input("Which side?"))
if side < 1 or side > 6:
print "That's not a valid side of a die! Try again!"
do_input()
except ValueError:
print "That's not a valid number. Try again!"
do_input()
dice_count(rolls, side)
You'll want to store the result of each die role somehow, rather than just adding up the sum of your roles. This will also extend your function to be able to look at the results of all 50 results if you want, or just one roll at a time.
There are a few data structures you could use, but I'd recommend a dictionary because it's the most intuitive when dealing with storing values associated with events. For example:
from collections import defaultdict
import random
def dice_sum(rolls):
results = defaultdict(int)
for i in xrange(rolls):
this_roll = random.randint(1,6)
results[this_roll] += 1
return results
Running dice_sum(50):
>>> results = dice_sum(5)
>>> results[1]
11
>>> results[2]
5
>>> results[3]
6
>>> results[4]
13
>>> results[5]
8
>>> results[6]
7
Getting a histogram for a single line has been explained, so if you want the whole thing:
def histogram(results):
hist = ""
for i in xrange(1,7):
bar = '#' * results[i]
hist += '{}: {}\n'.format(i,bar)
return hist
Running it:
>>> print histogram(results)
1: ###########
2: #####
3: ######
4: #############
5: ########
6: #######

Categories

Resources