I am trying to create a number guessing game in Python for a school project. I have made a basic game that will work fairly well, but I want to add in some exception handling in case the user enters something incorrectly. For example, this is a section of my code:
def Normal_Guess():
number = round(random.uniform(0.0, 100.0),2)
guess = ""
while guess != number:
try:
guess = float(input("Please guess a number between 0 and 100: "))
except ValueError or TypeError:
print ("That isn't even a number!")
if guess < number and guess >= 0:
print ("You need to guess higher!")
elif guess > number and guess <= 100:
print ("You need to guess lower!")
elif guess == number:
print("Congratulations! You guessed the number!")
elif guess < 0 or guess > 100:
print ("The number you guessed is not between 0 and 100")
else:
print("That isn't even a number!")
New_Game()
This works fine when the user enters a float or integer value as "guess", and the Try-Except clause I have seems to catch if the user enters anything but a number at first, but the program seems to also carry on to the "if" statements. I am getting a TypeError saying that "'<' not supported between instances of 'str' and 'float'".
I have tried encompassing the entire loop in a Try-Except clause, and that doesn't work. I have no clue what I am doing wrong. Any help is much appreciated.
First off, the way you are catching the exception is invalid. The value of the expression ValueError or TypeError is always just going to be ValueError because that is how short-circuiting works with two non-False arguments. To get both types of errors to trigger the block, use a tuple, like (ValueError, TypeError).
The problem is that even if an exception is caught in your code, it will continue on to the if block. You have four simple options to avoid this:
Use a continue statement in the except block to tell the loop to move on without processing the following if structure:
try:
guess = float(input("Please guess a number between 0 and 100: "))
except (ValueError, TypeError):
print ("That isn't even a number!")
continue
This is probably the cleanest and easiest of the four options.
Do not use an except block to respond to the error. Instead, rely on the fact that the value of guess is still "". For this to work, you will have to pre-initialize guess with every iteration of the loop instead of once outside the loop:
while guess != number:
guess = ""
try:
guess = float(input("Please guess a number between 0 and 100: "))
except (ValueError, TypeError):
pass
if guess == "":
print ("That isn't even a number!")
elif guess < number and guess >= 0:
...
Personally, I am not a fan of this approach because it requires an initialization in every loop. This is not bad, just not as clean as option #1.
A variation on this option is to check directly if guess is an instance of str. You can then initialize it to the user input, making the conversion operation cleaner:
while guess != number:
guess = input("Please guess a number between 0 and 100: ")
try:
guess = float(guess)
except (ValueError, TypeError):
pass
if isinstance(guess, str):
print ("That isn't even a number!")
elif guess < number and guess >= 0:
...
Use the else clause that is one of the possible elements of a try block. This clause gets executed only if no exception occurred:
try:
guess = float(input("Please guess a number between 0 and 100: "))
except (ValueError, TypeError):
print ("That isn't even a number!")
else:
if guess < number and guess >= 0:
...
While this option creates an added layer of indentation, it is a possibility worth keeping in mind for those cases where a plain continue won't work. This happens sometimes when you need to do additional processing for both error and non-error cases, before you branch.
Put the entire if block into the try block. This way it will only be executed if there is no error. This is my least favorite option because I like my try blocks to be as trimmed-down as possible to avoid catching exceptions I did not intend to. In Python, try is relatively less of a performance-killer than in a language like Java, so for your simple case, this is still an option:
try:
guess = float(input("Please guess a number between 0 and 100: "))
if guess < number and guess >= 0:
...
except (ValueError, TypeError):
print ("That isn't even a number!")
Try using an else statement.
Your except catch print, but let script continue running. It will continue to all of if statements even when the catch is hit. What you want to do is skip the main logic of your function when the except is hit. Use the ELSE clause of the try-catch-else-finally block.
import random
def Normal_Guess():
number = round(random.uniform(0.0, 100.0),2)
guess = ""
while guess != number:
try:
guess = float(input("Please guess a number between 0 and 100: "))
except (ValueError, TypeError):
print ("That isn't even a number!")
else:
if guess < number and guess >= 0:
print ("You need to guess higher!")
elif guess > number and guess <= 100:
print ("You need to guess lower!")
elif guess == number:
print("Congratulations! You guessed the number!")
elif guess < 0 or guess > 100:
print ("The number you guessed is not between 0 and 100")
else:
print("That isn't even a number!")
Normal_Guess()
Related
Good afternoon everyone.
First of all I am a total beginer in coding and Python itself. To be honest I am not even sure is that a proper place to ask such a 'newbie' question.
But to the point.
During the online course I was asked to write a simple program to guess numbers.
I did that and the code works quite ok: https://pastebin.com/XwZ2qcab
Although I wanted to improve the code to allow user to type a non int variable and not crash.
I have used ' if type(userNumber) != int:' in the upgraded version of the code: https://pastebin.com/JQarjjSw but it does not work.
The issue I have is (I think) here:
for i in range(1, 7):
userNumber = input('Take a guess')
if type(userNumber) != int: #This line is my main issue, if I delete it code works like a charm.
break
elif int(userNumber) > int(number):
print('No! Your number is too high. Try again')
elif int(userNumber) < int(number):
print('No! Your number is too low. Try again')
else:
break
I have no idea why the line if type(userNumber) != int: break is not executed and pyCharm goes directly to: elif int(userNumber) > int(number): and crashes.
Funny thing is that on pythontutor.com code works as intended. Checks for userNumber and if it is not an int breakes the IF loop.
Hope that is somehow clear.
Extending on ex4's answer, you should use .isdigit() to check if the input is numeric, however where this is a game I assume you don't just want the game to end using a break when the player enters a bad input and you'd rather have them guess again.
Try the following segment. It takes inputs until the player enters an input which isn't a digit, where it gets the player to enter another input until it is a digit.
for i in range(1, 7):
userNumber = input('Take a guess')
while not userNumber.isdigit():
userNumber = input('What you have entered is not a number, please guess again')
if int(userNumber) > int(number):
print('No! Your number is too high. Try again')
elif int(userNumber) < int(number):
print('No! Your number is too low. Try again')
else:
break
You get your userNumber variable from input function. And it always returns a string. So you have a few options you can use to check if user gives a digits.
First option is to use str.isdigit() method
userNumber = input('Take a guess')
if not userNunber.isdigit():
# user entered something else than digits
break
Another option could be using try-except method:
userNumber = input('Take a guess')
try:
# try to convert user input to integer
userNumber = int(userNumber)
except ValueError:
# We failed so user entered invalid value
break
In this case, you need to use a try… except… statement:
try:
int(“12ab”)
except ValueError:
print(“Not a number”)
Your full code would be:
for i in range(1, 7):
userNumber = input('Take a guess')
try:
num = int(userNumber)
except ValueError:
print(“Not a number”)
break
if num > int(number):
print('No! Your number is too high. Try again')
elif num < int(number):
print('No! Your number is too low. Try again')
else:
break
You can read more about it here.
In this example I was wondering what I could use instead of BREAK
while (True):
try:
guess = ***********
break
except ValueError:
print(***)
You could initialize guess to an invalid value and test for that.
guess = None
while guess is None:
try:
guess = int(input('Please enter your guess for the roll: '))
except ValueError:
print('Only enter a number please')
When there's no error, guess will be set to an integer, which is not None, so the loop will end.
But I prefer your original code, it's clearer.
Please provide a more information.
loop = True
while (loop):
try:
guess = int(input('Please enter your guess for the roll: '))
loop =False
#break
except ValueError:
print('Only enter a number please')
Another approach using a some lesser known but useful python control flows include using a for/else and try/except/else, it still requires a break but i think it's still a neat alternative
MAX_GUESS = 3
for _ in range(MAX_GUESS):
try:
guess = int(input('Input guess: '))
except ValueError:
print("Try again!")
else:
print("Success!")
break
else:
guess = None
print("Max guesses attempted")
The else block tied to the for/else loop is only entered if a break was NOT encountered during the loop, similarly the else of the try/except/else is only entered if an exception was NOT raised during the try
Can someone please help me understand the following issue...
I'm having problems executing my try/except block in my simple number guessing game. The function containing my error handling works fine if I remove the integer portion of the initial input. But if I do this, the rest of the game doesn't work, because from my understanding Python3 takes input and stores it as a string. So how can I get my exception to execute? Any help is much appreciated.
Thanks,
# number game
import random
print ("Welcome to the guessing number game!\n\n")
winning_number= random.randrange(1, 11)
guess = int(input("Can you guess the lucky number.\nHint it's between 1 and 10!\n"))
def is_number(guess):
try:
int(guess)
except ValueError:
print ('You need to type a number\n')
guess = int((input("Please input a number\n")))
game(guess)
def compare(guess):
if guess > winning_number:
print ("Wrong, you're guess is too high.\n")
guess = int(input("Guess againn\n"))
game(guess)
else:
print ("Wrong, you're guess is too low.\n")
guess = int(input("Guess again\n"))
game(guess)
def game(guess):
is_number(guess)
if guess == winning_number:
print ("You win!, You guessed the number!")
else:
compare(guess)
game(guess)
Here is what I get when I input anything other than an integer...
Welcome to the guessing number game!
Can you guess the lucky number.
Hint it's between 1 and 10!
f
Traceback (most recent call last):
File "C:/Users/mickyj209/PycharmProjects/Practice/NumberGuess.py", line 10, in
guess = int(input("Can you guess the lucky number.\nHint it's between 1 and 10!\n"))
ValueError: invalid literal for int() with base 10: 'f'
Process finished with exit code 1
You forgot to save the value that time (guess = int(guess)), you're not returning anything there, and you're just having the program run the function but not making a decision based on the result. You also have an int(input(... in the exception handling, which could itself generate an exception which won't be caught. The initial guess isn't in a try block, either.
You could refactor this program:
def game():
print ("Welcome to the guessing number game!\n\n")
winning_number = random.randrange(1, 11)
print("Can you guess the lucky number?\nHint: it's between 1 and 10!\n")
while 1:
try:
guess = int(input("Please input a number\n"))
except ValueError:
continue
if guess > winning_number:
print('Wrong - your guess is too high.')
elif guess < winning_number:
print('Wrong - your guess is too low.')
else:
print('You win! You guessed the number!')
break
I am learning python and was writing this game, where the program picks a random number and asks the user to guess the number. In this case, a user can enter an empty string or an alphabet by mistake. So, i felt the need to check the type of the user input before doing the comparison as shown below. Also, this lead me to the following stackoverflow entry
Checking whether a variable is an integer or not
My question is why checking of types is considered a bad practice and how can i accomplish my task by not checking the type?
import random
num = random.randint(1,10)
while True:
guess = input('Guess a number between 1 and 10: ')
if(bool(guess)):
try:
guess = int(guess)
except:
print("Please enter a numeric value")
continue
else:
print("you have to enter some number")
continue
if guess == num:
print("you guessed it right")
break
elif guess < num:
print("Try higher")
elif guess > num:
print("Try lower")
As the comments have stated, at no point do you check the type. What you do is validate and convert the input, which is appropriate for this program (and indeed, should be used in any program that accepts user input).
Try this instead:
import random
num = random.randint(1, 10)
while True:
try:
guess = int(input('Guess a number between 1 and 10: '))
if guess == num:
print('You have guessed the correct number')
break
if guess < num:
print('Try higher.')
else:
print('Try lower.')
except ValueError:
print('Please enter a number.')
The idea is that simply converting the input and handling the error leads to much cleaner code. In Python circles, checking the type via isinstance is known as Look Before You Leap which is discouraged. Just attempt the operation in question and handle the failure case (usually by exception handling). This is termed Easier to Ask Forgiveness than Permission.
I am making a simple 'guess a number between one and ten' game. I have used some basic error handling and am printing the number generated by the random module for testing purposes.
However I would like to know if there is a less verbose way to write this.
This is the code:
import random
while True:
"""Variable declaration"""
number_of_attempts = 1
number = random.randrange (1,11)
print (number)
print("Time to play a guessing game! Muhahaha...")
"""Error handling and main game code/while loop"""
while True:
try:
guess = int(input("Guess a number between one and ten."))
except ValueError:
print("Input a whole number between one and ten silly!")
continue
if guess >= 1 and guess <= 10:
pass
else:
print("Input a number between one and ten silly!")
continue
if guess == number:
print("You were successful and it took you", number_of_attempts, "attempts!!!")
break
else:
print("Try again!")
number_of_attempts = number_of_attempts +1
"""Game Exit/Restart"""
play_again = input("Would you like to play again, y/n?")
if "y" in play_again or "yes" in play_again:
continue
else:
break
Thanks,
Ben
if guess >= 1 and guess <= 10:
Can be written as:
if 1 <= guess <= 10:
Also, your first conditional can simply be written as:
if not 1 <= guess <= 10:
print("Input a number between one and ten silly!")
continue
But this can also be put inside the try bit, saving you from writing continue twice:
try:
guess = int(input("Guess a number between one and ten."))
if not 1 <= guess <= 10:
print("Input a number between one and ten silly!")
continue
except ValueError:
print("Input a whole number between one and ten silly!")
continue
Finally your last conditional can simply be:
if play_again not in ('y', 'yes'):
break
The continue isn't needed.
You may also want to wrap this all up into a function as well, to get rid of those infinite while loops and to prevent you from using continue and break so much.
Why not put the actual conditions on the while loops so you don't have to hunt for breaks to understand the loops? It would make your code clearer and smaller.
if guess == number:
print("You were successful and it took you", number_of_attempts, "attempts!!!")
break
For instance if you put guess == number as the while loop conditional then the print would be the first thing after the loop. Initialize guess to -1 so it always works the first time. The play again if statement could also disappear into the loop conditional as well.