KeyError when user input is misspelled - python

I have to program a text based game where conditions must be met before the game can end. As long as the user input is spelled correctly the game can be completed. However is there is a spelling error I get a KeyError: 'Whatever the misspelled word is'
I can't figure out how to resolve this issue. I have tried to check if user_input in rooms, I've tried to use try:/except:, I just can't figure it out. Would appreciate if someone could steer me in the right direction!
def main():
current_room = 'Mid Deck'
user_input = None
while user_input != 'Exit': #Check to see if user wants to exit game
print('You are in', current_room + '.' ) #Print list of possible user actions
options = rooms.get(current_room)
for i in options:
print(i, 'is', options[i])
user_input = input('What do you want to do?:').capitalize() #Get user input
if user_input == 'Exit':
print('Sorry you lost!')
elif user_input == 'Checklist': #Command to check which consoles have been activated
print('\n'.join(checklist))
elif user_input == 'Activate': #Command to activate consoles and update dictionary and list to reflect user input
if current_room == 'Bridge':
if win_condition < 7:
print('If you activate the console now')
print('the ships systems will short circuit')
print('and you will never escape the gravity well.')
print('Do you still want to activate? Yes or No?')
user_input = input().capitalize()
if user_input == 'Yes':
print('You have lost the game!')
else:
print('You have left the Bridge.')
current_room = 'Navigation'
else:
print('Congratulations you have escaped the stars gravity well!')
print('Thanks for playing and safe journey home!')
else:
checklist.append(current_room + ' is online.')
rooms[current_room]['Console'] = 'Online'
else:
current_room = rooms[current_room][user_input]

The KeyError is probably raised when the user input a not defined key in:
current_room = rooms[current_room][user_input]
To handle this issue you have to define which input is valid.
current_room_keys = ['Navigator', ...] #room key that valid
Some pseudo-code:
while user_input != 'Exit': #Check to see if user wants to exit game
user_input = input('What do you want to do?:').capitalize() #Get user input
if user_input == 'Exit':
elif user_input == 'Checklist': #Command to check which consoles have been activated
elif user_input == 'Activate': #Command to activate consoles and update dictionary and list to reflect user input
elif user_input in current_room_keys:
current_room = rooms[current_room][user_input]
else:
print('Please input a valid key')
continue

Related

How to break multiple loops in an if-statement within an if-statement in Python 3

