I'm still super beginner in learning python right now and english is not my native language .I hope there is someone can answer my problem. My concern is how can I end all the loop when enter 'e'. I try to modify the code so that it exit all the loop when enter 'e' but the when I also enter 'm' , it also same when enter 'e' instead I want to return back to the menu loop when I enter 'm'. Thank you. Code below
def A():
print("a")
def B():
print("B")
def Menu():
print("Menu")
print("1.A")
print("2.B")
while True:
Menu()
while True:
option = input("Choose a or b")
if option == 'a':
A()
break
elif option == 'b':
B()
break
else:
print("Choose 'a' or 'b' only")
while True:
repeat = input("'m' or 'e'")
if repeat != 'e' and repeat != 'm':
print("Choose 'm' or 'e' only'")
if repeat == 'm':
break
if repeat == 'e':
break
break
I undestand your problem so I'll give you the only clean solution:
while True: # A loop
while True: # B loop
...
# Now from here...
# ...you want to go here?
If you want to exit both B and A loop from inside B loop, there's only one clean way:
def foo():
while True:
while True:
...
return # Will end both loops
Put the whole thing into a function and replace the "double break" with return.
There's an other solution that I would nickname "boolean label solution" which works in most cases but it's less clean so I will just give you a clue.
flag = true
while flag:
while True:
if (condition_to_exit):
flag = false
break
If you just wish to exit the program after exiting the loops, just use the exit() function:
while True:
...
while True:
...
exit()
I'd recommend creating functions for the user input, this way your code will be cleaner and easier to understand.
Look how clean the main loop looks now, it's very clear what it does:
Executes the Menu function
Lets the user choose whether to execute A or B
Asks user to input "m" or "e"
If user inputs "e" it breaks the loop
That's the steps the main loop has to do, so that's all the code that should be there. Code for checking if the user inputs the right options is not the main loop business, it should be inside a function.
This way you delegate tasks and responsibilities to different parts of the code, which for bigger projects it might not be you who programs them.
The code than be further improved and refactored, for example you might want to use dictionaries for the options of your menu. So each key is an option and the value is the function to be executed. This way your Menu() would be just a loop iterating over the dictionary to display the options and then executing the associated function.
Also you might want to take a look at classes, since all this will fit better encapsulated inside a class.
But first and most important: Keep your code clean, self descriptive and organized.
def A():
print("a")
def B():
print("B")
def Menu():
print("Menu")
print("1.A")
print("2.B")
def ExecuteAorB():
while True:
option = input("Choose a or b")
if option == 'a':
A()
break
elif option == 'b':
B()
break
else:
print("Choose 'a' or 'b' only")
def AskUserMorE():
while True:
repeat = input("'m' or 'e'")
if repeat not in ('e', 'm'):
print("Choose 'm' or 'e' only'")
else:
return repeat
while True:
Menu()
ExecuteAorB()
userInput = AskUserMorE()
if userInput == 'e':
break
Related
I'm trying to restart a program using an if-test based on the input from the user.
This code doesn't work, but it's approximately what I'm after:
answer = str(raw_input('Run again? (y/n): '))
if answer == 'n':
print 'Goodbye'
break
elif answer == 'y':
#restart_program???
else:
print 'Invalid input.'
What I'm trying to do is:
if you answer y - the program restarts from the top
if you answer n - the program ends (that part works)
if you enter anything else, it should print 'invalid input. please enter y or n...' or something, and ask you again for new input.
I got really close to a solution with a "while true" loop, but the program either just restarts no matter what you press (except n), or it quits no matter what you press (except y). Any ideas?
This line will unconditionally restart the running program from scratch:
os.execl(sys.executable, sys.executable, *sys.argv)
One of its advantage compared to the remaining suggestions so far is that the program itself will be read again.
This can be useful if, for example, you are modifying its code in another window.
Try this:
while True:
# main program
while True:
answer = str(input('Run again? (y/n): '))
if answer in ('y', 'n'):
break
print("invalid input.")
if answer == 'y':
continue
else:
print("Goodbye")
break
The inner while loop loops until the input is either 'y' or 'n'. If the input is 'y', the while loop starts again (continue keyword skips the remaining code and goes straight to the next iteration). If the input is 'n', the program ends.
Using one while loop:
In [1]: start = 1
...:
...: while True:
...: if start != 1:
...: do_run = raw_input('Restart? y/n:')
...: if do_run == 'y':
...: pass
...: elif do_run == 'n':
...: break
...: else:
...: print 'Invalid input'
...: continue
...:
...: print 'Doing stuff!!!'
...:
...: if start == 1:
...: start = 0
...:
Doing stuff!!!
Restart? y/n:y
Doing stuff!!!
Restart? y/n:f
Invalid input
Restart? y/n:n
In [2]:
You can do this simply with a function. For example:
def script():
# program code here...
restart = raw_input("Would you like to restart this program?")
if restart == "yes" or restart == "y":
script()
if restart == "n" or restart == "no":
print "Script terminating. Goodbye."
script()
Of course you can change a lot of things here. What is said, what the script will accept as a valid input, the variable and function names. You can simply nest the entire program in a user-defined function (Of course you must give everything inside an extra indent) and have it restart at anytime using this line of code: myfunctionname(). More on this here.
Here's a fun way to do it with a decorator:
def restartable(func):
def wrapper(*args,**kwargs):
answer = 'y'
while answer == 'y':
func(*args,**kwargs)
while True:
answer = raw_input('Restart? y/n:')
if answer in ('y','n'):
break
else:
print "invalid answer"
return wrapper
#restartable
def main():
print "foo"
main()
Ultimately, I think you need 2 while loops. You need one loop bracketing the portion which prompts for the answer so that you can prompt again if the user gives bad input. You need a second which will check that the current answer is 'y' and keep running the code until the answer isn't 'y'.
It is very easy do this
while True:
#do something
again = input("Run again? ")
if 'yes' in again:
continue
else:
print("Good Bye")
break
Basically, in this the while loop will run the program again and again because while loops run if the condition is True so we have made the condition true and as you know True is always true and never false. So, will not stop then after this the main part comes here first we will take input from the user whether they want to continue the program or not then we will say that if user says yes i want to continue then the continue keyword will bring the loop to the top again and will run the program again too and if the user says something else or you can do it in another way if you want to only quit the program if user says no then just add this
elif 'no' in again:
print("Good Bye")
break
else:
print("Invalid Input")
this will look that if there is the 'no' word in the input and if there is then it will break the loop and the program will quit
So I have this while loop which asks user if he/she wants to repeat the program. All works good but I was trying it out and found out that after user repeats the program and when asked second time if he/she wants to repeat, I choose no. But the program still repeats although it prints that program is closing, how can I fix this?
edit: I've fixed it with changing break with return and adding return after main()
def main():
endFlag = False
while endFlag == False:
# your code here
print_intro()
mode, message=get_input()
ui = str.upper(input("Would you like to repeat the program again? Y/N: "))
while True:
if ui == "Y":
print(" ")
main()
elif ui == 'N':
endFlag = True
print("Program is closing...")
break
else:
print("wrong input, try again")
ui = str.upper(input("Would you like to repeat the program again? Y/N: "))
This is because main() function is being called recursively & endFlag is a local variable.
So when you first put 'y' , then another main() is recursively called from the first main() function.
After you put 'n' which ends this second main() and return to the first main which still in a loop with endFlag (local variable) with value as false.
So, need to change,
Either
endFlag variable as global ( i.e. defined outside main function )
Or,
some program exit function in place of break
The thing is that you're doing recursion over here, i.e. you're calling method main() inside main() and trying to break out of it the way you've done is not gonna work (well, you're know it :) )
Second - you don't need a forever loop inside a first loop, you can do it with one simple loop and break.
Here it is:
def print_intro():
intro = "Welcome to Wolmorse\nThis program encodes and decodes Morse code."
print(intro)
def get_input():
return 'bla', 'bla-bla-bla'
def main():
while True:
# your code here
print_intro()
mode, message = get_input()
ui = str.upper(input("Would you like to repeat the program again? Y/N: "))
if ui == "Y":
print(" ")
elif ui == 'N':
print("Program is closing...")
break
else:
print("wrong input, try again\n")
main()
this is what you should do:
(BTW this is a piece of example code)
while True
name = input('Enter name:')
print ('Hi '+ name)
exit = input('Do you want to exit?(Y/N)')
if exit == 'N' or 'n':
break
(Im not sure if i put the indents correctly )
You can apply this concept into your code.
I am building off of a simple Pythagorean Theorem calculator I wrote a while back to make a more advanced version as an introduction to classes and functions. I've successfully programmed it to solve for c, either a or b and to loop back the calculation function if the user needs to do another calculation.
I've recently tried to add a main menu function, so if the user needed to solve for c, and now needs to solve for b, he/she can go back to the main menu to select the option they need. With some difficulty, I've managed to code it to where it will
Go back to the main menu
The user selects another option
The user performs the calculation as needed
1-3 repeats successfully
But then if they try to go back and select another option, it just returns to the python prompt. It's very hard for me to describe this problem in words, as other things go wrong as well. Such as, if you preform less than 2 calculations and try to go back, the method you're currently on keeps looping. I have no idea why any of this is happening, and it seems I'm doing everything right. I've tried troubleshooting, but as said above, my particular situation is hard to describe. I'm convinced that I haven't done it right, and I would like to know how. My code and screenshots are attached below.
Code
' A Pythagoren Therom Calculator (v.2.0)
By: Anon_104'''
#imports
import time, math
#Welcome statement (Welcomes the user)
print("Welcome to the pythagorean theorem calculator!")
time.sleep(1)
#a class to organize and keep everything in order ;)
class pytha:
#custom function for solving for c
def cal():
global ques1
a = int(input('Please enter the "A" value: '))
b = int(input('Please enter the "B" value: '))
print("Calculating...")
time.sleep(1)
print('The "C" value is ')
c = math.sqrt(a*a + b*b)
print(c)
ques1 = str(input("Another Calculation? (y/n) Or return to main menu? (back)"))
#function for solving for a or b, given c
def cal2():
global ques2
var = input('Please input either the "A" or "B" value: ')
c = input('Please input the "C" value: ')
var2 = float(c)**2 - float(var)**2
ans = math.sqrt(var2)
print('The "A"/"B" value is {0}'.format(ans))
ques2 = str(input("Another Calculation? (y/n) Or return to main menu? (back)"))
def mainmenu():
global query1
query1 = input('Welcome to the main menu! Solve for "C" or "A"/"B"? (opt1/opt2)')
pytha.mainmenu()
#The loop and break code for function 1
if query1 == 'opt1':
pytha.cal()
while ques1 == 'y':
pytha.cal()
if ques1 == 'back':
pytha.mainmenu()
while query1 == 'opt1':
pytha.cal()
elif ques1 == 'n':
print("Quitting... ")
time.sleep(1.6)
quit
#The loop and break code for function 2
if query1 == 'opt2':
pytha.cal2()
while ques2 == 'y':
pytha.cal2()
if ques2 == 'back':
pytha.mainmenu()
while query1 == 'opt2':
pytha.opt2
elif ques2 == 'n':
print("Quitting... ")
time.sleep(1.6)
quit
Screenshot
It doesn't loop again
P.S This is my first question EVER on a help board for anything, so go easy on me if I haven't done something right.
You don’t need the query statements at the end. Include the calls to your methods in the methods or create a new one for the purpose of returning to the main menu. I would also suggest using float() instead of int() when dealing with possible decimals, but I did not change this.
class Pytha(object):
def __init__(self):
import time, math
self.math = math
self.time = time
print("Welcome to the pythagorean theorem calculator!\n")
self.time.sleep(1)
self.mainmenu()
#custom function for solving for c
def cal(self):
try:
a = int(input('\nPlease enter the "A" value: '))
b = int(input('Please enter the "B" value: '))
print("Calculating...")
self.time.sleep(1)
print('The "C" value is ')
c = self.math.sqrt(a*a + b*b)
print(c)
except ValueError:
print("\nError: Please enter a number\n")
self.cal()
self.rerun()
#function for solving for a or b, given c
def cal2(self):
try:
var = int(input('\nPlease input either the "A" or "B" value: '))
c = int(input('Please input the "C" value: '))
var2 = float(c)**2 - float(var)**2
ans = self.math.sqrt(var2)
print('The "A"/"B" value is {0}'.format(ans))
except ValueError:
print("\nError: Please enter a number\n")
self.cal2()
self.rerun()
def mainmenu(self):
query1 = str(input('Welcome to the main menu! Solve for "C" or "A"/"B" or quit program? (opt1/opt2/q)\n'))
if query1.lower() == "opt1":
self.cal()
elif query1.lower() == "opt2":
self.cal2()
elif query1.lower() == 'q':
quit()
else:
print("Error: Please type 'opt1' or 'opt2' or 'q'\n")
self.mainmenu()
def rerun(self):
query1 = str(input('\nAnother Calculation? Solve for "C" or "A"/"B" or quit program? (opt1/opt2/q)\n'))
if query1.lower() == "opt1":
self.cal()
elif query1.lower() == "opt2":
self.cal2()
elif query1.lower() == 'q':
quit()
else:
print("Error: Please type 'opt1' or 'opt2' or 'q'\n")
self.rerun()
app = Pytha()
There were more things you could do to clean this up. I put everything in the class and called everything as self.something().
I added .lower() for your responses in case a user does OPT1 or Opt1.
I created a single rerun function to call after each operation. It automatically goes to this after the first run.
I also used try/except for your inputs because you will get a ValueError by entering a non-numeric character when calling int(). Instead, it now will tell the user to enter a number and will try again.
For quit, you need to call it as quit().
The init loads as soon as you call the class, which allows you to do things to initiate it, such as including your imports, setting variables, printing messages, and running functions. This way it is all inclusive.
Finally, it is standard practice to begin you class name with a capital letter (though not a requirement).
Hope this helps you get a better idea of how to use classes.
EDIT:
If you want to build a custom import for your tool to use without direct user interaction, you can build it like this:
class Pythag(object):
#custom function for solving for c
def solve_C(a, b):
from math import sqrt
a = int(a)
b = int(b)
c = sqrt(a*a + b*b)
return (c)
#function for solving for a or b, given c
def solveAB(var, c):
from math import sqrt
var = int(var)
c = int(c)
var2 = float(c)**2 - float(var)**2
ans = sqrt(var2)
return(ans)
Then you can import it into another script. If your pythag script is named pythag.py, you would import it as
from pythag import Pythag
Then call the modules like this:
Pythag.solve_C(4,5)
I am new to python and learning quickly. Thank you all for the help.
I am attempting to create a text menu that will always run in the background of a storytelling text rpg. I have searched and cannot find an explanation of how to create an "always on" menu or how one would work.
I would like the player to be able to hit "m" at any time in the game and have the menu prompt show up.
So far, I have created a "userinput" function as well as a "menu" function that will be deployed each time the game prompts the user/player for input.
def menu():
print('Press "1" for map >>> "2" for stats >>> "3" for exit')
choice = input()
if choice == '1':
print('map needs to be made and shown')
elif choice == '2':
print('stats need to be made and assinged to choice 2 in def menu')
elif choice == '3':
print('You are exiting the menu. Press "M" at any time to return to the menu')
return
else:
print('I did not recognize your command')
menu()
def userinput():
print('Press 1 to attack an enemy >>> 2 to search a room >>> 3 to exit game')
print('Press "M" for menu at any time')
inputvalue = input()
if inputvalue == 'm':
menu()
elif inputvalue == '1':
print('attack function here')
elif inputvalue == '2':
print('search function here')
elif inputvalue == '3':
exit
else:
userinput()
This does not appear to be an ideal solution because the user cannot choose to view a map or exit the game at any time they want.
Is there a way to have a menu always running in the background?
I thought of using a while loop that would never close and all of the game would be held within that while loop but that doesn't seem economical by any means.
Any thoughts or help would be appreciated.
I took a stab at it. This is perhaps not the best structure for doing what you're looking for but I don't want my reply to get too complicated.
The "standard" approach for anything with a UI is to separate the model, the view and the control. Check out MVC architecture online. While it adds complexity at the start it makes life much simpler in the long run for anything with a non trivial UI.
Other points of note are:
you're not stripping whitespace from your input (potentially problematic "3 " won't do what you want)
you're input is case sensitive (you ask for "M" but check for "m") .. maybe use choice = choice.strip.lower()??
there's a difference between the way raw_input and input work between Python 2 and Python 3 which means your code doesn't work in python 2. What's the difference between raw_input() and input() in python3.x? I've changed my example to use raw_input. You may want to use this work around http://code.activestate.com/recipes/577836-raw_input-for-all-versions-of-python/ near the top of your code for portability.
Some code
# flag we set when we're done
finished = False
def finish():
# ask the user for confirmation?
global finished
finished = True
return
def handle_menu_input(choice):
handled = True
if choice == '1':
print('map needs to be made and shown')
elif choice == '2':
print('stats need to be made and assinged to choice 2 in def menu')
else:
handled = False
return handled
def menu():
finished_menu = False
while not finished_menu:
print('Press "1" for map >>> "2" for stats >>> "3" for exit')
choice = raw_input() # NOTE: changes behaviour in Python 3!
if handle_menu_input(choice):
# done
pass
elif choice == '3':
print('You are exiting the menu. Press "M" at any time to return to the menu')
finished_menu = True
else:
print('I did not recognize your command')
menu()
return
def userinput():
print('Press 1 to attack an enemy >>> 2 to search a room >>> 3 to exit game')
print('Press "M" for menu at any time')
choice = raw_input() # NOTE: changes behaviour in Python 3!
if choice == 'm':
menu()
elif choice == '1':
print('attack function here')
elif choice == '2':
print('search function here')
elif choice == '3':
finish()
# elif handle_menu_input(choice):
# # delegate menu functions?? ..
# # do this if you want to see maps anytime without going through the menu?
# # otherwise comment this elif block out.
# # (Problem is 1, 2 etc are overloaded)
# pass
else:
print('I did not recognize your command')
return
def main():
# main loop
while not finished:
userinput()
return
if __name__ == "__main__":
main()
I'm trying to restart a program using an if-test based on the input from the user.
This code doesn't work, but it's approximately what I'm after:
answer = str(raw_input('Run again? (y/n): '))
if answer == 'n':
print 'Goodbye'
break
elif answer == 'y':
#restart_program???
else:
print 'Invalid input.'
What I'm trying to do is:
if you answer y - the program restarts from the top
if you answer n - the program ends (that part works)
if you enter anything else, it should print 'invalid input. please enter y or n...' or something, and ask you again for new input.
I got really close to a solution with a "while true" loop, but the program either just restarts no matter what you press (except n), or it quits no matter what you press (except y). Any ideas?
This line will unconditionally restart the running program from scratch:
os.execl(sys.executable, sys.executable, *sys.argv)
One of its advantage compared to the remaining suggestions so far is that the program itself will be read again.
This can be useful if, for example, you are modifying its code in another window.
Try this:
while True:
# main program
while True:
answer = str(input('Run again? (y/n): '))
if answer in ('y', 'n'):
break
print("invalid input.")
if answer == 'y':
continue
else:
print("Goodbye")
break
The inner while loop loops until the input is either 'y' or 'n'. If the input is 'y', the while loop starts again (continue keyword skips the remaining code and goes straight to the next iteration). If the input is 'n', the program ends.
Using one while loop:
In [1]: start = 1
...:
...: while True:
...: if start != 1:
...: do_run = raw_input('Restart? y/n:')
...: if do_run == 'y':
...: pass
...: elif do_run == 'n':
...: break
...: else:
...: print 'Invalid input'
...: continue
...:
...: print 'Doing stuff!!!'
...:
...: if start == 1:
...: start = 0
...:
Doing stuff!!!
Restart? y/n:y
Doing stuff!!!
Restart? y/n:f
Invalid input
Restart? y/n:n
In [2]:
You can do this simply with a function. For example:
def script():
# program code here...
restart = raw_input("Would you like to restart this program?")
if restart == "yes" or restart == "y":
script()
if restart == "n" or restart == "no":
print "Script terminating. Goodbye."
script()
Of course you can change a lot of things here. What is said, what the script will accept as a valid input, the variable and function names. You can simply nest the entire program in a user-defined function (Of course you must give everything inside an extra indent) and have it restart at anytime using this line of code: myfunctionname(). More on this here.
Here's a fun way to do it with a decorator:
def restartable(func):
def wrapper(*args,**kwargs):
answer = 'y'
while answer == 'y':
func(*args,**kwargs)
while True:
answer = raw_input('Restart? y/n:')
if answer in ('y','n'):
break
else:
print "invalid answer"
return wrapper
#restartable
def main():
print "foo"
main()
Ultimately, I think you need 2 while loops. You need one loop bracketing the portion which prompts for the answer so that you can prompt again if the user gives bad input. You need a second which will check that the current answer is 'y' and keep running the code until the answer isn't 'y'.
It is very easy do this
while True:
#do something
again = input("Run again? ")
if 'yes' in again:
continue
else:
print("Good Bye")
break
Basically, in this the while loop will run the program again and again because while loops run if the condition is True so we have made the condition true and as you know True is always true and never false. So, will not stop then after this the main part comes here first we will take input from the user whether they want to continue the program or not then we will say that if user says yes i want to continue then the continue keyword will bring the loop to the top again and will run the program again too and if the user says something else or you can do it in another way if you want to only quit the program if user says no then just add this
elif 'no' in again:
print("Good Bye")
break
else:
print("Invalid Input")
this will look that if there is the 'no' word in the input and if there is then it will break the loop and the program will quit