Loop issue with python3 - python

I'm struggeling a bit with a part of code for a little program I'm writing. Have in mind I'm very new with this.
Heres the code:
def sell():
sell = input("\nGreetings! What would you like to do today?\nPress 1 to sell an animal\nPress 2 to buy an animal\nPress 3 If you want to see all the farms and their animals first\n")
if sell == "1":
whichs = input("Which animal do you want to sell?\nPress 1 for pig\nPress 2 for horse\nPress 3 for cow\nPress 4 for bull\n")
if whichs == "1":
print ("\nYou just sold\n",p[0])
print ("\nYou now have 350gold")
print ("\nThese are the animals you have left:")
print (p[1], p[2], p[3]) #Prints the animals you have left from p list.
elif whichs == "2":
print ("\nYou just sold\n",p[1])
print ("\nYou now have 350gold")
print ("\nThese are the animals you have left:")
print (p[0], p[2], p[3])
elif whichs == "3":
print ("\nYou just sold\n",p[2])
print ("\nYou now have 360gold.")
print ("\nThese are the animals you have left:")
print (p[0], p[1], p[3])
elif whichs == "4":
print ("\nYou just sold\n",p[3])
print ("\nYou now have 350gold.")
print ("\nThese are the animals you have left:")
print (p[0], p[1], p[2])
else:
print ("Error")
I want this to loop so when the user has sold one animal, they start over with the:
sell = input("\nGreetings! What would you like to do today?\nPress 1 to sell an animal\nPress 2 to buy an animal\nPress 3 If you want to see all the farms and their animals first\n")
And I'm struggeling with how this is done.

The other two answers are right in telling you to use a while loop but fail to address a more general problem: the loop shouldn't be inside of the sell function but outside of it, as your text indicates that the user can also buy stuff or look at his stats. You should create individual functions for all of these actions and then create a loop that checks for the action and calls the appropriate functions:
def buy():
#...
def sell():
#...
def stats():
#...
while True:
choice = input("1: Buy 2:Sell 3:Stats - press any other key to exit")
if choice == "1": buy()
elif choice == "2": sell()
elif choice == "3": stats()
else: break
The loop could be optimized by using more pythonic approaches like mapping the choices to the functions in a dictionary, but I've written it with a simple if for clarity.
Also, if you don't choose to hold all your state in global variables (which you shouldn't), it would make sense to put the functions into a class which also holds the current balance, stock and other game parameters.

def sell():
looping = True
while looping:
sell = input("\nGreetings! ... Press Q for quit")
if sell == "1":
#rest of your code
elif sell == "Q":
looping = False

Try using a while loop:
def sell_function():
while True:
sell = input("\nGreetings! What would you like to do today?\nPress 1 to sell an animal\nPress 2 to buy an animal\nPress 3 If you want to see all the farms and their animals first\n")
# ...
else:
print("Error")
break # Stop looping on error
We could have also set a variable to True, done while variable and then variable = False instead of break for the same effect (in this instance).
I renamed your function, as you used a variable called sell and had a function with the same name which could cause problems. Also, you'll no doubt later find the break and continue statements useful.

Related

Can't end program with break. Break is used inside defined function and function is later used inside while loop. What can I do?

