I'm making a Choose Your Own Text Adventure game which, so far, contains far too much nesting. Example code is below = mine's in the same format, just with far more nesting - sometimes approaching 10 layers deep.
My question is: Any way to flatten it? The strings mean I need every IF statement to print something every time it's valid, so I can't just use 'AND' like this:
if A and B:
do something
elif C and D:
do something else
I've thought of putting the parts that repeat in their own functions, but then that won't improve readability in this case - at least, not that I can figure out.
Help?
print "First String"
choice = raw_input("Choose A or B")
if choice == "A":
print "You Chose A"
choice = raw_input("Choose C or D")
if choice == "C":
print "You Chose C"
choice = raw_input("Choose E or F")
if choice == "E" or choice == "F":
print "END"
elif choice == "D":
print "You Chose D"
choice = raw_input("Choose G or H")
if choice == "G" or choice == "H":
print "END"
elif choice == "B":
print "You Chose B"
choice = raw_input("Choose I or J")
if choice == "I":
print "You Chose I"
choice = raw_input("Choose C or D")
if choice == "C":
print "You Chose C"
choice = raw_input("Choose E or F")
if choice == "E" or choice == "F":
print "END"
elif choice == "D":
print "You Chose D"
choice = raw_input("Choose G or H")
if choice == "G":
print "END"
elif choice == "H":
print "You Chose H"
choice = raw_input("Choose K or L")
if choice == "K" or choice == "L":
print "END"
If the mappings are straightforward, like , lets say , if I chose A first, i can chose C or D , also if I chose B first I can chose C or E. Now when in C , irrespective of whether the first choice was A or B, the choices you get are same. Then you can use recursion along with a dictionary like -
dict = {'-1':['A','B'], 'A' : ['C','D'] , 'B':['I','J'], 'C':['E','F'] ..}
Then a recursive function like -
def choose(previousChoice, num):
print str(num) + " String"
choice = raw_input("Choose " + ' or '.join(dict[previousChoice]) + " :")
if dict.get(choice) != None and len(dict.get(choice)) > 0:
choose(choice, num + 1)
In the above example you start with -
choose('-1',1)
Related
I am trying to create a program that adds up the cost of chicken feed after you have chosen it and keeps giving me the type error for "NoneType" and "int"
I am new to Python an have no idea what to do to fix it
def printMenu():
print("Choose your type of chook food: ")
print("A. Display Chook Food Types")
print("B. Calculate total cost of the selected chook food")
print("C. Exit the program")
word = input("Enter A, B, C or D to proceed: ")
if word == "A":
print ("Choose the type of chook food: ")
print ("A. 10kg Pellets")
print ("B. 50kg Pellets")
print ("C. 10kg Mash")
print ("D. 50kg Mash")
print ("E. 10kg Enhanced")
print ("F. 50kg Enhanced")
print ("G. Return to menu")
food = input("Enter A, B, C, D, E or F, G: ")
if food == "A":
foodType() == smallPellets
print ("You have chosen 10kg Pellets")
return printMenu()
elif food == "B":
foodType() == largePellets
print ("You have chosen 50kg Pellets")
return printMenu()
elif food == "C":
foodType() == smallMash
print ("You have chosen 10kg Mash")
return printMenu()
elif food == "D":
foodType() == largeMash
print ("You have chosen 50kg Mash")
return printMenu()
elif food == "E":
foodType() == smallEnhanced
print ("You have chosen 10kg Enhanced")
return printMenu()
elif food == "F":
foodType() == largeEnhanced
print ("You have chosen 50kg Enhanced")
return printMenu()
elif food == "G":
return printMenu()
elif word == "B":
num1 = eval(input("Enter the amount you want to purchase: "))
foodType() * num1 == totalCost
print(totalCost)
elif word == "C":
exit()
else:
print ("You have entered the wrong key, try A, B, C or D")
print ("")
return printMenu()
I want to be able to chose the type of food and its specific price and when you enter the amount you need to buy it multiplys the price and gives you the answer
I can make out a few errors in your code, first of all "==" is the operator for comparing two values, "=" is the operator for assigning a value. So with "foodType () == something" you are not assigning anything, it would return either True or False, depending on what foodType () is.
Also when there are brackets behind something it means it's a function and you can't normally assign a value to a function, if you want to save multiple orders I would do something like this:
order = [] # create this list in the beginning of the function
# here come all your prints
if word == 'A':
order.append("some type of food")
elif word == 'B':
order.append("some type of food")
#...
else: # try to always include an else-statement for catching errors
print("Food unknown")
# then, for price evaluation
totalPrice = 0
for i in range(len(order)):
amount = int(input("How much", order[i], "do you want to buy?"))
totalPrice += price(order[i]) * amount
# price() is a function that returns the price of the given food type
This isn't the complete code, it's more of an outline, you'll have to piece it together yourself. Your error probably arises from totalCost = foodType() * num1, because, as already stated, foodType() is a function even though it shouldn't be.
Even if you don't make it a function something doesn't quite add up - you assign a string to foodType in 'A' and if you multiply it by num1 it wouldn't return the price, but the string num1 times like this:
>>> foodType = "pellets"
>>> num1 = 3
>>> print(foodType * num1)
>>> 'pelletspelletspellets'
That probably isn't what you want.
Feel free to ask if something isn't clear.
I am new to Pycharm, and Python as a whole, and for my first project I decided to do a random name/object selector which chooses a name from a pre-made variable of letters and prints that result.
I wanted to expand on this and have the user either use the default names in the code or add their own names to be used.
I gave it my best effort but when it came to the script running 1 of two functions I was unable to figure out how to do that.
Any help?
import string
import random
import os
letters = 'wjsdc' #*Default letters*
choice = random.choice(letters)
decision = input("Hello, use default? y/n")
print("You have chosen " + decision + ", Running function.")
def generator():
if decision == "y": #*Default function*
choice = random.choice(letters)
print("Name chosen is " + generator())
elif decision == "n": #*Attempted new function*
new_name1 = input("Please add a name")
new_name2 = input("Please add a name")
new_name3 = input("Please add a name")
new_name4 = input("Please add a name")
new_name5 = input("Please add a name")
if choice == "w":
finalname = new_name1
elif choice == "j":
finalname = new_name2
elif choice == "s":
finalname = new_name3
elif choice == "c":
finalname = new_name4
elif choice == "d":
finalname = new_name5
name = finalname
return name
print("Name chosen is " + name)
def generator(): #*Default function script*
if choice == "w":
finalname = "Wade"
elif choice == "j":
finalname = "Jack"
elif choice == "s":
finalname = "Scott"
elif choice == "d":
finalname = "Dan"
elif choice == "c":
finalname = "Conall"
name = finalname
return name
print("Name chosen is " + generator())
Your code is pretty weird, and I'm not sure what you are trying to achieve.
you define two functions generator; you should give them different names
instead of chosing from one of the letters and then selecting the "long" name accordingly, just chose from the list of names in the first place
you can use a list for the different user-inputted names
I'd suggest using something like this:
import random
def generate_name():
names = "Wade", "Jack", "Scott", "Dan", "Conall"
decision = input("Use default names? Y/n ")
if decision == "n":
print("Please enter 5 names")
names = [input() for _ in range(5)]
return random.choice(names)
print("Name chosen is " + generate_name())
This is the piece of code I have:
choice = ""
while choice != "1" and choice != "2" and choice != "3":
choice = raw_input("pick 1, 2 or 3")
if choice == "1":
print "1 it is!"
elif choice == "2":
print "2 it is!"
elif choice == "3":
print "3 it is!"
else:
print "You should choose 1, 2 or 3"
While it works, I feel that it's really clumsy, specifically the while clause. What if I have more acceptable choices? Is there a better way to make the clause?
The while bit could be refactored a little to make it a little bit cleaner by checking if the element is within a list of choices like so
while choice not in [1, 2, 3]:
This is checking if the value of choice is not an element in that list
You can push the logic into the loop, and replace
while choice != "1" and choice != "2" and choice != "3":
with
while True:
and then the initial line choice = "" is unnecessary. Then, in each branch, once you're done what you want to do you can break.
I think something like that would be better
possilities = {"1":"1 it is!", "2":"2 it is!", "3":"3 it is!"}
choice = ""
while True:
choice = raw_input("pick 1, 2 or 3")
if choice in possilities:
print possilities[choice]
break
else:
print "You should use 1, 2 or 3"
You can use a dictionary to map 1 to the code you want to execute when 1 is the value, and so on... That way you get rid of the ifs and your code can support other values in the future by simply updating the dictionary. As for the condition in the while, you just check if the key is in the dictionary.
I'd suggest having a function which just loops until a valid option is chosen, then returns the chosen value.
This means the rest of your code is not intended inside the while, keeping everything nice and flat ("Flat is better than nested")
def get_choice(options):
"""Given a list of options, makes the user select one.
The options must be strings, or they will never match (because raw_input returns a string)
>>> yn_choices = ['y', 'n']
>>> a = get_choice(options = yn_choices)
"""
prompt_string = "Pick " + ", ".join(options)
while True:
choice = raw_input(prompt_string)
if choice in options:
return choice
else:
print "Invalid choice"
# Prompt user for selection
choice = get_choice(["1", "2", "3"])
# Do stuff with choice...
if choice == "1":
print "1 it is!"
elif choice == "2":
print "2 it is!"
elif choice == "3":
print "3 it is!"
else:
print "You should choose 1, 2 or 3"
I think you can use a set which contains all of your possible choices and use "in" expression to judgefor the while part.
As for the if-else part, print (choice, " it is!") will be ok.
while str(choice) not in "123"
.....
This question already has answers here:
how to stop a for loop
(9 answers)
Closed 6 years ago.
I am making a script game and use this code for multiple choice.
while True:
d1a = input ("Do you want to: A) Befriend Fred. B) Be mean to Fred. [A/B]? : ")
if d1a == "A":
print ("You befriend fred. You now have a friend..")
elif d1a == "B":
print ("You angered Fred. He kills you. RIP.")
elif d1a == "Q" :
break
After this happens,If you type A or B it will print the desired text and then ask you again "Do you want to befriend fred?" etc.
You can simply add break statements to each conditional:
while True:
d1a = input ("Do you want to: A) Befriend Fred. B) Be mean to Fred. [A/B]? : ")
if d1a == "A":
print ("You befriend fred. You now have a friend..")
break
elif d1a == "B":
print ("You angered Fred. He kills you. RIP.")
break
elif d1a == "Q" :
break
Also if you want to leave the loop after one iteration the loop isn't necessary. However, I assume you're looping until you get the correct input, in which case it might be nice to tell your player that the input was incorrect:
while True:
d1a = input ("Do you want to: A) Befriend Fred. B) Be mean to Fred. [A/B]? : ")
if d1a == "A":
print ("You befriend fred. You now have a friend..")
break
elif d1a == "B":
print ("You angered Fred. He kills you. RIP.")
break
else:
print("Incorrect input")
This is the piece of code I have:
choice = ""
while choice != "1" and choice != "2" and choice != "3":
choice = raw_input("pick 1, 2 or 3")
if choice == "1":
print "1 it is!"
elif choice == "2":
print "2 it is!"
elif choice == "3":
print "3 it is!"
else:
print "You should choose 1, 2 or 3"
While it works, I feel that it's really clumsy, specifically the while clause. What if I have more acceptable choices? Is there a better way to make the clause?
The while bit could be refactored a little to make it a little bit cleaner by checking if the element is within a list of choices like so
while choice not in [1, 2, 3]:
This is checking if the value of choice is not an element in that list
You can push the logic into the loop, and replace
while choice != "1" and choice != "2" and choice != "3":
with
while True:
and then the initial line choice = "" is unnecessary. Then, in each branch, once you're done what you want to do you can break.
I think something like that would be better
possilities = {"1":"1 it is!", "2":"2 it is!", "3":"3 it is!"}
choice = ""
while True:
choice = raw_input("pick 1, 2 or 3")
if choice in possilities:
print possilities[choice]
break
else:
print "You should use 1, 2 or 3"
You can use a dictionary to map 1 to the code you want to execute when 1 is the value, and so on... That way you get rid of the ifs and your code can support other values in the future by simply updating the dictionary. As for the condition in the while, you just check if the key is in the dictionary.
I'd suggest having a function which just loops until a valid option is chosen, then returns the chosen value.
This means the rest of your code is not intended inside the while, keeping everything nice and flat ("Flat is better than nested")
def get_choice(options):
"""Given a list of options, makes the user select one.
The options must be strings, or they will never match (because raw_input returns a string)
>>> yn_choices = ['y', 'n']
>>> a = get_choice(options = yn_choices)
"""
prompt_string = "Pick " + ", ".join(options)
while True:
choice = raw_input(prompt_string)
if choice in options:
return choice
else:
print "Invalid choice"
# Prompt user for selection
choice = get_choice(["1", "2", "3"])
# Do stuff with choice...
if choice == "1":
print "1 it is!"
elif choice == "2":
print "2 it is!"
elif choice == "3":
print "3 it is!"
else:
print "You should choose 1, 2 or 3"
I think you can use a set which contains all of your possible choices and use "in" expression to judgefor the while part.
As for the if-else part, print (choice, " it is!") will be ok.
while str(choice) not in "123"
.....