I'm currently making a main menu for my scoring system that will take the user to different parts of code by using while loops as a simple form of validation but it causes a never ending while loops because some of my definition also have while loops as well. Here's what I've done
def menu():
print("""\n Main Menu \n
1) Join the Event as a Team
2) Join the Event by Yourself
3) Score Screen""")
menuchoice_option = ["1","2","3"]
menuchoice = ""
while menuchoice not in menuchoice_option:
menuchoice = input("Please enter your choice here:")
if menuchoice == "1":
team_menu()
menuchoice = True
elif menuchoice == "2":
individual()
menuchoice = True
elif menuchoice == "3":
#scorescreen()
menuchoice = True
else:
menuchoice = False
print("Please enter a value between 1-3")
menuchoice = input("Please enter your choice here:")
Here's my other functions that the menu def causes to do an infinite whille loops
def team_menu():
global teamS
team_player = ""
while team_player != "":
team_player = input("What is your name:")
print("""\n Available Teams \n
1) Team Ahab
2) Team Ishmael
\n 3) Go back to Main Menu\n""")
team_choice = ""
team_choice_option = ["1","2","3"] # all valid choices on team menu
while team_choice not in team_choice_option:
team_choice = input("Enter your choice here:")
if team_choice == "1":
teamS["Team 1"]["Team Ahab"].append(team_player)
print(teamS["Team 1"])
print("Thank You for Joining Team Ahab")
team_choice = True
elif team_choice == "2":
teamS["Team "+ team_choice]["Teeam Ishmael"].append(team_player)
print(teamS["Team 2"])
print("\nThank You for Joining Team Miller\n")
team_choice = False
elif team_choice == "3":
menu()
team_choice = True
else:
print("Enter a value between 1-3")
team_choice = False
My ideal output would be for it stop causing infinite while loops from different defs in my code. I'm a beginner so please execuse me
Old:
Well... True will never be one of your menuchoice_option, they are 1,2,3.
Make menuchoice="1" (instead of True), for example, if the user select "1".
Edit:
Try to simplify your code: ideally, data should be atomic, and code should work around the data to extract and act as best/smart as possible. And use a better indentation (helps seeing the blocks).
Something like the following would be much, much better to maintain/develop:
def menu():
options = {
1: "Join the Event as a Team",
2: "Join the Event by Yourself",
3: "Score Screen"
}
funcs = {
1: team_menu,
2: individual,
3: scorescreen
}
print("\n Main Menu \n")
for k,v in options.items():
print(f"{k}) {v}")
choice = None
while choice not in options:
# notice that if a value invalid for "int()" casting,
# the code will blow. Wrap this with try/except to avoid it.
choice = int(input("Please enter your choice here:"))
# By now, you know a valid option was chosen.
# Let's use to select the corresponding function from "funcs" dict
funcs[choice]()
I did not test it. But looks like working.
How about using some recursion for the menu, I share my idea:
options = """
Main Menu
1) Join the Event as a Team
2) Join the Event by Yourself
3) Score Screen
4) Exit
>>> """
def menu(menuchoice):
if menuchoice == "1":
team_menu()
elif menuchoice == "2":
individual()
elif menuchoice == "3":
#scorescreen()
pass
elif menuchoice == "4":
exit()
else:
print("Please enter a value between 1-5")
decision = str(input(">>> "))
menu(decision)
if __name__ == "__main__":
decision = str(input(options))
menu(decision)
I hope I give you an idea.
Related
I have simplified it to this:
def hang():
p = 1
while p == 1:
gameinput = input("Please select a gamemode, Type [1] for one player or Type [2] for two player: ")
if gameinput == "2":
def two_player_word():
print("2")
elif gameinput == "1":
def one_player_word():
print("1")
def hangman():
if gameinput == "2":
word = two_player_word()
elif gameinput == "1":
word = one_player_word()
print("Word")
def main():
gamerestart = 1
while gamerestart == 1:
print()
print("Would you like to play again?")
gameoverinput = input("Press [1] to play again, Press [2] to exit program. ")
if gameoverinput == "1":
for i in range(0, 25):
print()
hangman()
elif gameoverinput == "2":
print("Thank you for playing, goodbye....")
time.sleep(2)
quit()
else:
print("Invaild option.")
if __name__ == "__main__":
main()
I had previously defined gameinput in the 'hang()' it collects the user input and so on.
My problem is in the 'hangman()' I need gameinput again to make the variable word (its made so a user can either make a word (two_player_word) or one player when it generates a random word (one_player_word()
It works perfectly without gameinput being in a function but after the player either wins or loses I want it to let the user decide if they want to change gamemode or not as shown in main().
There is a lot more code but figured it would be easier to try figure out the problem using just this.
Just pass the gameinput from hang into hangman as an argument.
def hang():
while True:
gameinput = input("Please select a gamemode, Type [1] for one player or Type [2] for two player: ")
if gameinput not in ("1", "2"):
continue
hangman(gameinput)
break
def hangman(gameinput):
if gameinput == "2":
word = two_player_word()
elif gameinput == "1":
word = one_player_word()
print("Word")
There are two problems that cause your code to fail (besides indentation).
You are defining nested functions (one/two_player_word) which you then try to call from outside the function (where they are not defined). You can change this by defining the functions outside the function hang().
hangman() uses the gameinput variable but it's not defined nor provided. You can change this by adding it as a parameter to the function call.
Your adjusted code could work like this:
import time
def one_player_word():
print("1")
def two_player_word():
print("2")
def hang():
p = 1
while p == 1:
gameinput = input("Please select a gamemode, Type [1] for one player or Type [2] for two player: ")
if gameinput == "2":
two_player_word()
elif gameinput == "1":
one_player_word()
def hangman(gameinput):
if gameinput == "2":
word = two_player_word()
elif gameinput == "1":
word = one_player_word()
print("Word")
def main():
gamerestart = 1
while gamerestart == 1:
print()
print("Would you like to play again?")
gameoverinput = input("Press [1] to play again, Press [2] to exit program. ")
if gameoverinput == "1":
for i in range(0, 25):
print()
hangman(gameoverinput)
elif gameoverinput == "2":
print("Thank you for playing, goodbye....")
time.sleep(2)
quit()
else:
print("Invaild option.")
if __name__ == "__main__":
main()
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.
I'm currently trying to make a scoring system where a user can enter an event as a team and I used while loops and defs to make this possible but I'm having trouble using them.
def team_menu():
global teamS
team_player = ""
while team_player:
team_player = input("What is your name:")
print("""\n Available Teams \n
1) Team Ahab
2) Team Ishmael
\n 3) Go back to Main Menu\n""")
team_choice = ""
team_choice_option = ["1","2","3"] # all valid choices on team menu
while team_choice not in team_choice_option:
team_choice = input("Enter your choice here:")
if team_choice == "1":
teamS["Team 1"]["Team Ahab"].append(team_player)
print(teamS["Team 1"])
print("Thank You for Joining Team Ahab")
team_choice = True
elif team_choice == "2":
teamS["Team "+ 2]["Team Miller"].append(team_player)
print(teamS["Team 2"])
print("\nThank You for Joining Team Miller\n")
team_choice = True
elif team_choice == "3":
menu()
team_choice = True
else:
print("Enter a value between 1-3")
team_choice = False
When I try to run this code it imidiently asks me for what to team to join even though it didn't even ask of the name of the user before. How do I fix this? My ideal output would be to ask for the name of the user first then let them pick what team they want to join
The loops within the function seem unnecessary since you're only prompting for one player.
from typing import Dict, List, NamedTuple
class Team(NamedTuple):
name: str
players: List[str]
def team_menu(team_dict: Dict[str, Team]) -> None:
player = input("What is your name: ")
print(
"""
Available Teams
1) Team Ahab
2) Team Ishmael
3) Go back to Main Menu
"""
)
choice = ""
while choice not in ["1", "2", "3"]:
choice = input("Enter your choice here:")
if choice == "3":
return # back to main menu
team_dict[choice].players.append(player)
print(f"Thank you for joining {team_dict[choice].name}")
team_dict = {
"1": Team("Team Ahab", []),
"2": Team("Team Ishmael", []),
}
team_menu(team_dict)
# menu()
You need to change 7th line:
while team_player == "":
You are using complex two-state branching based on team_player and team_choice values, it could be facilitated with one current state of team menu aka state machine:
from collections import namedtuple
def team_menu():
# Code smells, it could be passed here by param, i.e. team_menu(teamS)
global teamS
states = namedtuple("States", ("CHOOSE_PLAYER", "CHOOSE_TEAM", "END"))
# Starts from player.
state = states.CHOOSE_PLAYER
while state != states.END:
if state == states.CHOOSE_PLAYER:
team_player = input("What is your name:")
# If player name selected then continue with team.
if team_player:
state = states.CHOOSE_TEAM
elif state == states.CHOOSE_TEAM:
print(
"""
Available Teams
1) Team Ahab
2) Team Ishmael
3) Go back to Main Menu
"""
)
team_choice = input("Enter your choice here:")
# all valid choices on team menu
team_choice_option = ["1", "2", "3"]
# If team selected, add this player and continue with another player.
if team_choice in team_choice_option:
state = states.CHOOSE_PLAYER
if team_choice == "1":
teamS["Team 1"]["Team Ahab"].append(team_player)
print(teamS["Team 1"])
print("Thank You for Joining Team Ahab")
elif team_choice == "2":
teamS["Team 2"]["Team Miller"].append(team_player)
print(teamS["Team 2"])
print("Thank You for Joining Team Miller")
elif team_choice == "3":
# You don't need to call menu() but if you do, then
# be prepared to get sometimes "RecursionError: maximum
# recursion depth exceeded".
state = states.END
else:
print("Enter a value between 1-3")
# There is the end of team_menu() it could return `teamS` here
# to main `menu()` to avoid using global.
return None
I've tried googling and searching on SO, but I cant figure out why my break on the second to last line is not heading out of the while loop. Better yet, I cant figure out why the loop is not continuing either. My intention is to give the user the possibiltiy to head to the main menu after the last choice (basically the while loop for menuchoice (which is one loop above what I have pasted here).
Any suggestions? Thank you in advance. It feels like I'm missing something essential.
#this is going to show how many exercise weapons you need for next magic level
if menuchoice == "4":
#these functions returns the amount of magic wands/rods that is needed to be spent for next magic level
print("Select vocation")
print("Press P for Royal Paladin")
#ask user to input vocation:
while True:
vocationchoice = input()
if vocationchoice == "P" or vocationchoice == "p":
#ask user to input magic level for paladin
num1 = float (input("Enter your magic level: "))
#ask for own training dummy
print("Do you have your own exercise dummy? Type Y for yes and N for no.")
while True:
trainingdummy = input()
if trainingdummy == "y" or trainingdummy == "Y":
#list the different exercise weapons
print("Select exercise weapon:")
print("1. Training rod")
#loop, where we ask user to input what exercise weapon they want to calculate
while True:
while True:
weaponchoice = input()
if weaponchoice == "q":
sys.exit() #quit the program
if weaponchoice == "1" or weaponchoice == "2" or weaponchoice == "3" or weaponchoice == "f":
break #break out of the input loop
#User choice
if weaponchoice == "1":
print("The amount of training rods needed for next magic level is " + str((nextmaglvlpalwithdummy(num1))) + ".")
if trainingdummy == "n" or trainingdummy == "N":
#list the different exercise weapons
print("Select exercise weapon:")
print("1. Training rod")
#loop where ask user to input what exercise weapon they want to calculate
while True:
weaponchoice = input()
#User choice
if weaponchoice == "1":
print("The amount of training rods needed for next magic level is " + str((nextmaglvlpal(num1))) + ".")
elif weaponchoice == "f":
break
print("\nGo to main menu? Press F.")
This will help you I think. Break only breaks from current loop. If you want to go up on levels you need to break from each loop separately.
A suggestion is to turn a loop into a function and use return which will effectively exit any loop. A little bit of code refactor will be needed though.
If not the case can you maybe provide some more info and possibly the full code (there is a higher loop that we dont see here?)
First, you should print things in the input() command as it will be cleared in intend: input("Text to display").
Second, if you want to exit to the main menu, you need to break every nested loop. Here you only break the most inner loop.
As in Python there is no goto instruction nor named loops, you can use a flag. A flag is set to true when the used presses 'F' and this flag is then used at the beginning of every outer nested loop to break them. It can look like this:
while True: # This is your menu loop
menuFlag = False # Declare and set the flag to False here
menu = input("Choose the menu: ")
# ...
while True: # Choose character loop
if menuFlag: break # Do not forget to break all outer loops
character = input("Choose a character: ")
# ...
while True: # Any other loop (choose weapon, ...)
weapon = input("Choose weapon: ")
# Here you want to return to the menu if f is pressed
# Set the flag to True in this condition
if weapon == "f":
menuFlag = True
break
In your game this ressembles to:
goToMainMenu = False
while True:
if goToMainMenu: break
vocationchoice = input("Select vocation.\nPress P for Royal Paladin: ")
if vocationchoice == "P" or vocationchoice == "p":
#ask user to input magic level for paladin
num1 = float (input("Enter your magic level: "))
#ask for own training dummy
while True:
if goToMainMenu: break
trainingdummy = input("Do you have your own exercise dummy?\nType Y for yes and N for no: ")
if trainingdummy == "y" or trainingdummy == "Y":
#loop, where we ask user to input what exercise weapon they want to calculate
while True:
while True:
weaponchoice = input("Select exercise weapon:\n1. Training rod: ")
if weaponchoice == "q":
sys.exit() #quit the program
if weaponchoice == "1" or weaponchoice == "2" or weaponchoice == "3" or weaponchoice == "f":
break #break out of the input loop
#User choice
if weaponchoice == "1":
print("The amount of training rods needed for next magic level is " + str((nextmaglvlpalwithdummy(num1))) + ".")
if trainingdummy == "n" or trainingdummy == "N":
#list the different exercise weapon
#loop where ask user to input what exercise weapon they want to calculate
while True:
weaponchoice = input("Select exercise weapon (press F for main menu):\n1. Training rod: ")
#User choice
if weaponchoice == "1":
print("The amount of training rods needed for next magic level is " + str((nextmaglvlpalwithdummy(num1))) + ".")
elif weaponchoice == "f" or weaponchoice == "F":
goToMainMenu = True
break
Add a break for weaponchoice == "1" to get out of the loop.
When I print my Clients dictionary keys using option 2, it shows up as [] even when I've already added a client. Can anyone help me understand what is going wrong?
def main():
import sys
Clients = {}
choice = input(" Click 1 to add another client\n Click 2 to Check a Clients Balance\n Click 3 to change a Clients Balance ")
if choice == "1":
name = input('Add a Client\'s name : ')
Clients.update({name.rstrip("\n"):0})
print(name)
print(Clients.keys())
main()
elif choice == "2":
print(Clients.keys())
main()
elif choice == "3":
print('Do it later')
main()
else:
print('Please choose again')
main()
main()
You are calling main again and again, using a new dictionary each time, this is called recursion. Here, you should use a while loop.
def main():
clients = {}
while True:
choice = input("Click 1 to add another client\n Click 2 to Check a Clients Balance\n Click 3 to change a Clients Balance ")
if choice == "1":
name = input("Add a Client's name : ")
clients[name.rstrip()] = 0
print(name)
print(clients.keys())
elif choice == "2":
print(clients.keys())
elif choice == "3":
print('Do it later')
else:
print('Please choose again')
main()