I need a help with a certain situation.
We have the following code:
import random
Genre = ["Power metal", "Melodic death metal", "Progressive metal", "Rock"]
Power_metal = ["Helloween", "Dragonforce", "Hammerfall"]
Melodic_death_metal = ["Kalmah", "Insomnium", "Ensiferum", "Wintersun"]
Progressive_metal = ["Dream theater", "Symphony X"]
Rock = ["Bon Jovi", "Nirvana"]
a = ["Pumpkins united", "Halloween"]
Helloween = set(a)
Music = input("\nSelect a music genre from available: %s:" % (Genre))
def bands(Music):
while True:
if Music == "Melodic death metal":
return (Melodic_death_metal)
elif Music == "Power metal":
return (Power_metal)
elif Music == "Progressive metal":
return (Progressive_metal)
elif Music == "Rock":
return (Rock)
else:
Music = input("\nYou entered the wrong name. Please, enter again: %s:" % (Genre))
Band = input("\nReffering to chosen genre, I have bands such as: %s. Choose a specific band and I'll suggest a random song:\n" % bands(Music))
def fate(Band):
while True:
if Band == "Helloween":
if len(Helloween) != 0:
print("Suggested song: ", Helloween.pop())
break
elif len(Helloween) == 0:
print("I don't have more songs to propose. Enjoy your music")
break
fate(Band)
while True:
next = input("\nWould you like me to suggest one more song from the band of your choice ? Answer yes or no:\n")
if next == "no":
print("Enjoy your music")
break
elif next == "yes":
fate(Band)
The problem is: when we get to the point where the program has no more songs to offer, it should print: "I don't have more songs to propose. Enjoy your music"and break. But instead of this, it goes all the way to the last loop and doesn't end until I type in the console no.
Can I make somehow the statement inside loop to end program even if I type in console yes?
Cause it will keep printing:
I don't have more songs to propose. Enjoy your music.
Would you like me to suggest one more song from the band of your choice ? Answer yes or no:
Thanks for the help.

Changing a local variable in multiple functions in Python?

background: I'm currently writing a text-based adventure and each enemy has a certain amount of turns you can attack it before it attacks back.
So to handle this the code sets an argument in the function for the fight dictating how many times you can attack.
def fight_sequence(rounds):
while rounds > 0:
attack = input()
if attack == magic:
magic("you teleport away to safety. Congratulations you have stayed alive through your journey and found a few souvenoirs. nice job!", 1, "you muster up all of your energy, chant the spell.... and nothing happens.Cthulu... seems unimpressed", 1, "")
elif attack == sword:
sword(1)
def magic(teleportmessage, teleportsuccess, firemessage, firefail, winmessage):
x = 0
while x == 0:
fightorflight = input("""you open the book to cast a spell
Do you want to try teleporting or use a fireball?""").lower()
if "teleport" in fightorflight:
if teleportsuccess = 1:
print(teleportmessage)
x = 1
else:
choice = input("You can't teleport out of this battle. Would you like to try a fireball?")
if choice == yes:
fightorflight = "fireball"
else:
x = 1
elif "fire" in fightorflight:
print(firemessage)
if firefail == 1:
choice = input("do you want to try to teleport instead?").lower()
if "yes" in choice:
fightorflight = "teleport"
else:
x = 1
else:
print(winmessage)
else:
print("Sorry not sure what you mean")
def sword(attacksuccess):
if attacksuccess == 1:
print("You pull out the sword and swing at the monster damaging it severely.")
else:
print("You pull out the sword and swing at the monster, but its immune to blunt objects.")
fight_sequence(3)
both magic() and sword() need to be able to decrease rounds by 1, originally i just did that before entering the magic or sword function. however some items to attack with allow you to attack more than once if you want so that won't work for them. Such as magic if they also choose to teleport. Is there a way to allow me to change the variable rounds while inside of another function?
I think using a return value might help but I'm not sure how to go about it
You can simply add a new argument to the magic function, and pass the 'rounds' variable through when you call it.
e.g.
def fight_sequence(rounds):
...
magic("some message", false, "fired", false, "you won", rounds)
def magic(teleportmessage, teleportsuccess, firemessage, firefail, winmessage, rounds):
Your passing through the variable (not just the value) so it will change in every context where rounds can be seen.
HTH.
I would recommend using classes to create this game rather than lots of functions, an example of a class in a hero game below.
class Hero:
def __init__(self):
self.health = 10
def eatApple(self):
self.health += 1
def takeDamage(self):
self.health -= 1
init function runs as class is initialized.
player = Hero()
print(player.health) # will print 10
player.takeDamage()
print(player.health) # will print 9
This way you can have global variables for you functions which can be changed in each function and is much more organised.

While loop in function not working (Python 3.5.0)

