How to validate user input properly?

Question: I want to make sure that when the user inputs, for example, a 6 into the choice prompting for one of five choices that the program will ask them to enter a valid value and then continue with their new choice. However, when I finally do enter a valid choice after entering an invalid one, the code just stops. How can I get it to take their new choice?

Also, when I enter 1 as the value in the Ashe part where you talk to him, it replies with the second option because of the “else” statement. Why won’t it take the 1?



#create a function to print the instructions to shrink the main area
def printInstructions():
  print(" ")
  print("You are playing as Noel Levine. Your childhood friend Claire Elford has the witch's heart within her, though unknowingly. The heart can grant any one wish for a person, but to get it, that person would have to kill her.")
  print(" ")
  print("Trapped in a haunted mansion with 3 others and Claire for five days, you fear for her safety. Thankfully nobody knows she has the heart except you, but if you make the wrong choices, anyone could kill her. Your job is to prevent that from happening, even if Claire doesn't remember who you are. \n\n To make choices, enter only the number that corresponds to that choice.")

#function to make sure the user input is either 1 or 2 so that they can make a choice between two options
def validateChoice2(x):
  while x != "1" and x != "2":
    x = input("\nThat's not a valid choice! Please input the number of the choice you wish to make: ")
  return x

#function to make sure the user input is either 1, 2, 3, 4, or 5 so that they can make a choice between five options
def validateChoice5(x):
  while x != "1" and x != "2" and x != "3" and x != "4" and x != "5":
    x = (input("\nThat's not a valid choice! Please input the number of the choice you wish to make: "))
  return x
#lists for choices the player has made and for the endings
choicesList = []

#game start
print("-----WITCH'S HEART SIMULATOR-----")
print(" ")
#so the program doesn't keep running ahead of the user
input("Type anything to continue. ")
print(" ")

#context for the game and character intros
print("DAY 1 - INTRO. \nGathered in the dining room, the five of you trapped in the mansion make your introductions. The man with the teal braid and green outfit introduces himself as Ashe Bradley, a witch researcher. The man named Wilardo Adler has dark blue hair with a red streak, appearing cold and mysterious. The man with short purple hair calls himself Sirius Gibson, supposedly the lord of the mansion. You already know each other, but everyone else doesn't know that yet. Claire Elford, the one who you're here to save, sports a light blue bob and an enthusiastic smile. And of course, you're Noel Levine, with blond hair and dark blue clothes.")
print(" ")

#first choice, validate using function and the append to the list of choices
choice = input("After the introduction, everyone decides to split ways. Who would you like to spend the day with?\n \nCHOICE: 1. ASHE, 2. WILARDO, 3. SIRIUS, 4. CLAIRE, 5. NOBODY. ")

#check what choice the user has made by seeing what number is at index 0 in the choices list
#if they chose ashe
if choicesList[0] == "1":
  print("\n\"Huuuh? Hey Noel! What do you need?\" Ashe is curious to see you follow him.")
  #another choice to be validated
  choice = input("\nWhat would you like to say? \n \nCHOICE: 1. \"JUST WANTED TO TALK.\" or 2. \"DO YOU KNOW ABOUT THE WITCH'S HEART?\" ")

  #nested if statement for choice after a choice
  if choice == "1":
    print("\nYou earn a smile from Ashe. \"Oh, no problem then! Well, I guess I can tell you a little more about me. Like I said, I'm a witch researcher. I came here to find some information on the evil witch Dorothy... they say this might be her mansion! That's why I don't trust Sirius entirely, because how could it be his?\" \n \n\"Anyway, have you ever heard the legend of the witch's heart? Super cool, right? Turns out it's not just a fairytale... and it may be hiding in this very mansion! Ooh, it would help my research so much to find it...\" \n \nYou learned a little more about Ashe!")
    print("\nAshe looks a little surprised at the question, but he nods excitedly. \"Yeah, of course! It's only the coolest thing ever! Turns out it's not just a fairytale... and it may be hiding in this very mansion! Ooh, it would help my research so much to find it... but, maybe I never will.\" \n \nYou learned a little more about Ashe!")

#if they chose wilardo
if choicesList[0] == "2":
  print("\nWilardo gives you a strange look, but he does not make you leave. He doesn't seem to be the type for conversation, so you sit quietly with him in his designated room for the entire day. Wow, how boring!")

#if they chose sirius
if choicesList[0] == "3":
  print("\nSirius is not amused to see you. \"I'm busy. Go bother someone else,\" he snapped, heading into his room and shutting the door on you. Hm.. well, it appears you'll be spending the day alone. \n \nYou explored the mansion by yourself, encountering low-level demons along the way. Nothing you can't fight off. Unfortunately, there doesn't seem to be anything helpful around here.")