How do I make a loop in an if-statement within an if-statement? I'm busy with How to learn Python 3 the hard way, and so far I know I can do the following:
while True:
print("choose 1st branch")
choice = input()
if choice == '1':
print('1, now choose second branch')
while True:
choice = input("")
if choice == "2":
print("2")
while True:
choice = input("")
if choice == "3":
print('3')#
else: #needs to ask for input for choice 3 again
print("try again")
else:print("try again")#needs to ask for input for choice 2 again
ive edited a simpler code example of what im trying to accomplish
Instead of creating a loop everywhere you want to check if the user input is a valid choice, you can extract that "checking if user input is within a valid choices" into a function. Said function will be something like
def get_user_choice(prompt, choices=None):
while True:
choice = input(prompt)
if choices is None:
# Return the entered choice without checking if it is
# valid or not.
return choice
if choice in choices:
return choice
print("unknown choice, try again")
With this new function, we check the validity of the choices first, then after we received the correct input, we then process with the logic for each of the choices.
occu = "ranger"
prompt = "-->"
def get_user_choice(prompt, choices=None):
while True:
choice = input(prompt)
if choices is None:
# Return the entered choice without checking if it is
# valid or not.
return choice
if choice in choices:
return choice
print("unknown choice, try again")
def room1():
print("you walk into an bare room")
door = False
gemstone = False
hole = False
monster = False
rat = False
trap = False
occu = "ranger"
while True:
print("you see a door infront of you")
print("do you go left, right or forward?")
choice = get_user_choice(prompt, ("left", "right", "forward"))
if choice == "left" and hole == False:
print("\nDo you \ndodge \nor \nattack?")
choice = get_user_choice(prompt, ("dodge", "attack"))
if choice == "dodge" and occu == "ranger":
trap = True
rat = True
print("\nhole \nroom")
choice = get_user_choice(prompt, ("hole", "room"))
if choice == "hole" and rat == True:
print("you walk up to the hole, you see a faint glitter")
print("do you reach your hand in?")
print("\nyes \nno")
choice = get_user_choice(prompt, ("yes", "no"))
if choice == "yes":
print("you reach into the whole and pull out a gemstone")
print("you put the gemstone in your inventory")
print("and go back to the room\n")
hole = True
gemstone = True
choice = True
elif choice == "no":
print(" you go back to the centre of the room")
Notice that other input also get modified to use this function to check if the choice user selected is valid or not.
The problem is that you are reusing the variable choice, and assigning it to be a boolean value and later on be the input. Try using another variable as well for either the boolean or the input, i.e. proceed.
proceed = False # CREATE VARIABLE PROCEED
while proceed == False: # LOOP WHILE PROCEED IS FALSE
print("do you reach your hand in?")
print("\nyes \nno")
choice = input(prompt)
if choice == "yes":
print("you reach into the whole and pull out a gemstone")
print("you put the gemstone in your inventory")
print("and go back to the room\n")
hole = True
gemstone = True
proceed = True # CHANGE PROCEED, NOT CHOICE
elif choice == "no":
print("You go back to the center of the room")
# Perhaps assign proceed to be True here as well?
else:
print("unknown choice, try again")
occu = 'ranger'
prompt = "-->"
def room1():
print("you walk into an bare room"
door = False
gemstone = False
hole = False
monster = False
rat = False
trap = False
occu = 'ranger'
while True:
print("you see a door infront of you")
print("do you go left, right or foward?")
if input(prompt) == 'left' and hole == False:
print('\nDo you \ndodge \nor \nattack?')
if input(prompt) == 'dodge' and occu == 'ranger':
trap = True
rat = True
print("\nhole \nroom")
if input(prompt) == 'hole' and rat == True:
print("you walk up to the hole, you see a faint glitter")
while True:
print("do you reach your hand in?")
print("\nyes \nno")
choice = input(prompt)
if choice not in ['yes', 'no']:
print("unknown choice, try again")
continue # <-- Starts loop over.
elif choice == "yes":
print("you reach into the whole and pull out a gemstone")
print("you put the gemstone in your inventory")
print("and go back to the room\n")
hole = True
gemstone = True
else:
print(" you go back to the centre of the room")
break # <-- Breaks out of loop.

How to make the code jump back instead of forward?

I was working with a mastermind assignment but one of my define function isn't working as expected.
How do I make the "quit" jump back to "have a guess..." instead of continue to the colourlst?
def valid_usercolour():
while True:
#print('Welcome to the Mastermind')
usercolour = input('Please have your guess [r,o,y,g]: ').lower()
if 'quit' in usercolour:
while True:
dc_quit = input('Do you really wanted to quit the game?[y/n]: ')
if dc_quit.lower() == "y":
print()
print('Alright, thank You for playing, Goodbye', user_name, '!' )
quit()
break
elif dc_quit.lower() == "n":
print("Alright, let's continue to our game")
break
else:
print("Sorry! I don't understand what you mean, could you please type only [Y/N]")
continue
colourslist = ['r','o','y','g']
if any(character not in colourslist for character in usercolour):
print("Error! Only Characters ,", colourslist, "are allowed")
continue
if len(usercolour) != 4:
print("Error! Only 4 characters are allowed!")
continue
break
return usercolour
Just add else: and indent what's below it right before colourslist. Python codes do not "jump back":
def valid_usercolour():
while True:
#print('Welcome to the Mastermind')
usercolour = input('Please have your guess [r,o,y,g]: ').lower()
if 'quit' in usercolour:
while True:
dc_quit = input('Do you really wanted to quit the game?[y/n]: ')
if dc_quit[0].lower()[0] == "y":
print()
print('Alright, thank You for playing, Goodbye', user_name, '!' )
quit()
break
elif dc_quit[0].lower()[0] == "n":
print("Alright, let's continue to our game")
break
else:
print("Sorry! I don't understand what you mean, could you please type only [Y/N]")
continue
else:
colourslist = ['r','o','y','g']
if any(character not in colourslist for character in usercolour):
print("Error! Only Characters ,", colourslist, "are allowed")
continue
if len(usercolour) != 4:
print("Error! Only 4 characters are allowed!")
continue
break
return usercolour
BONUS: I added [0] at the values of dc_quit to force taking one character only. A full 'yes' or 'no' works too ;-)

How do you get an elif to run after an if when in a stack?