I am doing a piece of code for a school with 7-10 year old students which will test their basic arithmetic skills. The program is fully functional and should allows the teacher to see the scores in text files afterwards. However, it's currently 556 lines long. I have shortened it as much as possible but I can't seem to get this one piece of code to work:
def Repeat(repeat_q, option_right, t_class_right):
repeat_q = input("\n\nWould you like to see any other class details? ")
if repeat_q == "Yes" or repeat_q == "yes":
option_right = False
t_class_right = False
repeat_question = True
repeat_q = " "
elif repeat_q == "No" or repeat_q == "no":
print("Okay...")
repeat = False
T_Exit()
else:
print("Please only write 'yes' or 'no'")
return repeat_question
This function is called later on like this:
elif test == 2:
OP_2(list_counter, repeat_question)
while repeat_question != True:
Repeat(repeat_q, option_right, t_class_right)
All it does like this is repeat the 'repeat_q' variable. I have tried changing the value of the variable after it but nothing seems to work.I can get it to work if I take it out of the function, like this:
elif test == 3:
OP_3(list_counter, repeat_question)
while repeat_question != True:
repeat_q = input("\n\nWould you like to see any other class details? ")
if repeat_q == "Yes" or repeat_q == "yes":
option_right = False
t_class_right = False
repeat_question = True
elif repeat_q == "No" or repeat_q == "no":
print("Okay...")
repeat = False
T_Exit()
else:
print("Please only write 'yes' or 'no'")
This is what happens to the code:
Hello and welcome to my quiz.
Please write your name: teacher
Write the number of the class you would like to see (1, 2 or 3): 1
Opening Class 1
_________________________________________
| |
| 1) Alphabetical with highest score |
| 2) Highest score, highest to lowest |
| 3) Average score, highest to lowest |
|_________________________________________|
Choose one of the options above (1, 2 or 3): 2
Sorting by highest score, from highest to lowest
['Lol: 10', 'Zaid: 9', 'Abdul: 8', 'Hello: 5', 'Bruno: 5']
Would you like to see any other class details? yes
Would you like to see any other class details? yes
Would you like to see any other class details? yes
Would you like to see any other class details? yes
Would you like to see any other class details? no
Okay...
You have now finished viewing class details
Thank you for using this program
>>> # Exits the program
As opposed to this (The working but inefficient version):
Hello and welcome to my quiz.
Please write your name: teacher
Write the number of the class you would like to see (1, 2 or 3): 1
Opening Class 1
_________________________________________
| |
| 1) Alphabetical with highest score |
| 2) Highest score, highest to lowest |
| 3) Average score, highest to lowest |
|_________________________________________|
Choose one of the options above (1, 2 or 3): 1
Sorting alphabetically...
['Abdul: 8', 'Bruno: 5', 'Hello: 5', 'Lol: 10', 'Zaid: 9']
Would you like to see any other class details? yes
Write the number of the class you would like to see (1, 2 or 3): 1
Opening Class 1
_________________________________________
| |
| 1) Alphabetical with highest score |
| 2) Highest score, highest to lowest |
| 3) Average score, highest to lowest |
|_________________________________________|
Choose one of the options above (1, 2 or 3): 3
Sorting by average score, from highest to lowest
['Lol: 10.0', 'Zaid: 8.333333333333334', 'Abdul: 5.333333333333333', 'Hello: 3.3333333333333335', 'Bruno: 3.0']
Would you like to see any other class details? no
Okay...
You have now finished viewing class details
Thank you for using this program
>>>
Can anyone please help me. A full version of my code is available if anyone wants to check that out: http://www.filedropper.com/teacherprogramtask3-annotated
When you have the chunk of code inside of the Repeat() function, repeat_question = True is creating a local variable called repeat_question. This variable is a different variable to the one outside of the function that the while loop is checking.
This issue is to do with variable scope, this website explains it quite well: http://gettingstartedwithpython.blogspot.com.au/2012/05/variable-scope.html
There is a simple solution however, you just need to use the return repeat_question at the end of your function by setting repeat_question to the result of the function:
while repeat_question != True:
repeat_question = Repeat(repeat_q, option_right, t_class_right)
Also inside the function's elif...: and else: statements you may have to set repeat_question to False.
That should fix it.
EDIT: I think that it isn't working as when it is inside the function, the option_right and t_class_right variables are also only local variables and don't affect the option_right and t_class_right that are outside of the function.
It's a bit of a messy workaround but it should work.
OK I got it working!
Repeat function:
def Repeat(repeat_q, option_right, t_class_right):
repeat_q = input("\n\nWould you like to see any other class details? ")
if repeat_q == "Yes" or repeat_q == "yes":
option_right = False
t_class_right = False
repeat_question = True
repeat_q = " "
elif repeat_q == "No" or repeat_q == "no":
print("Okay...")
repeat = False
t_class_right = True
repeat_question = False
T_Exit()
else:
print("Please only write 'yes' or 'no'")
return repeat_question, t_class_right, repeat_question
And in the code:
if test == 1:
OP_1(list_counter, repeat_question)
while repeat_question != True:
repeat_question, t_class_right, repeat_question = Repeat(repeat_question, option_right, t_class_right)
elif test == 2:
OP_2(list_counter, repeat_question)
while repeat_question != True:
repeat_question, t_class_right, repeat_question = Repeat(repeat_question, option_right, t_class_right)
elif test == 3:
OP_3(list_counter, repeat_question)
while repeat_question != True:
repeat_question, t_class_right, repeat_question = Repeat(repeat_question, option_right, t_class_right)
else:
T_Broke()
You have to name repeat_q to repeat_question in the function call, as it is in the above code. That may have caused it to crash and stop working or it could have closed since option_right and t_class_right weren't being updated, or a combination of the two.

