from random import random
# This function handles the number guessing and number formatting
def run_game():
# rand is declared by grabbing a number between 0 and 1, multiplying it by 100, and rounds to nearest integer
rand = round(random() * 100, 0)
print("Guess the number [0 - 100]")
guesses = 0
while True:
# Assigns the 'answer' variable by grabbing user input from console
answer = input()
# Checks if the input from the console is a number, and if not, asks the user to enter a valid number
if answer.isdigit():
n = int(answer)
if n > int(rand):
print("Number is less than " + str(n))
guesses = guesses + 1
elif n < int(rand):
print("Number is greater than " + str(n))
guesses = guesses + 1
else:
guesses = guesses + 1
print("It took you " + str(guesses) + " guesses to guess the right number!")
reply = play_again()
if reply is False:
break
else:
run_game()
else:
print("Please enter a number")
def play_again():
while True:
reply = input("Play again? (y/n)\n")
if reply.lower() == "y":
return True
elif reply.lower() == "n":
return False
else:
print("Enter 'y' or 'n'")
if __name__ == "__main__":
run_game()
So when I run this program, it runs fine. Once guessing the number, I can type y or n to play again. If I have only played once, it works fine. But if I select y, and play again, entering n after playing the second game does nothing
Your main issue is that you're using recursion to start a new game, but after the recursive call returns (assuming it does), you just keep on going in the original game.
There are a few ways you could fix that. The simplest would be to change the code that handles checking the user's choice to play again so that it always breaks:
if reply:
run_game()
break
A better approach would be to get rid of the recursion. There are a few ways you could do that. One simple idea is to simply reset the appropriate variables and keep right on going with your game loop when the user wants to play again:
reply = play_again()
if reply:
rand = round(random() * 100, 0)
print("Guess the number [0 - 100]")
guesses = 0
else:
break
Another way to avoid recursion would be to add another loop. Here's one way you could do it with a separate function:
def run_game():
rand = round(random() * 100, 0)
print("Guess the number [0 - 100]")
guesses = 0
while True:
answer = input()
if answer.isdigit():
n = int(answer)
if n > int(rand):
print("Number is less than " + str(n))
guesses = guesses + 1
elif n < int(rand):
print("Number is greater than " + str(n))
guesses = guesses + 1
else:
guesses = guesses + 1
print("It took you " + str(guesses) + " guesses to guess the right number!")
break # unconditionally break here!
def run_many_games():
again = True
while again:
run_game()
again = play_again()
One thing you may note that I've changed in all of the code above is how I test if the return value from play_again is True or False. There's no need for an extra comparison step when you have a bool value already. Just do if reply (or if not reply if you're testing for False). You can also do this in a while loop condition, as I do with again in my last code block.
Heres a good way to solve this problem. In your code you never actually exit the while loop because run game never exits, and there is no system variable returned to break it. Using sys.exit(0) also works, but its a bad habit to get into for these kinds of programs.
from random import random
# This function handles the number guessing and number formatting
def run_game():
# rand is declared by grabbing a number between 0 and 1, multiplying it by 100, and rounds to nearest integer
rand = round(random() * 100, 0)
print("Guess the number [0 - 100]")
guesses = 0
while True:
answer = input()
if type(answer) == int:
n = int(answer)
if n > int(rand):
print("Number is less than " + str(n))
guesses = guesses + 1
elif n < int(rand):
print("Number is greater than " + str(n))
guesses = guesses + 1
else:
guesses = guesses + 1
print("It took you " + str(guesses) + " guesses to guess the right number!")
break
reply = play_again()
if reply:
run_game()
else:
print 'Thank you for playing'
def play_again():
while True:
reply = raw_input("Play again? (y/n)\n")
if reply.lower() == "y":
return True
elif reply.lower() == "n":
return False
else:
print("Enter 'y' or 'n'")
if __name__ == "__main__":
run_game()
The reason this is happening is because run_game ends up calling itself recursively. Instead of restarting the game when the user chooses to play again it effectively creates a new instance of the game. Then when the user chooses to stop playing it returns back to the old session instead of exiting the program.
You can even prove this to yourself by remembering the solution before choosing to play again, and then choosing not to play again after the second session. You'll then be playing the previous session again and entering the solution you remembered or wrote down.
Now you can solve this problem by using sys.exit() instead of break to force the program to close, but that doesn't seem like good practice. If somebody chooses to play again too many times they can cause the program to run out of stack space and crash. Instead it's probably better to move that check out of run_game like this
if __name__ == "__main__":
while True:
run_game()
if not play_again():
break
And modify the else block in run_game to this
else:
guesses = guesses + 1
print("It took you " + str(guesses) + " guesses to guess the right number!")
break
There's no point in returning True or False according to the user input, you can work from there directly.
import sys
from random import random
# This function handles the number guessing and number formatting
def run_game():
# rand is declared by grabbing a number between 0 and 1, multiplying it by 100, and rounds to nearest integer
rand = round(random() * 100, 0)
print("Guess the number [0 - 100]")
guesses = 0
while True:
# Assigns the 'answer' variable by grabbing user input from console
answer = input()
# Checks if the input from the console is a number, and if not, asks the user to enter a valid number
if answer.isdigit():
n = int(answer)
if n > int(rand):
print("Number is less than " + str(n))
guesses = guesses + 1
elif n < int(rand):
print("Number is greater than " + str(n))
guesses = guesses + 1
else:
guesses = guesses + 1
print("It took you " + str(guesses) + " guesses to guess the right number!")
play_again()
else:
print("Please enter a number")
def play_again():
while True:
reply = input("Play again? (y/n)\n")
if reply.lower() == "y":
run_game()
elif reply.lower() == "n":
sys.exit(0)
else:
print("Enter 'y' or 'n'")
if __name__ == "__main__":
run_game()
This way the code is somewhat cleaner and fixes your problem. There's no point in passing "flags" around when you can do things directly.
Since your game is from 0 to 100 you should also verify if the user doesn't put a number that's bigger than 100, since lower than 0 doesn't pass the isdigit check.
Related
I am making a program that generates a random number and asks you to guess the number out of the range 1-100. Once you put in a number, it will generate a response based on the number. In this case, it is Too high, Too low, Correct, or Quit too soon if the input is 0, which ends the program(simplified, but basically the same thing).
It counts the number of attempts based on how many times you had to do the input function, and it uses a while loop to keep asking for the number until you get it correct. The problem that I am facing is that I have to make it break out of the while loop once the guess is either equal to the random number or 0. This normally isn't an issue, because you could use sys.exit() or some other function, but according to the instructions I can't use break, quit, exit, sys.exit, or continue. The problem is most of the solutions I've found for breaking the while loop implement break, sys.exit, or something similar and I can't use those. I used sys.exit() as a placeholder, though, so that it would run the rest of the code, but now I need to figure out a way to break the loop without using it. This is my code:
import random
import sys
def main():
global attempts
attempts = 0
guess(attempts)
keep_playing(attempts)
def guess(attempts):
number = random.randint(1,100)
guess = int(input("Enter a number between 1 and 100, or 0 to quit: "))
while guess != 0:
if guess != number:
if guess < number:
print("Too low, try again")
attempts += 1
guess = int(input("Enter a number between 1 and 100, or 0 to quit: "))
elif guess > number:
print("Too high, try again")
attempts += 1
guess = int(input("Enter a number between 1 and 100, or 0 to quit: "))
else:
print()
print("Congratulations! You guessed the right number!")
print("There were", attempts,"attempts")
print()
#Ask if they want to play again
sys.exit()#<---- using sys.exit as a placeholder currently
else:
print()
print("You quit too early")
print("The number was ",number,sep='')
#Ask if they want to play again
sys.exit()#<----- using sys.exit as a placeholder currently
def keep_playing(attempts):
keep_playing = 'y'
if keep_playing == 'y' or keep_playing == 'n':
if keep_playing == 'y':
guess(attempts)
keep_playing = input("Another game (y to continue)? ")
elif keep_playing == 'n':
print()
print("You quit too early")
print("Number of attempts", attempts)
main()
If anyone has any suggestions or solutions for how to fix this, please let me know.
Try to implement this solution to your code:
is_playing = True
while is_playing:
if guess == 0:
is_playing = False
your code...
else:
if guess == number:
is_playing = False
your code...
else:
your code...
Does not use any break etc. and It does breaks out of your loop as the loop will continue only while is_playing is True. This way you will break out of the loop when the guess is 0 (your simple exit way) or when the number is guessed correctly. Hope that helps.
I am not a fan of global variables but here it's your code with my solution implemented:
import random
def main() -> None:
attempts = 0
global is_playing
is_playing = True
while is_playing:
guess(attempts)
keep_playing()
def guess(attempts: int) -> None:
number = random.randint(1,100)
print(number)
is_guessing = True
while is_guessing:
attempts += 1
guess = int(input("Enter a number between 1 and 100, or 0 to quit: "))
if guess == 0:
is_guessing = False
print("\nYou quit too early.")
print("The number was ", number,sep='')
else:
if guess == number:
is_guessing = False
print("\nCongratulations! You guessed the right number!")
print("There were", attempts, "attempts")
else:
if guess < number:
print("Too low, try again.")
elif guess > number:
print("Too high, try again.")
def keep_playing() -> None:
keep_playing = input('Do you want to play again? Y/N ')
if keep_playing.lower() == 'n':
global is_playing
is_playing = False
main()
TIP:
instead
"There were", attempts, "attempts"
do: f'There were {attempts} attempts.'
So this is my random number guessing program I made. It asks the user to input two numbers as the bound, one high and one low, then the program will choose a number between those two. The user then has to try and guess the number chosen by the program. 1) How do I get it to ask the user if they would like to play again and upon inputting 'yes' the program starts over, and inputting 'no' the program ends? 2) How do I create an error trap that tells the user "Hey you didn't enter a number!" and ends the program?
def main(): # Main Module
print("Game Over.")
def introduction():
print("Let's play the 'COLD, COLD, HOT!' game.")
print("Here's how it works. You're going to choose two numbers: one small, one big. Once you do that, I'll choose a random number in between those two.")
print("The goal of this game is to guess the number I'm thinking of. If you guess right, then you're HOT ON THE MONEY. If you keep guessing wrong, than you're ICE COLD. Ready? Then let's play!")
small = int(input("Enter your smaller number: "))
large = int(input("Enter your bigger number: "))
print("\n")
return small, large
def game(answer):
c = int(input('Input the number of guesses you want: '))
counter = 1 # Set the value of the counter outside loop.
while counter <= c:
guess = int(input("Input your guess(number) and press the 'Enter' key: "))
if answer > guess:
print("Your guess is too small; you're ICE COLD!")
counter = counter + 1
elif answer < guess:
print("Your guess is too large; you're still ICE COLD!")
counter = counter + 1
elif answer == guess:
print("Your guess is just right; you're HOT ON THE MONEY!")
counter = c + 0.5
if (answer == guess) and (counter < c + 1):
print("You were burning hot this round!")
else:
print("Wow, you were frozen solid this time around.", "The number I \
was thinking of was: " , answer)
def Mystery_Number(a,b):
import random
Mystery_Number = random.randint(a,b) # Random integer from Python
return Mystery_Number # This function returns a random number
A,B = introduction()
number = Mystery_Number(A,B) # Calling Mystery_Number
game(number) # Number is the argument for the game function
main()
You'd first have to make game return something if they guess right:
def game(answer):
guess = int(input("Please put in your number, then press enter:\n"))
if answer > guess:
print("Too big")
return False
if answer < guess:
print("Too small")
return False
elif answer == guess:
print("Your guess is just right")
return True
Then, you'd update the 'main' function, so that it incorporates the new 'game' function:
def main():
c = int(input("How many guesses would you like?\n"))
for i in range(c):
answer = int(input("Your guess: "))
is_right = game(answer)
if is_right: break
if is_right: return True
else: return False
Then, you'd add a run_game function to run main more than once at a time:
def run_game():
introduction()
not_done = False
while not_done:
game()
again = input('If you would like to play again, please type any character')
not_done = bool(again)
Finally, for error catching, you'd do something like this:
try:
x = int(input())
except:
print('That was not a number')
import sys
sys.exit(0)
I don't know what's wrong with it.. I run it and I'm able to input a number but then it stops working. It says, "TypeError: play_game() missing 1 required positional argument: 'limit.' But I'm not sure what's missing there??
#!/usr/bin/env python3
import random
def display_title():
print("Guess the number!")
print()
def get_limit():
limit = int(input("Enter the upper limit for the range of numbers: "))
return limit
def play_game(limit):
number = random.randint(1, limit)
print("I'm thinking of a number from 1 to " + str(limit) + "\n")
while True:
guess = int(input("Your guess: "))
if guess < number:
print("Too low.")
count += 1
elif guess >= number:
print("Too high.")
count += 1
elif guess == number:
print("You guessed it in " + str(count) + " tries.\n")
return
def main():
display_title()
again = "y"
while again.lower() == "y":
limit = get_limit()
play_game()
again = input("Play again? (y/n): ")
print()
print("Bye!")
# if started as the main module, call the main function
if __name__ == "__main__":
main()
You have defined your play_game function to take limit as a parameter, but when you call this function in your main loop, you don't supply a value in the brackets of play_game().
You could either try adding that limit value that you've specified by calling it like
play_game(25)
Or, based on your code, since you're asking the user to provide a limit, call it like:
play_game(limit)
Or, if you want to be able to call play_game() without setting a limit, then change your play_game definition line to something like:
def play_game(limit=25):
Which will set a default value of 25 whenever that function is called without supplying the limit value.
Yes, play_game() needs the parameter limit. I've done a quick check on your code, and there is some additional problem
the count variable isn't initialized
you calculate the random number in every step
guess > number should be used instead of guess >= number
Here is the fixed code, it works for me. I hope it will be usefull:
import random
count = 0
number = -1
def display_title():
print("Guess the number!")
print()
def get_limit():
limit = int(input("Enter the upper limit for the range of numbers: "))
return limit
def play_game(limit):
global number, count
if number == -1:
number = random.randint(1, limit)
print("I'm thinking of a number from 1 to " + str(limit) + "\n")
while True:
guess = int(input("Your guess: "))
if guess < number:
print("Too low.")
count += 1
elif guess > number:
print("Too high.")
count += 1
elif guess == number:
print("You guessed it in " + str(count) + " tries.\n")
return
display_title()
again = "y"
while again.lower() == "y":
limit = get_limit()
play_game(limit)
again = input("Play again? (y/n): ")
print()
print("Bye!")
In your main you are calling playgame() without providing a limit as an argument.
Your main should look something like
def main():
display_title()
again = "y"
while again.lower() == "y":
limit = get_limit()
play_game(10)
again = input("Play again? (y/n): ")
print()
print("Bye!")
So my assignment(I have to use the while statement) was to make a number guessing game, part of that was to show the number of guesses the player had after they get the number right. I found something that I read is supposed to work but doesn't. here is my code.
#A text program that is a simple number guessing game.
import time
import random
#Setting up the A.I.
Number = random.randint(1,101)
def AI():
B = AI.counter =+ 1
Guess = int(input("Can you guess what number I'm Thinking of?: "))
while Guess > Number:
print("nope, to high.")
return AI()
while Guess < Number:
print("Sorry, thats to low. try again!")
return AI()
while Guess == Number:
print("Congragulations! you win! You guessed " + str(B) + " times")
time.sleep(60)
quit()
AI.counter = 0
AI()
Though when the player gets the number right it says that the player got it in one guess even when that's not the case.
You were pretty close #Simpson! Here's a slightly changed version that should give you what you're looking for :)
Let me know if you have any questions!
#A text program that is a simple number guessing game.
import random
#Setting up the A.I.
def AI():
counter = 1
number = random.randint(1,101)
guess = int(input("Can you guess what number I'm Thinking of?: "))
while guess != number:
if guess < number:
print("Sorry, thats to low. try again!")
else:
print("nope, too high")
counter += 1
guess = int(input("Can you guess what number I'm Thinking of?: "))
print("Congragulations! you win! You guessed " + str(counter) + " times")
time.sleep(60)
quit()
AI()
Without recursion - changed the whiles to ifs and added counter inside the method.
import time
import random
Number = random.randint(1,101)
def AI():
B = 1
Guess = int(input("Can you guess what number I'm Thinking of?: "))
while True:
if Guess > Number:
print("nope, to high.")
elif Guess < Number:
print("Sorry, thats to low. try again!")
if Guess == Number:
print("Congragulations! you win! You guessed " + str(B) + " times")
time.sleep(2)
break # leave the while true
# increment number
B += 1
Guess = int(input("Can you guess what number I'm Thinking of?: "))
AI()
Counting function calls is a perfect case for function decorators, a very useful feature of Python. You can define your decorator as:
def call_counted(funct):
def wrapped(*args, **kwargs):
wrapped.count += 1 # increase on each call
return funct(*args, **kwargs)
wrapped.count = 0 # keep the counter on the function itself
return wrapped
And then you can use it to decorate a function you wish to count calls to without dealing with the counter itself in your process flow:
import time
import random
secret_number = random.randint(1, 101)
#call_counted # decorate your AI function with the aforementioned call_counted
def AI():
current_guess = int(input("Can you guess what number I'm thinking of?: "))
while current_guess > secret_number:
print("Nope, too high. Try again!")
return AI()
while current_guess < secret_number:
print("Sorry, that's too low. Try again!")
return AI()
while current_guess == secret_number:
print("Congratulations! You win! You guessed {} times.".format(AI.count))
time.sleep(60)
quit()
AI()
I restyled your code a bit, but it's essentially the same.
I'd avoid recursion, tho, because this can be written much simpler and without the need to count function calls:
import time
import random
secret_number = random.randint(1, 101)
def AI():
counter = 0
while True:
counter += 1
current_guess = int(input("Can you guess what number I'm thinking of?: "))
if current_guess > secret_number:
print("Nope, too high. Try again!")
elif current_guess < secret_number:
print("Sorry, that's too low. Try again!")
else:
break
print("Congratulations! You win! You guessed {} times.".format(counter))
time.sleep(60)
quit()
AI()
You could do it generically with a function decorator that addes a call counter to any function to which it is applied:
(Note I also modified your code so it follows the PEP 8 - Style Guide for Python Code more closely.)
""" A text program that is a simple number guessing game. """
import functools
import time
import random
def count_calls(f):
""" Function decorator that adds a call count attribute to it and counts
the number of times it's called.
"""
f.call_count = 0
#functools.wraps(f)
def decorated(*args, **kwargs):
decorated.call_count += 1
return f(*args, **kwargs)
return decorated
# Setting up the A.I.
number = random.randint(1, 101)
# print('The number is:', number) # For testing.
#count_calls
def AI():
guess = int(input("Can you guess what number I'm thinking of?: "))
while guess > number:
print("Nope, too high.")
return AI()
while guess < number:
print("Sorry, that's too low. Try again!")
return AI()
while guess == number:
print("Congragulations! You win! You guessed " + str(AI.call_count) + " times")
time.sleep(10)
quit()
AI()
Use default arguments:
def AI(B=1):
Guess = int(input("Can you guess what number I'm Thinking of?: "))
while Guess > Number:
print("nope, to high.")
return AI(B + 1)
while Guess < Number:
print("Sorry, thats to low. try again!")
return AI(B + 1)
while Guess == Number:
print("Congragulations! you win! You guessed " + str(B) + " times")
time.sleep(60)
return
And then call the function:
AI()
Also, you should really be using ifs instead of whiles here since the loops are run exactly once, but whiles also work, so that's fine. Also, recursion might eat up your RAM, which just wastes resources, provided that you could've implemented the same thing as a loop, but your approach works, so that's fine too.
import random
control = True
main = True
count = 0
user = input("Would you like to play Guess The Number?")
if (user == "yes"):
while (control == True):
randgen = random.randrange(0, 100)
print("Guess a random number")
while main == True:
number = int(input())
if (number == randgen):
print("Great Job you guessed the correct number")
print("You have tried ", count, "time(s)")
main = False
control = False
if (number < randgen):
count += 1
print("Your number is smaller than the random number")
print("You are at ", count, "trie(s)")
main = True
if (number > randgen):
count += 1
print("Your number is larger than the random number")
print("You are at ", count, "trie(s)")
main = True
again = int(input("Would you like to play again?1 for yes and 2 for no."))
if (again == 1):
control = True
user = ("yes")
if (again == 2):
control = False
print ("Ok bye bye")
##user ("no")
if (user == "no"):
print ("OK then Bye")
This Code works except for the part that when I want to play again it does not work. I have a coding background in java that's why I know some code but I made the guess the number game in java and I cannot figure out whats wrong with my python version(posted above).
Please make these changes:
if (again == 1):
control = True
main=True
user = ("yes")