Dice roller having issues with second while loop - python

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:

Related

hailstone program in python

i have to write a hailstone program in python
you pick a number, if it's even then half it, and if it's odd then multiply it by 3 and add 1 to it. it says to continue this pattern until the number becomes 1.
the program will need methods for the following:
accepting user input
when printing the sequence, the program should loop until the number 1.
print a count for the number of times the loop had to run to make the sequence.
here's a sample run:
prompt (input)
Enter a positive integer (1-1000). To quit, enter -1: 20
20 10 5 16 8 4 2 1
The loop executed 8 times.
Enter a positive integer (1-1000). To quit, enter -1: 30
30 15 46 23 70 35 106 53 160 80 40 20 10 5 16 8 4 2 1
The loop executed 19 times.
Enter a positive integer (1-1000). To quit, enter -1: -1
Thank you for playing Hailstone.
right now i have this:
count = 0
def hailstone(n):
if n > 0
print(n)
if n > 1:
if n % 2 == 0:
hailstone(n / 2)
else:
hailstone((n * 3) + 1)
count = count + 1
i don't know what to do after this
Try to think in a modular way, make two functions: check_number() and user_call(). Check_number will verify if the current number in the loop is odd or even and the user_call() just wraps it to count how many times the loop did iterate.
I found the exercise in a great book called Automate Boring Stuff with Python, you have to check it out, if you don't know it already.
Here's my code. Try to use what serves you the best.
from sys import exit
def check_number(number):
if number % 2 ==0:
print(number // 2)
return(number // 2)
else:
print(number*3+1)
return number*3+1
def user_call(number):
count = 0
while number != 1:
count += 1
number = check_number(number)
return count
if __name__ == "__main__":
try:
number = int(input('Give a number \n'))
count = user_call(number)
print('count ',count)
except Exception as e:
exit()
you can use global
visit https://www.programiz.com/python-programming/global-keyword to learn more
import sys
res = []
def hailstone(number):
global res
if number > 1:
if number % 2 == 0:
res.append( number // 2 )
hailstone(res[len(res)-1])
else:
res.append(number * 3 + 1)
hailstone(res[len(res)-1])
return res
number = int(input('Enter a positive integer. To quit, enter -1: '))
if number <= 0 or number == 0:
print('Thank you for playing Hailstone.')
sys.exit()
else:
answers = hailstone(number)
for answer in answers:
print(answer)
print('The loop executed {} times.'.format(len(answers) + 1))
I used recursion to solve the problem.
Heres my code:
Edit: All criteria met
count = 0
list_num = []
def input_check():
number = int(input("Enter a positive integer (1-1000). To quit, enter -1: "))
if number >= 1 and number <= 1000:
hailstone_game(number)
elif number == -1:
return
else:
print("Please type in a number between 1-1000")
input_check()
def hailstone_game(number):
global count
while number != 1:
count += 1
list_num.append(number)
if number % 2 == 0:
return hailstone_game(int(number/2))
else:
return hailstone_game(int(number*3+1))
list_num.append(1) # cheap uncreative way to add the one
print(*list_num, sep=" ")
print(f"The loop executed {count} times.")
return
input_check()
Additional stuff that could be done:
- Catching non-integer inputs using try / except
Keep in mind when programming it is a good habit to keep different functions of your code separate, by defining functions for each set of 'commands'. This leads to more readable and easier to maintain code. Of course in this situation it doesn't matter as the code is short.
Your recursive function is missing a base/terminating condition so it goes into an infinite loop.
resultArray = [] #list
def hailstone(n):
if n <= 0: # Base Condition
return
if n > 0:
resultArray.append(n)
if n > 1:
if n % 2 == 0:
hailstone(int(n/2))
else:
hailstone((n * 3) + 1)
# function call
hailstone(20)
print(len(resultArray), resultArray)
Output
8 [20, 10, 5, 16, 8, 4, 2, 1]
Here's a recursive approach for the problem.
count=0
def hailstone(n):
global count
count+=1
if n==1:
print(n)
else:
if n%2==0:
print(n)
hailstone(int(n/2))
else:
print(n)
hailstone(3*n+1)
hailstone(21)
print(f"Loop executed {count} times")

python append not adding to list

I am trying to learn python and am currently working with a basic dice roll script.
2 die roll until they both hit 6. when it will print the number of rolls it took to hit the defined [6:6].
this repeats 2 more times as seen with
for x in range(3):
roll_dice()
My problem is that when I try to sum the run list it will only print the last dice roll count. I'm thinking my run.append(count) is not updating but resetting once it goes through the loop again?
I understand the rest of my code is probably really inefficient but still early stages of learning.
import random
def roll_dice():
dice_one = 0
dice_two = 0
count = 0
run = []
while True:
dice_one = random.randrange(1,7)
dice_two = random.randrange(1,7)
count += 1
print(dice_one, " ", dice_two)
if dice_one + dice_two == 12:
print("----", count, "attempts----")
break
run.append(count)
print(sum(run))
for x in range(3):
roll_dice()
Like the others have pointed out, the run.append(count) is being called outside the While loop. Due to this, only the last updated value of count is being added to run.
By moving the run.append(count) inside the While loop, it will be updated each time the loop is executed.
Simply put run.append(count) in the while loop:
import random
def roll_dice():
dice_one = 0
dice_two = 0
count = 0
run = []
while True:
dice_one = random.randrange(1,7)
dice_two = random.randrange(1,7)
count += 1
print(dice_one, " ", dice_two)
if dice_one + dice_two == 12:
print("----", count, "attempts----")
break
run.append(count)
print(sum(run))
for x in range(3):
roll_dice()
print(sum(run)) only prints the last dice roll count because run.append(count) is outside the while loop. It is only called once on every function call. Put it inside the while loop and it will append each time you roll the dies.

Heads or Tails / Coin-flip program

I want to write a coin flip or "Heads or Tails" program, but when I run it, it only gets either heads or tails everytime. I can't see why, it's a logical error so I find it hard to spot.
import random
flips = 1
coin = random.randint(1,2)
heads = 0
tails= 0
while flips <= 100:
if coin == 1:
print("Heads")
heads += 1
flips +=1
elif coin == 2:
print("tails")
tails += 1
flips +=1
print("You got", heads, "heads and", tails,"tails!")
input("Exit")
Python removes a lot of code writing that you have to do in other languages. This program is only three lines. Using the random() method, you're able to do this in a very simple matter.
Here is my code.
import random
coin_flip = ['heads','tails']
print random.choice(coin_flip)
import random
flips = 0
heads = 0
tails = 0
while flips < 100:
if random.randint(1,2) == 1:
print("heads")
heads += 1
else:
print("tails")
tails += 1
flips += 1
print("you got ", heads," heads, and ", tails," tails!")
input ("exit")
Changes made: starts from 0 and is only raising count when a flip has been made (also, flip is made every iteration as the cases are contained enough)
also, im not casting the toss to a seperate variable but comparing it immediately.
my output was:
you got 54 heads, and 46 tails!
exit
without listing the seperate flips
Note; this was the first time I ever wrote python. If there's room for optimalisation, let me know!
Try this:
import random
flips = 1
heads = 0
tails= 0
while flips <= 100:
coin = random.randint(1,2)
flips +=1
if coin == 1:
print("Heads")
heads += 1
elif coin == 2:
print("tails")
tails += 1
print("You got " + str(heads) + " heads and " + str(tails) + " tails!")
raw_input("Exit")
Edits i made:
put coins variable in loop so that a new random value is assigned on every call.

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

Modified coin flip program in Python, can't work out the loop

So I'm required to write a lab for my Python class to flip a coin. Yes, it's been asked before, but this one in particular, I haven't seen any examples in any of the searches I've done. The program is supposed to accept input from the user, how many times to flip the coin. It then uses that input to flip the coin said number of times and record how many heads and tails. At the end, it will print the number of flips, and how many heads and tails. The program is then supposed to prompt the user to enter another number of flips, but with my program, each time, it accepts the second input, but skips the loop and ends the program. Also, an input of 0 is supposed to terminate the program. Here are the two examples I've tried:
import random
timesToFlip = input("Enter the number of times to flip the coin: ")
def coinFlipGame(timesToFlip):
coinHeads = 0
coinTails = 0
accumulator = 0
while timesToFlip > 0 and accumulator < timesToFlip:
coinFlip = random.randint(0,1)
if coinFlip == 1:
accumulator += 1
print "After", accumulator, "flip(s) of the coin, the result was heads!"
coinHeads += 1
raw_input("Press [ENTER] to continue...."); print
else:
accumulator += 1
print "After", accumulator, "flip(s) of the coin, the result was tails!"
coinTails +=1
raw_input("Press [ENTER] to continue...."); print
print "Heads =", coinHeads, "| Tails =", coinTails; print
if timesToFlip == 0:
print; print "You have chosen to end the game. Goodbye!"
timesToFlip = input("Enter the number of times to flip the coin: ")
coinFlipGame(timesToFlip); print
And here's the other version:
import random
timesToFlip = input("Enter the number of times to flip the coin: ")
def coinFlipGame(timesToFlip):
coinHeads = 0
coinTails = 0
accumulator = 0
if timesToFlip == 0:
print "You have chosen to end the game. Goodbye!"
else:
while timesToFlip > 0 and accumulator < timesToFlip:
coinFlip = random.randint(0,1)
if coinFlip == 1:
accumulator += 1
coinHeads += 1
print accumulator, "coin flip(s) performed. Heads."
else:
accumulator += 1
coinTails += 1
print accumulator, "coin flip(s) performed. Tails."
print "Flips:", accumulator, "| Heads:", coinHeads, "| Tails:", coinTails
timesToFlip = input("Enter the number of times to flip the coin: ")
coinFlipGame(timesToFlip)
Any help on how to get the input within the module to repeat the loop would be greatly appreciated! :D And yes, we have to use modules in the program, according to the professor.
Its not skipping the loop, your second input is outside the loop. maybe instead do this:
def coinFlipGame(timesToFlip):
coinHeads = 0
coinTails = 0
accumulator = 0
while accumulator < timeToFlip:
coinFlip = random.randint(0,1)
if coinFlip == 1:
accumulator += 1
coinHeads += 1
print accumulator, "coin flip performed. Heads."
else:
accumulator += 1
coinTails += 1
print accumulator, "coin flip performed. Tails."
print "Flips:", accumulator, "| Heads:", coinHeads, "| Tails:", coinTails
timesToFlip = int(input("Enter the number of times to flip the coin: "))
while timesToFlip:
coinFlipGame(timesToFlip)
timesToFlip = int(input("Enter the number of times to flip the coin: "))
Note: you are probably going to want to int() the input
Thank you guys for all the help! Here's the completed code in all its glory :D
'''
_MBE_
CIS-115-09
Lab 6-1
Write a python program, using modules / functions, to simulate flipping
a coin using a random number generator.
If the random number generator returns a 0 consider that a “tails”,
and a return of a 1 a “heads”.
At the beginning of the program ask the user how many times to flip the coin,
keep track of the total “heads” and “tails” and print the results after
the coin has been flipped the requested number of times.
Allow the user to enter another number of times to flip the coin
and re-run the program.
An input of zero (0) times to flip the coin will terminate the program.
'''
print; printHeader = raw_input("Please enter your name: ")
print; print printHeader, "| Lab 6-1"; print
raw_input("Press [ENTER] to continue...."); print
import random # importing the random library to allow for use of random
#random functions later on
# declaring the variable to take input on how many times to flip the coin
timesToFlip = int(input("Enter the number of times to flip the coin: ")); print
# defining the function for the coin flip game
def coinFlipGame(timesToFlip):
coinHeads = 0 # used to store how many times the coin is heads
coinTails = 0 # used to store how many times the coin is tails
accumulator = 0 # ensures that the coin is only flipped a certain number of times
while accumulator < timesToFlip:
coinFlip = random.randint(0,1)
if coinFlip == 1:
accumulator += 1
coinHeads += 1
print "After", accumulator, "flip(s) of the coin, the result was heads!"
raw_input("Press [ENTER] to continue...."); print
else:
accumulator += 1
coinTails += 1
print "After", accumulator, "flip(s) of the coin, the result was tails!"
raw_input("Press [ENTER] to continue...."); print
print "Flips:", accumulator, "| Heads:", coinHeads, "| Tails:", coinTails
while timesToFlip: # a loop to allow the program to keep running until
#an appropriate kill code is entered
coinFlipGame(timesToFlip)
timesToFlip = input("Enter the number of times to flip the coin: "); print
if timesToFlip == 0:
print "You have ended the game. Goodbye!"; print
raw_input("Press [ENTER] to end program....")
# end program

Categories