Function called without being told to

Newish to python, working on a text adventure, testing out the use of functions.
def cell1():
loop = 1
while loop == 1:
print("ONE")
cave1 = input()
if cave1 == ("end?"):
print("\nthis should end program")
loop = 0
break
elif cave1 == ("TWO"):
global testvar
testvar = 1
option1()
else:
print("INVALID")
def option1():
print("TWO")
loop = 1
while loop == 1:
print("test1 definition")
print (testvar)
test1 = input()
if test1 == ("ONE"):
print("you pick up the cheese")
loop = 0
cell1()
elif test1 == ("THREE"):
option2()
else:
print("INVALID")
def option2():
print("THREE")
loop = 1
while loop == 1:
print("This is option 3")
test2 = input()
if test2 == ("ONE"):
print("testering2")
cell1()
elif test2 == ("TWO"):
global testvar
testvar = 2014
option1()
else:
print("INVALID")
run = True
while run == (True):
print ("testing 123")
cell1()
print("restart about to activate")
cont = input("Restart? ")
if (cont) != "yes":
break
This program should allow you to go between options (what would be rooms) and eventually in cell1, the program should be end-able.
if the program is run and "end?" is typed as the first input, the program goes into the continue bit at the bottom, however, if you go between the 'rooms' then back to cell1, typing "end?" will call option 2.
Ive had a look around and it is still baffling me, am i ding something wrong?
Any help is appreciated, thank you.
The reason "end?" only quits for the player when they are within the first cell is because you're only checking for that input therein. The execution contained within option1() and option2() doesn't affect the execution of cell1(). You're not returning anything from your option functions, nor are you changing a sentinel value.
So, there's two basic ways you could go about this.
First, you could return a value from your functions:
if option1() == "END":
break
Or, you could alter your while loop:
# is_running is defined globally
while is_running:
And then just set is_running to False in any of your methods whenever the user types "end?". That'd probably be the easiest way with the design you're using now.
I'm sure you can tell, though, that in general your program is going to get exponentially more complex as you add more rooms and your function calls get further nested.
I'm pretty sure that the issue you're having is because you don't always break out of the loop in one function when you call another function. For instance, if your entries were TWO, ONE then end?, you'd find yourself still in the cell1 loop. That's because when the inner call to cell1 returns, the control flow of the program goes back to where that function was called from, which is option1, since loop is now 0, the loop ends and option1 returns, to the outer call to cell1, where the loop is still running.
Unless you want the game you're designing to have a tree structure, where you can return to where you came from with different semantics than moving to some other place, I'd suggest using a different architecture. Rather than each of your functions calling the next function when appropriate, return that function instead. Then you'd write a single top level loop that calls the function. Here's an example where the function to be called by the top level loop is saved in a variable named state:
def cell1():
print("In cell1!")
while True:
choice = input("pick 'ONE' or 'TWO' (or type 'quit' to exit):")
if choice == "ONE":
return option1
elif choice == "TWO":
return option2
elif choice == "quit":
return None
else:
print("I'm sorry, I didn't understand that.")
def option1(): # these other two functions are very basic in my example
print("In option1!") # but you can make them as complex as you want
return option2
def option2():
print("in option2!")
return cell1
def control_loop(initial_state=cell1):
state = initial_state
while state is not None:
state = state() # the next state is the return value of the previous state
The problem is you are getting deeper and deeper within nested functions. For example, changing
if test1 == ("ONE"):
print("you pick up the cheese")
loop = 0
cell1()
to
if test1 == ("ONE"):
print("you pick up the cheese")
loop = 0
break
will allow you to run your program, enter room two, go back to room one, and "end?" will work properly. This won't fix your issues completely though because there is a similar problem where when you go from two to three where if you simply changed
if test2 == ("ONE"):
print("testering2")
cell1()
to
if test2 == ("ONE"):
print("testering2")
break
it would break the current function and go back into option1() (if you run your program, go to room two, then to room three, then back to one) where "end?" doesn't do anything. Hopefully this gets you on the right track.