#if they chose claire
if choicesList[0] == "4":
  print("\n\"Noel? Hi! You wanna explore together? I thought maybe we could look around to find something useful, and then cook dinner for everyone later!\"")
  choice = input(("\nWhat would you like to say? \n \nCHOICE: 1. \"SURE!\" or 2. \"SORRY, I'M GOING TO BED.\" "))

  #choice within a choice
  if choice == "1":
    print("\n\"Cool! C'mon, I wanted to look at these demons...\" You and Claire explore together, taking note of the low-level demons you worked together to fend off. Inspecting the front door, you noticed there was some kind of magic circle or ward on it, but you couldn't be sure what it did. Maybe that was what trapped you here, who knows. \n \nAfter a long day of exploring the massive mansion, the two of you got to work on preparing dinner for the others. \"Salisbury steak?\" Claire suggested, so you nodded and helped her make it. With lots of laughter and mishaps, it was a fun day, and the food looked delicious. \n\nYou had fun with Claire!")
    print("\nYou left Claire to explore and make dinner by herself. Taken by surprise, a demon in the mansion attacked her and killed her.\n")
    #game ends here

#if they chose nobody
if choicesList[0] == "5":
  print("\nYou decide to spend the day alone in your room, falling asleep until dinner. Talk about a waste!")

I prefer making a function to get input from the user and then just calling that function. Something like:

def get_input(prompt, options):
	while True:
		for option in options:
			print(f"{options.index(option)} {option}")

		user_input = input("=> ")

			user_input = int(user_input)

			if options[user_input]:
				return user_input

		print("Invalid Input")

i = get_input("Are You a: ", ["Lion", "Tiger", "Wolf", "Platypus"])

if i == 3:
	print("You are a cool person")

	print("You are a 'meh' person")
1 Like

You don’t need multiple functions, and having multiple functions makes it more difficult as you need to use global variables. Here’s what I would do for a question thing:

clear = lambda: print("\033c", end="", flush=True) # I got this from
def main(): # Always use a main function as it helps with
#object-oriented programming
  question = 'Choose wisely:\n1) Choice\n2) Choice\n3) Choice\n' 
  # Since we will use this more than once, it's better as a variable
  answer = input(question) # Ask question the first time
  while True: # This runs until you tell it not to
    if str(answer) in ('1', 'one'): # If option 1
      break # Break while loop
    elif str(answer) in ('2', 'two'):
    elif str(answer) in ('3', 'three'):
    else: # If not a valid answer, repeat question.
      clear() # Keeps the console clean. This is optional.
      answer = input(question)
  print(f'Since your answer was {answer}, you win!')

This is a little more advanced than mine, and I think it’s possibly better. Do you mind if I modify this and add it to my Python library? I think I would add a comment saying something like "modified from @InvisibleOne’s post at link.

Go ahead and do what you like with it :slight_smile:

1 Like

Thank you! I’m always looking for useful stuff like this!

1 Like
choice = input("[1] Test_1\n[2] Test_2\n[3] Test_3\n-> ")
if choice == "1":
elif choice == "2":
elif choice == "3":
elif choice not in ("1", "2", "3"):
   print(f"{choice} is invalid!")
My adaptation of InvisibleOne's answer (which I have already added to my library ). I copied it verbatim from the code (so it has comments too).
# User Input Error Catcher #
# Adapted from @InvisibleOne's post here:
def getInput(prompt, options, inputLine='=> ', error='Invalid Input', clear='no'):
# prompt: What question the user is asked.
# options: The options available to the user (must be in the form of a list)
# inputLine: The text displayed on the line that the user types in their input. If you want it to be blank, set it to '' or "".
# error: The message displayed when the user's input is invalid.
  while True: # This runs until it is ended
    print(prompt) # Display the prompt
    for option in options: # Goes through the whole list of options
      print(f"{options.index(option)+1} {option}") # Displays the option number and text
    userInput = input(inputLine) # Gets user input, dipslaying the text from "inputLine"
    try: # This stops the code from crashing when it gets errors
      userInput = int(userInput) # Convert user's input into a number
      if options[userInput-1]: # This returns the value of the number the user inputted as their answer. The text is not actually used and Python just uses the numbers
        return userInput
    except: # If anything went awry (such as the user putting in text)
      if clear in ('yes', 'y', 'clear', 'clear()'): # User must set it to clear manually from the function options
        clear() # Clear screen
      print() # Displays blank line
      pass # Keep going
    print(error) # Display error message

What this does is counts starting at 1 (which makes sense to people), but subtracts one from the user’s input (so that it makes sense to Python). I think I made some other changes too.

To use the clear command, you will need to add this before the userInput function.
# Thanks to @bigminiboss on for this clear command.
# To use, type "clear()"
clear = lambda: print("\033c", end="", flush=True)

Im 97% sure there is a built-in Python function for this. :skull:

EDIT: confused myself ignore this. :sob: