Ex 36 Game Functions

Good evening,

I am completing Ex 36 and I have a question about best practice. I have a death function that accomplishes what I want it to (I think), but I wrote it in two different ways. Which follows best practice, and why? Again, both functions run.

Lastly, is there a better way to post this to make it easier for other readers of the forum? Should I post in github and send the link? Is that acceptable?

Example 1:

#This is an attempt at a text-based survival game game.  I'm really not sure how it is going to work out.
def start():
    print("""Your airplane was struck by a missle and you have crash-landed on a mountain side.  Your communications were destroyed.  Everyone onboard has perished except for you and your 11 year-old son.  After looking through the rubble, you were able to secure enough food to last three days at the most.  You have no means to alert anyone of your whereabouts.  How will you survive?  Will your son make it, or will you leave him fend for himself?\n\nAbout 150 yards ahead, you see something unusual.  As you and your son slowly stagger towards the site, you determine that it is a cave.  What will you do?  Will you go in or stay outside?""")
	
	choice = input("Do you want to go in or stay outside?  > ")
	if choice == "go in":
		print("The ground tremors and rocks seal you in separating you from your son.  While he can barely hear you, you tell him to hang tight and try to find help.")
	elif choice == "stay outside":
		death("How are you going to survive if you do nothing?  You lose!")
	else:
		death("Don't play yourself!  Your choices are to go in or stay outside.  Bye LOSER!")                  	
	
    def death(how):
    	print(how)
    	print("Would you like to try again?  Enter 1 for Yes or 2 for No.")
	
	#try:
	choice = input("> ")
	#	choice = int(input("> "))
		
	#except:
	#	print("Enter 1 for Yes or 2 for No.")	
	print("Enter 1 for Yes or 2 for No.")
		
	#print(">>>", choice)
	
	#if choice == 1:  #I tried try: and except: but it didn't work.
	#	start()
	#elif choice == 2:
	#	print("Thanks for playing.  Good-bye!")	
	#print(">>>>>>>>", repr(choice))
	
	if choice in "1":  #I tried try: and except: but it didn't work.
		start()
	elif choice in "2":
		print("Thanks for playing.  Good-bye!")
	#elif choice.isdigit() != 1 or 2:
		#print("Not an option. ")
	else:
		print("You obviously do not want to play.  Ciao!")
    	
    		

    start()

Example 2:

#This is an attempt at a text-based survival game game.  I'm really not sure how it is going to work     out.

def start():
	print("""Your airplane was struck by a missle and you have crash-landed on a mountain side.  Your communications were destroyed.  Everyone onboard has perished except for you and your 11 year-old son.  After looking through the rubble, you were able to secure enough food to last three days at the most.  You have no means to alert anyone of your whereabouts.  How will you survive?  Will your son make it, or will you leave him fend for himself?\n\nAbout 150 yards ahead, you see something unusual.  As you and your son slowly stagger towards the site, you determine that it is a cave.  What will you do?  Will you go in or stay outside?""")

choice = input("Do you want to go in or stay outside?  > ")
if choice == "go in":
	print("The ground tremors and rocks seal you in separating you from your son.  While he can barely hear you, you tell him to hang tight and try to find help.")
elif choice == "stay outside":
	death("How are you going to survive if you do nothing?  You lose!")
else:
	death("Don't play yourself!  Your choices are to go in or stay outside.  Bye LOSER!")                  	

def death(how):
	print(how)
	print("Would you like to try again?  Enter 1 for Yes or 2 for No.")

while True:
	try:
		choice = int(input("> "))
		if choice == 1:
			start()
    		elif choice == 2:
				print("Thanks for playing.  Good-bye.")
			break
		except ValueError:
			print("Invalid selection!!  Enter 1 for Yes or 2 for No.")

start()

Yes, if you have github that’s always a good option. I prefer the try/except method personally. Also, your indentation on this is crazy. Are you using tabs or spaces? You should definitely switch to spaces only. Check your editor settings.

I created a GitHub Gist with the problematic code.

