Python - Input Menu Function - python

I'm quite new to Python and I am trying to make a little adventure game, just to develop my skills. So, for my game, I want there to be a few options, and the player will pick one and it will return a different result. However, the options will not always be the same, so I decided to make a function, so the options and results could differ. Here is the code for my function:
def action(act1, act2, act3, act4):
loop = True
while loop:
print(menu)
player_action = input("Where would you like to go? ")
if player_action == '1':
act1
return
elif player_action == '2':
act2
return
elif player_action == '3':
act3
return
elif player_action == '4':
act4
return
else:
print("Please type \'1\', \'2\', \'3\', or \'4\'")
The parameters are functions for what I want to print out.
My problem is, when I call this function and run the code, Python executes each function in every if and elif statement. For example, when I call this:
def home_act1():
print("Welcome to the wilderness!")
def home_act2():
print("Welcome to the town!")
def home_act3():
print("Welcome to the store!")
def home_act4():
print("You left the adventure.")
exit()
action(home_act1(), home_act2(), home_act3(), home_act4())
I run the program and it does this:
Welcome to the wilderness!
Welcome to the town!
Welcome to the store!
You left the adventure.
Process finished with exit code 0
It seems to just be running all four of my parameters, it worked before I made it a function but something isn't working right.
Thanks to any help!

In this line:
action(home_act1(), home_act2(), home_act3(), home_act4())
you are actually calling each function and passing the result (None in each case, since that is the default.
Try passing just the functions (home_act instead of home_act()), then in the loop body actually call act().

The reason you have all 4 outputs and then the code exiting is because you call all four home_act functions immediately by doing action(home_act1(), home_act2(), home_act3(), home_act4()), which executes one after another and exits the program due to the exit() in home_act4().
Another thing that is problematic is that you return after each action within the while-loop, which means the code would have stopped once the user has done one single action.
Fixing these problems results in the following code:
def action():
loop = True
while loop:
#print(menu)
player_action = input("Where would you like to go? ")
if player_action == '1':
home_act1() # call the respective action function here
elif player_action == '2':
home_act2()
elif player_action == '3':
home_act3()
elif player_action == '4':
home_act4()
else:
print("Please type \'1\', \'2\', \'3\', or \'4\'")
def home_act1():
print("Welcome to the wilderness!")
def home_act2():
print("Welcome to the town!")
def home_act3():
print("Welcome to the store!")
def home_act4():
print("You left the adventure.")
exit()
action()
Good luck with further coding :)

def home_act1():
print("Welcome to the wilderness!")
def home_act2():
print("Welcome to the town!")
def home_act3():
print("Welcome to the store!")
def home_act4():
print("You left the adventure.")
exit()
def action():
loop = True
while loop:
# print(menu)
player_action = input("Where would you like to go? ")
if player_action == '1':
return home_act1() #or you can remove the return and carry on in the function
elif player_action == '2':
return home_act2()
elif player_action == '3':
return home_act3()
elif player_action == '4':
return home_act4()
else:
print("Please type \'1\', \'2\', \'3\', or \'4\'")
action()
You can return a function call:
def functionToCall():
print('Ok function called')
def function():
return functionToCall()
function()

Related

Using Python for default parameters

I am currently learning python and stuck on a coding exercise. I am trying to achieve the result as shown on the image1. I am stuck on the overall code. I also not sure how to incorporate the "quit", so that the program terminates.
Image1
def tester(result):
while tester:
if len(result)< 10:
return print(givenstring)
else:
return print(result)
def main():
givenstring = "too short"
result=input("Write something (quit ends): ")
if __name__ == "__main__":
main()
For your problem, you need to have a variable that is your Boolean (true/false) value and have your while loop reference that. currently your while loop is referencing your function. inside your main function when you get your user input you can have a check that if the input is "quit" or "end" and set you variable that is controlling your loop to false to get out of it.
you also are not calling your tester function from your main function.
You missed into main() function to call your function, like tester(result). But such basics should not be asked here.
def tester(result):
if len(result)< 10 and result != 'quit':
givenstring = "too short"
return print(givenstring)
else:
return print(result)
def main():
result=None
while True:
if result == 'quit':
print("Program ended")
break
else:
result=input("Write something (quit ends): ")
if result.lower() == 'quit':
result = result.lower()
tester(result.lower())
if __name__ == "__main__":
main()

How do I break this infinite loop

Im trying to create a menu. The idea is to make the script loop back to the main menu when the number two is selected. It loops back but when i select number 1 it just keeps looping. How do i fix this.
import os
import sys
def mainmenu():
print """
this is a test menu
"""
mainmenu()
choice = raw_input("DMF>>")
if choice == '1':
def men1():
print """
this is the second menu
"""
men1()
def back():
men1_actions['mainmenu']()
men1_actions = {
'mainmenu': mainmenu,
'2': back,
}
while True:
choice2 = raw_input("DMF>>")
if choice2 == '2':
back()
I'm not sure with what you are pertaining to exactly but you can first define the functions and then just call on one raw_input to indicate whether the input is 1 or 2.
def mainmenu():
print """this is a test menu"""
def men1():
print """this is the second menu"""
while True:
choice = raw_input("DMF>>")
if choice == '1':
mainmenu()
elif choice == '2':
men1()
else:
print """Please choose between 1 or 2"""