I have written a menu that runs before I am testing it will only run the first if and not any of the following elif lines.
An example being when asked to make my input in the first question in the menu, if I type exit (or any capitalised variation) it will output 'Goodbye' as expected and stop running but if I type in 'color', 'colour', 'play' or make an invalid entry nothing happens and the script stops running.
print("Python Adventure\n")
def menu(): # This is the menu text for options before running the game
option_1 = input("Select an option:\nPlay Color Exit\nType:")
if option_1.lower() == "exit":
print("\nGoodbye")
exit()
elif option_1.lower() == "color" or "colour": # color options here
def color():
color_1 = input("Play with color? yes/no\nType:")
if color_1.lower() == "n" or "no":
print("Color off\n")
menu()
elif color_1.lower() == "y" or "yes":
print("Color on\n")
menu()
elif color_1.lower() != "":
print("Not recognised please try again.")
color()
color()
elif option_1.lower() == "play": # Text based game will start here.
print("Running: Python Woods")
elif option_1.lower() != "": # Invalid entry trigger.
print("Invalid entry, try again.")
menu()
menu()
Please feel welcome to correct me on any terminology and formatting too. Any learning is helpful.
Here is a better design, which most of the commenters have implied:
print("Python Adventure\n")
def color():
color_1 = input("Play with color? yes/no\nType:")
if color_1.lower() in ("n", "no"):
print("Color off\n")
elif color_1.lower() in ("y", "yes"):
print("Color on\n")
else:
print("Not recognised please try again.")
return True
return False
def menu(): # This is the menu text for options before running the game
option_1 = input("Select an option:\nPlay Color Exit\nType:")
if option_1.lower() == "exit":
print("\nGoodbye")
return False
elif option_1.lower() in ("color", "colour"): # color options here
while color():
pass
elif option_1.lower() == "play": # Text based game will start here.
print("Running: Python Woods")
elif option_1.lower() != "": # Invalid entry trigger.
print("Invalid entry, try again.")
return True
while menu():
pass

'while' loop not behaving as expected

Background:
I have made a program that takes a text input, applies encryption (a simple cipher) and saves the output to a list - if desired. Messages can also be decrypted.
The program is navigated through an options menu:
1. Encrypt a message
2. View encrypted messages
3. Decrypt a message
To allow all sections of the program to access the same list (variable) of saved messages, I have written it within a class. Within the class exist def's that call on this list.
Only the 'encrypt a message' bit has been written so far.
Problem:
The user decision flow is made with two Y/N choices.
However, the choices do not work - even if the user types in 'N' - my program thinks they have typed 'Y' in both cases.
def encrypt():
def save_cip():#This function allows the user to save the ciphered message to the ciphered_messages if they choose
choosing = True
while choosing:
save_choice = input("Would you like to save your Ciphered message? (Y/N)\n")
if save_choice == "Y" or "y":
print("You chose yes")
cct.ciphered_messages.append(' '.join(["Message", str(len(cct.ciphered_messages)), ":", cipher]))
choosing = False
elif save_choice == "N" or "n":
print("You chose no")
choosing = False
continue
else:
print("That was not a valid entry, please enter Y or N only")
continue
I think the problem lay within the scope, and that somehow the same variable is not being referenced when setting and reading Y or N. I have been going up and down the same code for about 3 hours and still nothing, declaring all variables in many different places with no luck, so any advice greatly appreciated.
Full executable code:
class cct:
print("Welcome to the CaeserCipher tool v1.0")
menu_state = "main" #This is used to record what state the program is in
unciphered_messages = [] #Decrypted messages are saved here
ciphered_messages = [] #Encrypted messages are saved here
def menu(): #This is the main menu interface
while cct.menu_state == "main": #This while
cct.menu_state = input("What would you like to do? \n 1: Encrypt a Message \n 2: View Encrypted Messages \n 3: Decrypt a message\n")
if cct.menu_state == "1":
cct.encrypt()
elif cct.menu_state == "2":
cct.view()
elif cct.menu_state == "3":
cct.decrypt()
elif cct.menu_state == "main":
print("\n\nWelcome back to the menu!\n\n")
else:
print("You did not enter a valid choice. Please enter a number between 1 and 3.\n")
cct.menu_state = "make_choice"
continue
def encrypt():
def save_cip():#This function allows the user to save the ciphered message to the ciphered_messages if they choose
choosing = True
while choosing:
save_choice = input("Would you like to save your Ciphered message? (Y/N)\n")
if save_choice == "Y" or "y":
print("You chose yes")
cct.ciphered_messages.append(' '.join(["Message", str(len(cct.ciphered_messages)), ":", cipher]))
choosing = False
elif save_choice == "N" or "n":
print("You chose no")
choosing = False
continue
else:
print("That was not a valid entry, please enter Y or N only")
continue
#This while loop continually takes messages, gives the option of saving, and asks if you want to cipher another
while cct.menu_state == "1":
text = input("Enter your message: ") #Enter the message you wish to cipher
cipher = '' #Create a string for the cipher
for char in text: #This for sub-loop will increment each character by 1. e.g. A -> B, T -> U, Z -> A
if not char.isalpha():
continue
char = char.upper()
code = ord(char) + 1
if code > ord('Z'):
code = ord('A')
cipher += chr(code)
print(' '.join(["Your ciphered message is:", cipher]))
save_cip()
print(cct.ciphered_messages)
#This sub-while loop is reponsible for checking if you want to cipher another message
#and making sure the user has made a valid choice
choosing_another = True
while choosing_another == True:
choice_variable = input(' '.join(["You have", str(len(cct.ciphered_messages)), "saved messages \n", "Would you like to Cipher another? (Y/N)\n"]))
if choice_variable == "Y" or "y":
print("You chose yes")
choosing_another = False
elif choice_variable == "N" or "n":
print("You chose no")
cct.menu_state = "main"
choosing_another = False
else:
choice_variable = input("That was not a valid entry, please enter Y or N only: \n")
continue
return
def view():
#TO BE CODED
return
def decrypt():
#TO BE CODED
return
cct.menu()
This is always true:
if save_choice == "Y" or "y":
bacause its interpreted as :
if (condition) or (condition):
the 1st condition is (save_choice == "Y")
the 2nd condition is just ( "y" ) which python interprets as 'True'
So the whole condition is always True.
U probably mean:
if save_choice == "Y" or save_choice == "y":
Or better :
if save_choice.lower() == "y":
Not a python programmer, but i don't think python allows a "implied" subject for the or operator
--> IF save_choice == "Y" OR save_choice == "y" :