Problems transferring information from one part of a function to another

While working on my program I have run into a problem where the information stored in Menu option 1 is not being transferred to Menu option 2. As you can see it is correctly stored when in menu one. When it returns to go to menu option 2 its like it never went to option 1.
update #1:
some suggestions I've had is to understand scope? from what I can tell the program is not passing the data along to its parent program even though I've typed out return in each of the definitions.
#Must be able to store at least 4 grades
#Each class can have up to 6 tests and 8 hw's
#Weighted 40%*testavg 40% hw average attendance is 20%
#User must be able to input a minimum grade warning
#after each test the your program must calculate the students average and issue warning if necessary
##Define the Modules##
import math
def menu (a): #2nd thing to happen
menuend = 'a'
while menuend not in 'e':
menuend = raw_input("Type anything other then 'e' to continue:\n")
print "What would you like to do ?"
menudo = 0
print "1 - Enter Courses\n2 - Select Course to Edit\n3 - Save File\n4 - Load File\n5 - Exit\n"
menudo = input("Enter Selection:")
if (menudo == 1):
menuchck = 0
menuchck = raw_input("\nYou have entered #1 (y/n)?:\n")
if menuchck in ["Yes","yes","y","Y"]:
x = m1()
else:
print "I'm sorry,",nam,",for the confusion, lets try again\n"
menu()
elif (menudo == 2):
menuchck1 = 0
menuchck1 = raw_input("\nYou have entered #2 (y/n)?:\n")
if menuchck1 in ["Yes","yes","y","Y"]:
x = m2()
else:
print "I'm sorry,",nam,",for the confusion, lets try again\n"
menu()
elif (menudo == 3):
print "Entered 3"
elif (menudo == 4):
print "Entered 4"
else:
print "Anything Else Entered"
def course(): #3rd thing to happen
b = {}
while True:
while True:
print "\n",name,", please enter your courses below ('e' to end):"
coursename = raw_input("Course Name:")
if (coursename == 'e'):
break
will = None
while will not in ('y','n'):
will = raw_input('Ok for this name : %s ? (y/n)' % coursename)
if will=='y':
b[coursename] = {}
print "\n",name,", current course load:\n",b
coursechck = None
while coursechck not in ('y','n'):
coursechck = raw_input("Are your courses correct (y/n)")
if coursechck =='y':
return b
else:
b = {}
print
##Menu Options##
def m1():
a = course()
return a
def m2():
print "Excellent",name,"lets see what courses your enrolled in\n"
print x
return x
###User Input Section###
name = raw_input("Enter Students Name:\n")
a = {}
menu(a)
raw_input("This is the end, my only friend the end")
In your if-elif blocks in the do==1 case, you write m1(), but for the last case, you write x=m1(). You should have the latter everywhere (by typing m1() you only run the function, but do not store the returned x anywhere).
By the way, you can avoid this if-elif confusion using if chck in ["Yes","yes","Y","y"]:

Categories