How to set variable to string input python 3.5?

I'm trying to set a variable to a string input that the user inputs. I've done something similar similar before, by setting a variable to an integer input that the user inputs and tried copying that and just changing it from int() to str() but it didn't work. Here's what I have thus far:
import time
def main():
print(". . .")
time.sleep(1)
playerMenu()
Result(playerChoice)
return
def play():
playerChoice = str(playerMenu())
return playerChoice
def playerMenu():
print("So what will it be...")
meuuSelect = str("Red or Blue?")
return menuSelect
def Result():
if playerChoice == Red:
print("You Fascist pig >:c")
elif playerChoice == Blue:
print("QUICK, BEFORE YOU PASS OUT, WHAT DOES IT TASTE LIKE?!?")
return
main()
When I run it, it tells me that playerChoice is not defined. I don't understand why it's telling me this since I clearly set playerChoice = to whatever the user's string input was
Your functions return values (good) but you're not doing anything with them (bad). You should store the values in a variable and pass them to whoever needs to work with them:
def main():
print(". . .")
time.sleep(1)
choice = playerMenu()
Result(choice)
# no need for "return" at the end of a function if you don't return anything
def playerMenu():
print("So what will it be...")
menuSelect = input("Red or Blue?") # input() gets user input
return menuSelect
def Result(choice):
if choice == "Red": # Need to compare to a string
print("You Fascist pig >:c")
elif choice == "Blue":
print("QUICK, BEFORE YOU PASS OUT, WHAT DOES IT TASTE LIKE?!?")
main()

Variable is not updating in function

I'm new in Python but bear with me.
In my code, I am trying to make variable room to 2, via west() function.
Code:
EDIT: I have isolated most of the non-essential code.
room = 1
cmds = 'west'.lower()
def isValidCMD(cmd):
if cmd in cmds:
return True
else:
print("Unknown command. For help type /help, for available options type /options")
cmd = input(">> ")
if isValidCMD(cmd):
runCMD(cmd)
return False
def runCMD(cmd):
if cmd == '/help':
help()
elif cmd == '/exit':
exit()
elif cmd == '/about':
about()
elif cmd == '/stats':
stats()
elif cmd == '/options':
options()
elif cmd == 'north':
north()
elif cmd == 'south':
south()
elif cmd == 'east':
east()
elif cmd == 'west':
west()
elif cmd == '/lookaround':
look_around()
def west():
if room == 1:
print("You head on over to the lab, to get some advice from Professor Andrew.")
return 2 #LINE 40 < -------
elif room == 7:
print("You head back to Auderban Square feeling primed for battle.")
else:
print("You cannot go west.")
cmd = input(">> ")
if isValidCMD(cmd):
runCMD(cmd)
def main():
while True:
# Town
if room == 1:
print("\nYou are at the centre of town, Auderban Square.".upper())
print("\nYou look at the signpost and see 4 signs.")
print("\t- North - Twinleaf Forest")
print("\t- South - Store of Celestia")
print("\t- East - Deskemon Training Ground")
print("\t- West - Auderban's Deskemon centre")
# Lab
elif room == 2:
print("You are at Auderban's Deskemon Centre")
AndrewConv()
print("\nYou see the exit at the door.")
print("\t- East - Auderban Square")
cmd = input(">> ")
if isValidCMD(cmd):
runCMD(cmd)
main()
Output:
But room keeps its value, 1.
Please give some advice for the future so I won't make the same mistake twice.
Replace west() function with this:
def west():
global room
...
Global variables are widely considered bad programming practice because it is extremely difficult to determine where and when they might be modified in a large program. They also make thread-safe and reentrant code almost impossible to write.
A simple approach would be to have each function accept the room as a parameter and return the “new room.” You can then always update the room in your main function every time you invoke a command.
You will probably end up keeping track of more than the room, though. Consider using a mutable data structure like a dictionary or a class to store the game state, and then passing it into your command functions. That way, it is just as simple to keep up with many state variables as one, and you still do not need global variables.
def main():
state = {'room': 1}
while True:
[...]
if isValidCMD(cmd, state):
runCMD(cmd, state)
def west(state):
thisroom = state['room']
if thisroom == 1:
print("You head on over to the lab, to get some advice from Professor Andrew.")
state.update(room=2)
elif thisroom == 7:
print("You head back to Auderban Square feeling primed for battle.")
else:
print("You cannot go west.")
cmd = input(">> ")
if isValidCMD(cmd):
runCMD(cmd)
There are some additional issues with this code. For example, you duplicate the command prompt code in each command prompt, which is brittle and error prone, and unnecessary since you will be returning to main() anyway.
Edited: Here is a minimal, runnable example:
def main():
state = {'room': 1}
for i in range(20):
oldroom = state['room']
nextroom(state)
print("Went from room {} to room {}.".format(oldroom, state['room']))
def nextroom(state):
state['room'] += 2

Create a text menu in Python3x that is always available

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()

Categories

Resources