How to exit only an 'if' block in Python and not the entire program

Here I want to exit the if block, but I don't want to use sys.exit() as it will terminate the program. I have a few lines to be executed at the end, hence I want to exit the if block only.
I can't use break as it flags an error "break outside loop".
In this I want the program to exit the block at "if (retry == 3)", line 55 and print the lines at the end. However, it’s not happening until it is using sys.exit(), where it’s completely exiting the program.
import random
import sys
loop = ''
retry = 0
loop = input('Do you want to play lottery? yes/no: ')
if loop != 'yes':
print('Thank you!! Visit again.')
sys.exit()
fireball = input('Do you want to play fireball? yes/no: ')
lotto_numbers = sorted(random.sample(range(0, 4), 3))
fireball_number = random.randint(0, 3)
while loop == 'yes':
user_input1 = int(input('Please enter the first number: '))
user_input2 = int(input('Please enter the second number: '))
user_input3 = int(input('Please enter the third number: '))
print('Your numbers are: ', user_input1, user_input2, user_input3)
def check():
if lotto_numbers != [user_input1, user_input2, user_input3]:
return False
else:
return True
def fbcheck():
if lotto_numbers == [user_input1, user_input2, fireball_number]:
return True
elif lotto_numbers == [fireball_number, user_input2, user_input3]:
return True
elif lotto_numbers == [user_input1, fireball_number, user_input3]:
return True
else:
return False
retry += 1
result = check()
if (result == True):
print("Congratulations!! You won!!")
else:
print("Oops!! You lost.")
if (fireball == 'yes'):
fb_result = fbcheck()
if (fb_result == True):
print("Congratulations, you won a fireball!!")
else:
print("Sorry, you lost the fireball.")
print('No of retries remaining: ', (3 - retry))
if (retry == 3):
sys.exit()
loop = input('Do you want to try again? yes/no: ')
continue
else:
pass
print("Winning combination: ", lotto_numbers)
if (fireball == 'yes'):
print('fireball no: ', fireball_number)
print('Thank you!! Visit again.')
You don't need anything at all. Code inside the if block will execute and the script will run code after the if block.
if is not a loop, so it doesn't repeat. To proceed to further code, just remember to stop the indent; that's all.
I.e.:
if some_condition:
# Do stuff
# Stop indent and do some more stuff
I think I gotcha your willing.
You want to execute something after the if condition is executed? So, create a subtask, and call it!
def finish_program():
print("something")
a = "foo"
print("finish program")
loop = input('Do u want to play lottery ? yes/no : ')
if loop!='yes':
print('Thank you!! visit again.')
finish_program()

Categories