pokeSnakes.py

As we discussed previously, I am working trying to think of user errors and handle them appropriately. In this function, I typecast the variable as an integer. Well, if a user enters a string like “foo,” Python throws an exception, as expected. However, when I try to handle the exception, I get another error. The error description is below. I would appreciate some insight into how to address this issue. I have spent the last few weeks trying to figure this out myself, to no avail. Many thanks to all.

foo

I got here…ValueError
Traceback (most recent call last):
File “/Users/dngra_000/VSCode_github/LPTHW/2020-09-18, Ex36.py”, line 117, in pokeSnakes
attempts = int(input(">"))
ValueError: invalid literal for int() with base 10: ‘foo’

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File “/Users/dngra_000/VSCode_github/LPTHW/2020-09-18, Ex36.py”, line 236, in
start()
File “/Users/dngra_000/VSCode_github/LPTHW/2020-09-18, Ex36.py”, line 13, in start
stepForward()
File “/Users/dngra_000/VSCode_github/LPTHW/2020-09-18, Ex36.py”, line 79, in stepForward
findWeapon()
File “/Users/dngra_000/VSCode_github/LPTHW/2020-09-18, Ex36.py”, line 91, in findWeapon
pokeSnakes()
File “/Users/dngra_000/VSCode_github/LPTHW/2020-09-18, Ex36.py”, line 150, in pokeSnakes
attempts, “is not an acceptable value. Please enter an integer value.”)
UnboundLocalError: local variable ‘attempts’ referenced before assignment

Easy. You get your input for choice at the top of the function, but you have to do it inside the try/except. Simply move it under the try: line and it should work. You could also look at how the while loop might be in the wrong place too. You want to loop constantly until they exit, and if they do a value error you want to try again, so the try/except for the ValueError should be inside the while loop.

@zedshaw, I am still getting the same error. I updated the GitHub Gist with the changes you suggested for review and further comment…

I believe the problem is that in this line

attempts = int(input(">"))

the value error happens inside the type conversion and at that point the variable attempts is not defined yet. So you get sent to your exception handler and try to print out the non-existing attempts, which results in the unbound local error inside this except block.

One solution would be to define attempts earlier and then just assign to it when you parse the input.

@florian

Thank you very much!! That did it.

Now the follow up question…why? Apparently I cannot declare a variable as part of an if statement. I guess this is just something to know going forward. I REALLY appreciate your time and insight.

1 Like

This has nothing to do with the fact that you define attempts inside an if statement. (Python is rather lenient in how it handles scope with regard to conditional blocks.) The problem is that attempts is not defined at all whenever the evaluation of int(input(">")) causes an error.

@florian…about variable definition, that’s what I thought. For now, I will mash the I believe button, but one of the things I tried previously was this:

attempts = int(input("How many times do you think you need to poke the snake in order to kill it?\n>"))

I thought this would assign the variable for me and remains unclear why this does not work.

The only way I have gotten it to work is to do what you said. Again thanks so much for the assist.

In programming it’s often important to be aware of the order in which things are happening. Your error situation can be condensed to this:

try:
    attempts = int(input(">"))
except:
    print("An error occured: attempts =", attempts)

Now consider just the second line. There are a couple of things happening in this order:

  1. Print the prompt and get a user input.
  2. Convert that input to an integer.
  3. Assign that integer to the variable attempts.

What happens if the user input is foo in step 1? – An error occurs because "foo" can’t be converted to an int.

When does the error occur? – In step 2. Before step 3.

What is the value of attempts at the exact point in time where the error happens? – This question makes no sense because there is no variable called attempts yet. The error has happened before it was defined!

Now you are jumping to the error handler and there you say “Hey, tell me what happened, and while you’re at it, show me what attempts is so I can see why it happened.” But attempts doesn’t exist. It was never created. That fires another error, ironically exactly in the line of code that is supposed to handle errors.

Does this help?

1 Like

I could not have asked for a better explanation! THANK YOU!

A free service run by Zed A. Shaw for learncodethehardway.org.