So I am creating a survival game, and I need to know how to loop back to a certain point in the code. I have wrapped the entire game in a function, but--now when in run it-- it just restarts itself.
import random
def game(choice1):
print "You need to build a fire. the recipe is 5 stick and 3 coal."
choice1 = raw_input("There are trees to your left and rocks to your right. Which way will you go?")
if choice1 == "left" or choice1 == "Left":
choice2a = raw_input("You go to the tree. Would you like to punch it?")
if choice2a == "yes" or choice2a == "Yes":
R = random.randint(1,11)
print "You punched the tree " + str(R) + " times."
if R <= 5:
print "It did not fall down"
elif R > 5:
R2 = random.randint(0, 5)
print"It fell down. It dropped " + str(R2) + " sticks."
elif choice2a == "no" or choice2a == "No":
game(choice1)
if choice1 == "right" or choice1 == "Right":
choice2b = raw_input("You go to the rocks. Would you like to pick up the coal in them?")
return game(choice1)
I imagine you want to loop back to the first raw_input statement, if that is the case, you can use while loops as Celeo has pointed above.
You will have to use an exit condition to escape the while loop once you are done looping.If you want to loop back to different parts of the program then I would recommend you write the code block as functions and call them as necessary.
Try reading about while loops here:
http://www.tutorialspoint.com/python/python_while_loop.htm
A while loop lets you repeat a code depending on a condition (while a condition is met, go back to the start).
To make such a game I would recommend using a (decision) state-machine. If the game is in a certain state, the player is asked the corresponding question and depending on the answer the game is moved to an other state. Each state should be implemented independently from the others, i.e. avoid deeply nested if/else constructs, this avoids errors and helps you to stay on top of things. You can also visualize/draw the game decision plan as a graph, where each node represents a state (or decision to be made) and each decision connects the node to an other state.
For your concrete example, you also need to keep track of what the player has collected so far, which is essentially an other state-system.
To implement such a state-based-game you can (ab-)use the python concept of generators. A generator is basically an object that returns 'items' with yield when queried with next(). A generator can provide a finite or an infinite amount of 'items', it can also return 'items' from an other generator with yield from.
Here an example implementation of your game:
Be aware that this code works only with python3! It should be possible to translate it into python2 (perhaps even automatically), but I feel no strong urge to do so ATM ;)
import random
import collections
def main(backpack):
print("You need to build a fire. the recipe is 5 stick and 3 coal.")
print("You have the following items in your backpack:")
for k,v in backpack.items():
print(' % 3d %s' % (v,k))
#TODO: add check if we have collected enough here
yield from choice1(backpack)
# tree or stone
def choice1(backpack):
answer = input("There are trees to your left and rocks to your right. Which way will you go?")
if answer.lower() in ('l', 'left'):
yield from choice2a(backpack)
elif answer.lower() in ('r', 'right'):
yield from choice2b(backpack)
else:
print('I could not understand you. Answer with either "left" or "right".')
yield from choice1(backpack)
# punch or not
def choice2a(backpack):
answer = input("You go to the tree. Would you like to punch it?")
if answer.lower() in ('y', "yes"):
R = random.randint(1,11)
print( "You punched the tree " + str(R) + " times.")
if R <= 5:
print("It did not fall down")
else:
R2 = random.randint(0, 5)
print("It fell down. It dropped " + str(R2) + " sticks.")
backpack['stick'] += R2
yield from choice2a(backpack)
elif answer.lower() in ('n', "no"):
yield from main(backpack)
else:
print('I could not understand you. Answer with either "yes" or "no".')
yield from choice2a(backpack)
# pick up or not
def choice2b(backpack):
answer = input("You go to the rocks. Would you like to pick up the coal in them?")
# TODO: implement this
yield main(backpack)
if __name__ == '__main__':
backpack=collections.defaultdict(int)
while True:
next(main(backpack))
Each of the functions is a generator-function, i.e. a function that returns a generator. Each of them represents a game-state that requires a decision. The player-state (i.e. what the player has collected so far) is passed along as backpack which is a dictionary that contains the amount per item.
(yield from xyz() could be interpreted as a kind of goto command.)
Related
This is an exercise from Introduction to CompSci and Programming in Python from OCW MIT. I modified it a little bit. The problem is I want to stop the program when I reached the max wrong answer but it stops if I try two times. Why two times ? How can I fix this ? As a new starter should I ask every question here ? Thanks to all
n = 0
max_guesses = 3
n = input("You are in the Lost Forest\n****************\n****************\n :)\n****************\n****************\nGo left or right? ")
if n == "left" or "Left":
print("You're out of lost forest")
while n == "right" or n == "Right":
n = input("You are in the Lost Forest\n****************\n****** ***\n :(\n****************\n****************\nGo left or right? ")
n =+ 1
for n in range (max_guesses):
break
print("Game over! You ran out of your lives")
There are a few errors that contribute to your code not working properly
Your variable n is the same as the value you get from the value you input best to separate those into different values to make it easier to avoid hard to detect errors
You need to have a condition that checks if n >= max_guesses.
Welcome to the community, we try to discuss the issues here rather than looking for a whole solution.
I suggest you to first learn the very basics of programming like the decision making, control flows (i.e if statements and loops).
Also, try to attempt the question, multiple numbers of times with different logics and inputs at runtime. it will give you a better understanding of logical analysis.
Here's one of the ways you could have added the logic.
#Maximum allowed guesses
max_guesses = 3
def func1():
#Input string 'left' or 'right'
in_str = input("You are in the Lost Forest\n****************\n****************\n :)\n****************\n****************\nGo left or right? ")
#Number of attempts made
n = 1
if in_str.lower() == "left":
print("You're out of lost forest")
while in_str.lower() == "right":
in_str = input("You are in the Lost Forest\n****************\n****** ***\n :(\n****************\n****************\nGo left or right? ")
n += 1
if in_str.lower() == "left":
print("You're out of lost forest")
break
if n >= max_guesses:
print("Game over!!!")
break
print("Total attempts made by user: ",n)
func1()
I have attempted to fix your code however, I have had to remove the for loop and change the variable names. Hopefully, it helps.
n = 1
max_guesses = 3
a = input("You are in the Lost Forest\n****************\n****************\n :)\n****************\n****************\nGo left or right? ")
if a.lower() == "left":
print("You're out of lost forest")
while a.lower() == "right":
if n == 3:
print("Game over! You ran out of your lives")
break
else:
a = input("You are in the Lost Forest\n****************\n****** ***\n :(\n****************\n****************\nGo left or right? ")
n += 1
I am doing an assignment for an IT class. Very basic Python projects. I have no experience with it but am able to grasp what is going on most of the time. This project involves making choices involving random integer selections. I can get the options to work the way I want in the if-else format but the else command isn't responding the way I want. The options all load properly but if the choice is 1-3 for some reason the program then prints the "else" statement after printing the "if" statements. This doesn't happen if they choose option 4 or pick an invalid number(the reason for the else statement).
I didn't have this issue in the previous section of the program. I must have missed something, but I can't tell what it is. I should reiterate I am very much a beginner at this and am basically copy-pasting code as the assignment instructed, and then editing it to suit my needs.
interactions = ["Back Away Slowly","Point Towards the Chamber","Attack","Try To Communicate",]
import random
badchoice = random.randint(1,3)
loop = 1
while loop == 1:
choice=menu(interactions, "How do you decide to interact?")
print("")
if choice == 1:
print("You start to slowly back away from the man.")
print("You worry you are giving off the wrong attitude.")
print("")
if choice == badchoice:
loop=0
print("The stranger was already weary of your presence.")
print(interactions[choice-1], "was not the correct decision.")
print("He calls for help. Villagers and guards immediately surround you.")
print("You are thrown back into the chamber. Hitting your head, and getting knocked unconscious in the process.")
print("You are back where you started and the items have been removed.")
print("There is no escape.")
print("Lamashtu's Curse can not be broken.")
print("Game Over.")
else:
print("The stranger looks at you in confusion.")
print("")
# Choices 2 and 3 go here. Same code. Seemed redundant to post all of it.
if choice == 4:
loop=0
print("The stranger is weary of your presence, and can not understand you.")
print("You can see in his eyes that he wants to help,")
print("and he escorts you back to his home for the time being.")
print("He offers you some much needed food and water.")
print("You are no closer to understanding what curse brought you here.")
print("Perhaps tomorrow you will have more time to inspect your surroundings.")
print("In time you may be able to communicate enough with your host to explain your dilemma,")
print("but for now you are trapped 6000 years in the past with no other options.")
print("At least you've made it out alive thus far......")
print("To be continued...")
else:
print("Please choose a number between 1 and 4.")
The else only applies to the most recent if at the same level, ie the one for number 4. The other three if statements are all independent. So after checking each of those, it then goes to check if the choice is 4, and runs the else if it isn't.
You need to make these all part of the same statement, which you do by using elif for every if after the first. Like this:
if choice == 1:
...
elif choice == 2:
...
elif choice == 3:
...
elif choice == 4:
...
else:
...
Your logic is incorrect. Your final if statement directs choice 4 to it's True branch, and everything else to the False branch. Python does exactly what you told it to do. There is no logical reference to the previous blocks.
The logic you need is
if choice == 1:
...
elif choice == 2:
...
elif choice == 3:
...
elif choice == 4:
...
else:
print("Please choose a number between 1 and 4.")
I'm creating a text-based adventure game in Python 3.4.3 and I can't figure out how to make the code repeat a question. There's a bunch of narration before this, if that helps understand what's going on at all.
print("\n\n\n\n\nYou awake to find yourself in the center of a clearing in a forest.")
print("You stand up and decide to take a look around.")
str = input("Which direction do you steer your head? d= down, l= left, r= right, u= up, b= behind you: ")
print(" ")
if str in ("d"):
print("You see your combat boots and the grassy ground below your feet. ")
if str in ("l"):
print("The forest trees grow thicker and darker that way. You stare into the shadows and feel... cold...")
if str in ("r"):
print("The forest is warm and inviting that way, you think you can hear a distant birds chirp.")
if str in ("u"):
print("The blue sky looks gorgeous, a crow flies overhead... that's not a crow...")
print("It's a Nevermore, an aerial Grim. You stand still until it passes.")
if str in ("b"):
print("the grass slowly grows to dirt as the area falls into a mountain cliff. You now know where you are.")
print("Mount Glenn, one of the most Grim-infested places in all of Remnant.")
print("It's a bit unsettling.")
else:
print("Try that again")
I want the code to repeat the question to the user, until they've answered every possible answer and move on to the next question. I also want it to repeat the question when they get else. How do I do this?
Don't use str as a variable name, it will shadow an important builtin and cause weird problems.
Use a while loop to restrict the output to valid options.
valid_choices = ('d', 'l', 'r', 'u', 'b',)
choice = None
while choice not in valid_choices:
text = input("Which direction do you steer your head? d= down, l= left, r= right, u= up, b= behind you: ")
choice = text.strip()
if choice == 'd':
print ('...')
elif choice == 'u':
print ('...')
See also:
string.strip
tuples
None
Basically you can put your question in a loop and iterate through it until you enter one of the desired 'if' case. I have modified your code as below. Please have a look
print("\n\n\n\n\nYou awake to find yourself in the center of a clearing in a forest.")
print("You stand up and decide to take a look around.")
while True:
str = input("Which direction do you steer your head? d= down, l= left, r= right, u= up, b= behind you: ")
print(" ")
if str in ("d"):
print("You see your combat boots and the grassy ground below your feet. ")
break
if str in ("l"):
print("The forest trees grow thicker and darker that way. You stare into the shadows and feel... cold...")
break
if str in ("r"):
print("The forest is warm and inviting that way, you think you can hear a distant birds chirp.")
break
if str in ("u"):
print("The blue sky looks gorgeous, a crow flies overhead... that's not a crow...")
print("It's a Nevermore, an aerial Grim. You stand still until it passes.")
break
if str in ("b"):
print("the grass slowly grows to dirt as the area falls into a mountain cliff. You now know where you are.")
print("Mount Glenn, one of the most Grim-infested places in all of Remnant.")
print("It's a bit unsettling.")
break
else:
print("Try that again")
Do something like this:
answered = False
while not answered:
str = input("Question")
if str == "Desired answer":
answered = True
Here's how I would do this; explanation is in the comments:
# Print out the start text
print("\n\n\n\n\nYou awake to find yourself in the center of a clearing in a forest.")
print("You stand up and decide to take a look around.")
# Use a function to get the direction; saves some repeating later
def get_direction():
answer = input("Which direction do you steer your head? d= down, l= left, r= right, u= up, b= behind you: ")
print(" ")
return answer
# Keep running this block until the condition is False.
# In this case, the condition is True, so it keeps running forever
# Until we tell Python to "break" the loop.
while True:
# I changed "str" to "answer" here because "str" is already a Python
# built-in. It will work for now, but you'll get confused later on.
answer = get_direction()
if answer == "d":
print("You see your combat boots and the grassy ground below your feet. ")
# Stop the loop
break
elif answer == "l":
print("The forest trees grow thicker and darker that way. You stare into the shadows and feel... cold...")
break
elif answer == "r":
print("The forest is warm and inviting that way, you think you can hear a distant birds chirp.")
break
elif answer == "u":
print("The blue sky looks gorgeous, a crow flies overhead... that's not a crow...")
print("It's a Nevermore, an aerial Grim. You stand still until it passes.")
break
elif answer == "b":
print("the grass slowly grows to dirt as the area falls into a mountain cliff. You now know where you are.")
print("Mount Glenn, one of the most Grim-infested places in all of Remnant.")
print("It's a bit unsettling.")
break
else:
print("Try that again")
# NO break here! This means we start over again from the top
Now, none of this scales very well if you add more than a few directions;
because I assume that after you go "right" you want a new question, so that's a
new loop inside the loop, etc.
# The start text
print("\n\n\n\n\nYou awake to find yourself in the center of a clearing in a forest.")
print("You stand up and decide to take a look around.")
# Use a function to get the direction
def get_direction():
answer = input("Which direction do you steer your head? d= down, l= left, r= right, u= up, b= behind you: ")
print(" ")
return answer
# Use a function to store a "location" and the various descriptions that
# apply to it
def location_start():
return {
'down': [
# Function name of the location we go to
'location_foo',
# Description of this
'You see your combat boots and the grassy ground below your feet.'
],
'left': [
'location_bar',
'The forest trees grow thicker and darker that way. You stare into the shadows and feel... cold...'
],
'right': [
'location_other',
'The forest is warm and inviting that way, you think you can hear a distant birds chirp.'
],
'up': [
'location_more',
"The blue sky looks gorgeous, a crow flies overhead... that's not a crow...\n" +
"It's a Nevermore, an aerial Grim. You stand still until it passes."
],
'behind': [
'location_and_so_forth',
"The grass slowly grows to dirt as the area falls into a mountain cliff. You now know where you are.\n" +
"Mount Glenn, one of the most Grim-infested places in all of Remnant.\n" +
"It's a bit unsettling."
],
}
# And another location ... You'll probably add a bunch more...
def location_foo():
return {
'down': [
'location_such_and_such',
'desc...'
],
}
# Store the current location
current_location = location_start
# Keep running this block until the condition is False.
# In this case, the condition is True, so it keeps running forever
# Until we tell Python to "break" the loop.
while True:
# Run the function for our current location
loc = current_location()
answer = get_direction()
if answer == ("d"):
direction = 'down'
elif answer == ("l"):
direction = 'left'
elif answer == ("r"):
direction = 'right'
elif answer == ("u"):
direction = 'up'
elif answer == ("b"):
direction = 'behind'
else:
print("Try that again")
# Continue to the next iteration of the loop. Prevents the code below
# from being run
continue
# print out the key from the dict
print(loc[direction][1])
# Set the new current location. When this loop starts from the top,
# loc = current_location() is now something different!
current_location = globals()[loc[direction][0]]
Now, this is just one way of doing it; one downside here is that you'll need
to repeat the descriptions for the locations if you want to allow the player to
approach one location from different directions. This may not apply to your
adventure game (the original adventure doesn't allow this, if I remember
correctly).
You can fix that quite easily, but I'll leave that as an exercise to you ;-)
I have been set some homework to make a word guessing game, I have got it to work for the most part but at this point I am using random.choice and that command allows the same string to repeat more than once. I need to know how to use random.randint in this instance.
""" This is a guessing game which allows the person operating the program to
guess what i want for christmas"""
import random
sw = ("Trainers")
print ("In this game you will have 10 chances to guess what I want for christmas, you start with 10 points, each time you guess incorrectly you will be deducted one point. Each time you guess incorrectly you will be given another clue.")
clue_list = ["They are an item of clothing", "The item comes in pairs", "The Item is worn whilst playing sport", "The item is an inanimate object", "The item can be made of leather","They come in differant sizes", "They have laces", "can be all differant colours", "the item has soles", "Im getting it for christmas ;)"]
def guessing_game(sw, clue_list):
x = 10
while x<=10 and x > 0:
answer = input("What do I want for christmas?")
if sw.lower() == answer and answer.isalpha():
print ("Good Guess thats what I want for christmas")
print ("You scored %s points" % (x))
break
else:
print ("incorrect, " + random.choice(clue_list))
x -=1
if x == 0:
print ("You lost, try again")
guessing_game(sw, clue_list)
for your implementation I think you want:
clueint = random.randint(0, len(clue_list))
print("incorrect, " + clue_list[clueint])
to ensure the same clues are not displayed twice declare an empty list to store guess in OUTSIDE the function definition:
clues_shown = []
and then add each int to the list:
def showClue():
clueint = random.randint(0, len(clue_list))
if clueint in clues_shown:
showClue()
else:
clues_shown.append(clueint)
print("incorrect, " + clue_list[clueint])
So I have the following code:
def monsterturn():
global monster
global playerhp
turn = True
print "Rolling for", monster, "...(14 or better to hit)"
time.sleep(1)
if r > 14:
print r, "- The", monster, "hit you!"
playerhp-=1
time.sleep(0.5)
print "Your HP:", playerhp
if playerhp == 0:
turn = False
time.sleep(0.5)
print "YOU HAVE BEEN SLAIN."
else:
turn = False
time.sleep(1.5)
playerturn()
elif r < 14:
print r, "- The", monster, "missed you."
turn = False
playerturn()
r = randrange(1, 21)
The function playerturn() is structured exactly like monsterturn(), except with the global variable monsterhp instead of playerhp, r2 instead of r, and dialogue for the player instead of the monster. The problem is, it calculates a random integer once, and then keeps it, which often winds up with nobody hitting anyone, forever. How can I get it to calculate a different random integer every time?
Also, the function playerturn() is called, and at the end triggers monsterturn(), which triggers playerturn(), and so on, until somebody dies.
I think you should just rethink your overall design, as this would cause you to run into issues. This is largely theoretical, but the longer your fight is, the deeper your call stack would become, in the end possibly resulting in a stack overflow (and also increased memory consumption; even if it continues to run fine).
Instead, I'd suggest you rework the functions to return a boolean value, whether the game should continue. You're then able to just loop as long as both functions return true, essentially meaning the game continues:
while playerturn() and monsterturn():
To make each hit/attack random, you'd reassign r a random value right before using it:
...
time.sleep(1)
r = randrange(1, 21)
if r > 14
...
Calculate r within the loop, instead of outside it.
You can also improve this greatly by factoring out the common material, so that monster and player have the same turn function. You'd do this by avoiding the reference to global variables and passing in the details that change (opponent's hitpoints, the message to print, and so forth)