While loop doesn't end function [duplicate] - python

This question already has answers here:
How to test multiple variables for equality against a single value?
(31 answers)
Closed 4 years ago.
I've been driving myself insane trying to troubleshoot and fix this. I cerated this dice rolling game with bets. I'm pretty new to coding, so I'm sure it's a simple error that I just keep overlooking.
The only issue is that it will not end the game if the user inputs "no".
The function doesn't return any errors. It runs and even prints GAME OVER before it returns the values used to find out if the player wants to play another round.
What happens is that it prints the game over, and then loops the diceRoll function without stopping it.
Picture uploaded to show what I mean.
And the code:
#pylint:disable=W0312
#python 3.6
from random import randint
import math
# Static Variables
START_BALANCE = 2500
# Game messages
BAD_GUESS = "ERROR! You can only enter a number between 1 and 6.\n- Your input was '{}'.\n"
BAD_BET = "ERROR! You can not bet less than 0 or more than your current balance {}$.\n"
userName = input("What is your name, player?\n").title()
print("Hello, {}! Welcome to the dice rolling game v.2!\n".format(userName))
def get_guess():
try:
guess = input("Enter a guess from 1 to 6, {}\n".format(userName))
guess = int(guess)
while (guess <= 0 or guess > 6):
print(BAD_GUESS.format(guess))
return get_guess()
except ValueError:
print(BAD_GUESS.format(guess))
return get_guess()
else:
print("Your guess is: {}.".format(guess))
return guess
def get_bet(balance):
try:
bet = input("\nHow much do you want to bet? Your balance is: {}$\n".format(balance))
bet = int(bet)
while (balance < bet) or (bet < 0):
print(BAD_BET.format(balance))
return get_bet(balance)
except ValueError:
print(BAD_BET.format(balance))
return get_bet(balance)
else:
print("You have bet {}$!\n- Your remaining balance is: {}$".format(bet, balance - bet))
return bet
#### FUNC START ####
def diceRoll(balance):
bet = get_bet(balance)
guess = get_guess()
balance -= bet
roll = randint(1,6)
if (roll == guess):
prize = bet * float(3.75)
prize = math.ceil(prize)
balance += prize
print("\nYOU WIN {}$!".format(prize))
print("You guessed: {} - The roll was {}!\n".format(guess, roll))
print("-- Your balance is now {}$ -- \n".format(balance))
elif (roll != guess):
print("\nYOU LOSE {}$".format(bet))
print("The roll was: {} - You guessed: {}.".format(roll,guess))
print("-- Your balance is now {}$ --\n".format(balance))
#
choice = input("Would you like to try again? Y/N\n").upper()
#
if (balance <= 0 or choice == "YES" or "Y"):
print("New round! Your balance is {}$".format(balance))
return [True, balance]
else:
print("GAME OVER! \n Balance: {}$".format(balance))
return [False, balance]
# Initialize game_state, which is a variable that keeps track of your rounds and balance.
game_state = [True, START_BALANCE]
# game_state[0] contains True if the user wants to play again, False if not.
# So if it's false, while (game_state[0]) will evaluate to false and stop the while loop.
while game_state[0]:
game_state = diceRoll(game_state[1])
# TODO: Build a while loop that executes any time the first item in game_state is True (i.e., while the
# user still wants to play a new round. Note that I initialized game_state[0] to True, assuming that
# if they started the program, they want to play the first round.

Inside diceRoll() function this should be changed from:
if (balance <= 0 or choice == "YES" or "Y")
to
if (balance <= 0 or choice == "YES" or choice == "Y")
to properly compare with the choice value.
In your case to make it clearer you are having 3 condition:
balance <= 0
choice == "YES"
"Y"
with the third one being always True. It doesn't check if choice has Y value but if the string provided "Y" in your case is equal to None or not and obviously it's not so it's always True.

In addition to the answers given, I recommend a list of positive choice strings and check if choice is in it.
acceptables = ["yes", "y", "yup", "yeah", "sure", "absolutely", "1", "roger"]
if (balance <= 0 or choice.lower() in acceptables)
.lower() converts the input string into lower case, so you don't have to bother about that. If you want to allow more than the examples in the above case, you can always add them as you wish. Same for, "no", "nope", "no way", "never", "0", ...

Related

Guess the number, play again

I'm making a guess the number game. My code is almost complete but I need to make it so that the program asks the player if they want to play again and then restarts. Could someone help me with how I should go about that? I tried making a new function ex. def game_play_again and then call the game_play() function but it's not reseting the attempts which leads to it not looping correctly.
This is my code right now
import random
MIN = 1
MAX = 100
attempts = 5
win = False
number = random.randint(MIN,MAX)
last_hint = f"{'EVEN' if number%2 == 0 else 'ODD'}"
#print game instructions
def game_start():
print(f"Im thinking of a number between {MIN} and {MAX}. Can you guess it within
{attempts} attempts? ")
input("Press enter to start the game ")
#process user input
def game_play():
global number, attempts, last_hint, win
while attempts > 0:
print()
print(f"You have {attempts} {'attempts' if attempts > 1 else 'attempt'} left.")
if attempts == 1:
print(f"This is your last chance. So i'll give you one more hint. Its's an {last_hint} number.")
while True:
try:
guess = int(input("Try a lucky number: "))
if guess in range(MIN, MAX+1):
break
else:
print(f"Please enter numbers between {MIN} and {MAX} only!")
except ValueError:
print("Plese enter numbers only!")
if guess == number:
win = True
break
if attempts == 1:
break
if guess > number:
if guess-number > 5:
print("Your guess is too high. Try something lower.")
else:
print("Come on you are very close. Just a bit lower.")
else:
if number-guess > 5:
print("Your guess is too low. Try something higher.")
else:
print("Come on you are very close. Just a bit higher.")
attempts -= 1
#print game results
def game_finish(win):
if win:
print("Congratulations you guessed it!")
else:
print(f"The number I was thinking of is {number}. Sorry you lost. Better luck next time!")
game_start()
game_play()
game_finish(win)
You can simply reset your variables to initial values and then call game_play()
def game_finish(win):
if win:
print("Congratulations you guessed it!")
else:
print(f"The number I was thinking of is {number}. Sorry you lost. Better luck next time!")
want_play_again = int(input("Want play again? [1-Yes / 2-No]"))
if want_play_again == 1:
game_play_again()
else:
print("Bye")
/
def game_play_again():
attempts = 0
win = False
game_play()
Within a while(True) loop, write a menu driven statement asking the user if they want to repeat. If they do, initialise values and call game methods. If they do not, break the loop.
pseudocode:
while(True):
choice = input('play again? y/n)
if choice=='y':
attempts, win = 5, False
number = random.randint(MIN,MAX)
last_hint = f"{'EVEN' if number%2 == 0 else 'ODD'}"
game_start()
game_play()
game_finish()
elif choice=='n':
break
else:
print('invalid input')
The above code should be in main, with all methods within its scope.
Better yet, in place of all the initializations, add an init() method declaring them and call them when necessary.
The indentation in the code you have submitted is faulty, so I'm not sure if a related error is involved.

Roulette simulation in Python

I am practicing in Python and I decided to create a simple roulette simulation with colors only for now. However, I also wanted to make it possible to bet on color. But it seems like I did something wrong, since for some reason I can't use the global variable 'balance' in one of the function. Also, I didn't come up with the idea of how to make bet a global variable. I tried to take it out so that it become the global variable with input function, however in this case it has the same issue as with balance variable.
import random
balance = 100
# user decides how much they will bet
def start():
print("Place your bet:")
bet = int(input(">"))
if bet > balance:
insufficient_funds()
else:
simulate()
# if user placed too much
def insufficient_funds():
print("Oops, your don't have enough funds to place a bet")
start()
# color choose and roulette simulation
def simulate():
print("Choose Red or for Black:")
answer = input("> ")
result = random.randint(1, 2)
if result == 1 and answer == "Red":
print("You won")
balance += bet
print(f"Your balance now {balance}")
start()
elif result == 2 and answer == "Black":
print("You won")
balance += bet
print(f"Your balance now {balance}")
start()
else:
print("You lost!")
balance -= bet
print(f"Your balance now {balance}")
start()
start()
I know it is super basic, but for now I try to make it as simple as possible to practice with python's fundamental things w/o using a lot of modules. I'd extremely appreciate if you could help me out with it.
Your code is awesome. The way python works, you have to explicitly tell it that you're going to use a global variable by using the global keyword. If you don't, it will create a new local variable within the function. Try:
import random
balance = 100
# user decides how much they will bet
def start():
global balance
print("Place your bet: ")
bet = int(input(">"))
if bet > balance:
insufficient_funds()
else:
simulate(bet)
# if user placed too much
def insufficient_funds():
print("Oops, your don't have enough funds to place a bet")
start()
# color choose and roulette simulation
def simulate(bet_amount):
global balance
print("Choose Red or for Black:")
answer = input("> ")
result = random.randint(1, 2)
if result == 1 and answer == "Red":
print("You won")
balance += bet_amount
print(f"Your balance now {balance}")
start()
elif result == 2 and answer == "Black":
print("You won")
balance += bet_amount
print(f"Your balance now {balance}")
start()
else:
print("You lost!")
balance -= bet_amount
print(f"Your balance now {balance}")
start()
start()
This is how you let Python know you're calling a global variable. To avoid variable shadowing, we can use bet in the start function, and then when we call it in the simulate function, we'll tell it that we need a bet_amount.
Your functions should isolate levels of concerns that are semantically meaningful. This would make the code easier to understand and maintain. The process can be decomposed into:
A betting phase where the user selects a pocket and bet amount
A rolling phase where the ball is rolled and falls in a random pocket
A game loop to repeatedly go through the phases and update wins & losses.
Each function should be standalone and perform its work without affecting data outside of it (i.e. no global variable). This will allow testing the "phase" functions independently before putting them together in the main loop. If you find any issue while testing these functions, you will know that there is no dependencies from external states so the problem is in the limited scope of the function itself.
Here's an example:
Rolling Phase...
from random import choice
from time import sleep
# CONSTANTS
pockets = ["00"]+[str(n) for n in range(37)]
groups = ["Red","Black","Even","Odd","Low","High"]
reds = [1,3,5,7,9,12,14,16,18,19,21,23,25,27,30,32,34,36]
def roll():
print("Rolling! ... ", end="")
sleep(2)
number = choice(pockets)
N = int(number)
color = "" if N<1 else "Red" if N in reds else "Black"
oddEven = "" if N<1 else "Odd" if N%2 else "Even"
lowHigh = "" if N<1 else "Low" if N<=18 else "High"
print(number, color)
return number,color,oddEven,lowHigh
Betting Phase...
def placeBet(maxAmount):
while True:
playerChoice = input("Pocket number or group: ")
if playerChoice not in pockets + groups:
print("must chose a number (00,0,1..36)")
print("or group (Red, Black, Odd, Even, Low, High)")
else: break
while True:
betValue = input("Amount to bet: ")
try:
betValue = int(betValue)
if betValue <= maxAmount: break
print("Not enough funds")
except ValueError:
print("invalid number")
return playerChoice, betValue
Main game loop...
def playRoulette(balance=100):
while balance:
pocket, amount = placeBet(balance)
if pocket in roll():
print("You win!")
balance += amount # or balance += payBack(pocket,amount)
else:
print("You lose!")
balance -= amount
print(f"Your balance is now {balance}")
print("Game Over!")
Winning payback could be computed in a separate function if you want to make it dependent on the odds of the selected pocket (e.g. a specific number is 35 to 1; Red, Even, ... are 1 to 1 bets)
Testing
roll()
Rolling! ... 6 Black
('6', 'Black', 'Even', 'Low')
roll()
Rolling! ... 33 Black
('33', 'Black', 'Odd', 'High')
placeBet(50)
Pocket number or group: green
must chose a number (00,0,1..36)
or group (Red, Black, Odd, Even, Low, High)
Pocket number or group: 99
must chose a number (00,0,1..36)
or group (Red, Black, Odd, Even, Low, High)
Pocket number or group: Red
Amount to bet: xxx
invalid number
Amount to bet: 65
Not enough funds
Amount to bet: 24
('Red', 24)
Sample run
playRoulette()
Pocket number or group: Red
Amount to bet: 10
Rolling! ... 2 Black
You lose!
Your balance is now 90
Pocket number or group: Black
Amount to bet: 25
Rolling! ... 12 Black
You win!
Your balance is now 115
Pocket number or group: 00
Amount to bet: 120
Not enough funds
Amount to bet: 115
Rolling! ... 9 Red
You lose!
Your balance is now 0
Game Over!

My program produces print statement infinity in a loop. Don't know how to fix it [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
So I'm trying to learn Python and I have written a program that is essentially designed to play a game with the user and a computer.
This game's mechanics are:
There are two players: the user and the computer, who alternate turns until one of them reaches 100 points or higher.
• The user is always the first player.
• If any player reaches 100 points or more at the end of their turn, the game ends immediately and the other player does not get another turn.
• One turn consists of the following: the player rolls a 6-sided die.
o If they roll a 1, they score 1 point and their turn is over. Even if a player has
accumulated points from previous rolls, if they roll a 1, their score for that turn will be 1 point and their turn is over.
o If they roll any other number, the roll score is added to the turn total.
o Then, they have the option to continue rolling or to hold. There is no restriction on how many times a player can roll in a turn.
• Holding: if a player holds, they score their current turn total and their turn ends. If,
for example, a player rolled a 3, 4, and 2, then decides to hold, they score 9 points.
• If the player is the user, they are given the option as to whether they would like to
continue rolling or hold after each time they roll the die and do not get a 1.
• If the player is the computer, they will always continue rolling until their turn total
reaches the value 10 or higher.
The problem with the code is it produces an infinite print statement when the code runs. I worked it down to the Boolean statement in the main function where I set is_user_turn = True. I have sorted through the code but there is something I am not seeing and need help fixing it.
Here is the code:
import random
def welcome():
print("Welcome to Jeopordy")
def print_current_player(is_user_turn):
if (is_user_turn == True):
print("It is now human's turn")
if (is_user_turn == False):
print("It is now computer's turn")
def roll_die():
roll = random(1,6)
return roll
def take_turn(is_user_turn,Computer_Hold):
turn_total = 0
if(is_user_turn == True):
while(is_user_turn == True):
roll = roll_die()
if(roll == 1):
return 1
turn_total = turn_total + roll
print("Your turn total is 1")
is_user_turn = False
else:
print("You rolled a ",roll)
turn_total = turn_total + roll
print("Your turn total is ",turn_total)
play = input("Do you want to roll gain (Y/N)?")
if(play == 'N' or play == 'n'):
is_user_turn = False
return turn_total
else:
is_user_turn == True
if(is_user_turn == False):
while(is_user_turn == False):
roll = roll_die()
while(turn_total <= Computer_Hold):
if(roll + turn_total <= Computer_Hold):
print("You rolled a ", roll)
turn_total = turn_total + roll
print("Your turn total is ",turn_total)
return turn_total
def report_points(userscore,computerscore):
print("computer: ",computerscore)
print("user: ",userscore)
def get_next_player(is_user_turn):
if(is_user_turn == True):
is_user_turn = False
return is_user_turn
else:
is_user_turn = True
return is_user_turn
def main():
Game_End_Points = 100
Computer_Hold = 10
is_user_turn = True
userscore = 0
computerscore = 0
welcome()
while(userscore <= Game_End_Points and computerscore <= Game_End_Points):
print_current_player(is_user_turn)
if(get_next_player(is_user_turn) == True):
userscore = userscore + take_turn(is_user_turn,Computer_Hold)
report_points(userscore,computerscore)
get_next_player(is_user_turn)
elif(get_next_player(is_user_turn) == False):
computerscore = computerscore + take_turn(is_user_turn,Computer_Hold)
report_points(userscore,computerscore)
get_next_player(is_user_turn)
main()
This part is the bug:
while(userscore <= Game_End_Points and computerscore <= Game_End_Points):
print_current_player(is_user_turn)
this executes this function infinitely:
def print_current_player(is_user_turn):
if (is_user_turn == True):
print("It is now human's turn")
if (is_user_turn == False):
print("It is now computer's turn")
since your function doesn't alter userscore or computerscore, it gets stuck there. That's my hint for now. If you need further help, just ask at comment.
Added Hint: "Indent"
also, just checked your whole code -- seems there are other bugs as well :)
I can't tell for sure but it looks like this might be causing the loop or is at least going to cause some problems for you:
if(play == 'N' or play == 'n'):
is_user_turn = False
return turn_total
else:
is_user_turn == True
In the else statement, you are checking that is_user_turn is True instead of assigning it a True value. Looks like it should be is_user_turn = True
The variable userscore will always be less than the Game_End_Points and so will be computer score and hence will loop infinitely, use some counter in the loop.
while(userscore <= Game_End_Points and computerscore <= Game_End_Points):
print_current_player(is_user_turn)
userscore=userscore+10 #something like this
computerscore+=10

Trying to get the number of tries to start at 1 and not 0

Whenever you run the game and start guessing it asks first what is guess #0? I'm trying to get it to display "what is guess #1?" but. at the same time keep the number of guesses equal to the number guessed (if that makes sense). Here's my code so far:
import random
def play_game(name, lower=1, upper=10):
secret = random.randint(lower, upper)
tries = 0
print("-----------------------------\n"
"Welcome, {}!\n"
"I am thinking of a number\n"
"between {} and {}.\n"
"Let's see how many times it\n"
"will take you to guess!\n"
"-----------------------------".format(name, lower, upper))
# Main loop
guessing_numbers = True
while guessing_numbers:
guess = input("What is guess #{}?\n".format(tries))
while not guess.isdigit():
print("[!] Sorry, that isn't a valid input.\n"
"[!] Please only enter numbers.\n")
guess = input("What is guess #{}?\n".format(tries))
guess = int(guess)
tries += 1
if guess < secret:
print("Too low. Try again!")
elif guess > secret:
print("Too high. Try again!")
else:
guessing_numbers = False
if tries == 1:
guess_form = "guess"
else:
guess_form = "guesses"
print("--------------------------\n"
"Congratulations, {}!\n"
"You got it in {} {}!\n"
"--------------------------\n".format(name,tries,guess_form))
if tries < 3:
# Randomly chooses from an item in the list
tries_3 = ["Awesome job!","Bravo!","You rock!"]
print (random.choice(tries_3))
# ---
elif tries < 5:
tries_5 = ["Hmmmmmpff...","Better luck next time.","Ohhh c'mon! You can do better than that."]
print (random.choice(tries_5))
elif tries < 7:
tries_7 = ["You better find something else to do..","You can do better!","Maybe next time..."]
print (random.choice(tries_7))
else:
tries_8 = ["You should be embarrassed!","My dog could do better. Smh...","Even I can do better.."]
print (random.choice(tries_8))
choice = input("Would you like to play again? Y/N?\n")
if "y" in choice.lower():
return True
else:
return False
def main():
name = input("What is your name?\n")
playing = True
while playing:
playing = play_game(name)
if __name__ == "__main__":
main()
I have the number of "tries" set to 0 at the beginning. However, if I set that to 1 then play the game and it only takes me 3 tries it will display that it took me 4 tries. so I'm not sure what to do. Still somewhat new to python so I would love some help
Anywhere that you have input("What is guess #{}?\n".format(tries)), use guess = input("What is guess #{}?\n".format(tries+1)). (adding +1 to tries in the expression, but not changing the variable itself)

Problems with Rock, Paper, Scissors Python Code

I'm working on a code with python, where we've been asked to create a game of Rock, Paper, Scissors using an external file of options (rock, paper, scissors) as opposed to having the code use any user input. However, for some reason, my code doesn't work. When someone inputs "yes", it prints "Let us play now," but that's it. Nothing else happens.
Why isn't the game completing when a user provides "yes" as input?
from random import randrange
def sample():
computer_input = randrange(1,3)
return computer_input
def main():
a = []
infile = open("input2.txt", "r")
for line in infile:
a.append(line)
computer_input = sample()
tied = 0 #games tied
user_won = 0 #games won by user
comp_won = 0 #games won by computer
user_input = ""
computer_input = ""
print("Rules of the game...")
print("Would you like to turn up with a game of rock, paper, or scissors? ;) Yes or no? -->")
answer = input()
if (answer == "yes"):
play = True
print("Let us now play.")
## elif(answer == "no" or "No"):
## play = False
## print("Sorry. Maybe we can play next time ;)")
## else:
## play = False
## print("Please try again!")
## main()
while True:
if(computer_input == "1"):
if(user_input == a[0]):
tied = tied + 1
print("Game is tied!")
elif(user_input == a[1]):
user_won = user_won + 1
print("You won! Paper covers Rock")
elif(user_input == a[2]):
comp_won = comp_won + 1
print("You lost! Rocks knocks out scissors")
## else:
## print("Try again!")
elif (computer_input == "2"):
if (user_input == a[0]):
comp_won = comp_won + 1
print("You lost! Paper covers Rock")
elif(user_input == a[1]):
tied = tied + 1
print("Game is tied!")
elif(user_input == a[2]):
user_won = user_won + 1
print("You won! Scissors cuts Paper")
## else:
## print("Try again!")
else :
if(user_input == a[0]):
user_won = user_won + 1
print("You won! Rock knocks out scissors")
elif(user_input == a[1]):
comp_won = comp_won + 1
print("You lost! Scissors cuts Paper")
elif(user_input == a[2]):
tied = tied + 1
print("Game is tied!")
## else:
## print("Try again!")
##
##print("Game over")
##print("Statistics")
##print("Games tied -->", tied)
##print("Game won by comp -->", comp_won)
##print("Game won by user -->", user_won)
##
main()
Notice that on line 5 below, you set computer_input to the result of sample():
def main():
a = []
infile = open("input2.txt", "r")
for line in infile:
a.append(line)
computer_input = sample()
But then a few lines later, you set it to "":
user_input = ""
computer_input = ""
Your while loop is checking against the value of computer_input, but it assumes it will be a number. It has no case to handle the empty string. I would recommend removing that line.
Also note that your while loop is checking the value of user_input, but you never seem to actually read input into that variable.
There are many, many problems with this code.
Every time you define or use a variable, you should have a clear idea of
why it is defined this way or exactly what this use of the variable is
going to accomplish.
You have a loop, which seems to indicate that you meant for more than
one round of the game to be played when you run the code once.
But there is only one place where the computer's choice is set
to a number 1, 2, or 3, and it occurs only once.
(Besides, as has already been pointed out, then you change the
computer's choice to "" without even reading the number once.)
You have no apparent way to get out of the loop within the logic of the code.
It is unclear what you think you are supposed to be reading from the
user's input file. You put the contents of the file in the array a line
by line, but then you only ever look at a[0], a[1], and a[2].
What were the first three lines of the file supposed to contain?
Why only three lines? What does it mean to ask whether
user_input == a[0]?
(I have a hunch that you were supposed to set the user input on each
round to a member of a, not compare user_input to a member of a.)
(Also notice that you set user_input = "" earlier, so unless you read
empty strings into the entries of a, expressions like
user_input == a[0] will always be false.)
What is the point of setting play = True? (Or even setting
play = False as in the commented-out code?) You never do anything that
would read the value of play.
What is the point of keeping count in the variables tied,
user_won, and computer_won? You never read those variables either,
except when you're setting new values of them.
It might help if you write some smaller functions with very clear
purpose, input and output. The sample() function is promising, but
everything else is in main().
For example, figuring out who won, given the computer's choice and
the player's choice, could be a function.
By writing such a function you would remove dozens of lines of code from
the loop in main(), replacing them with perhaps one line of code.
It's much, much easier to write well-designed loops when
the block of code inside the loop is short.

Categories

Resources