Python NameError, variable 'not defined' - python

the error it returns is:
NameError: name 'lives' is not defined
I know the code isn't as efficient as possible, this is one of my first projects, however whatever i try to do this error pops up, I've tried making a global for it but that didn't help. I would really appreciate some help with this, thanks!
import random
import time
def main():
global guess,rand_num
win = False
rand_num = 45
lives = 10
while lives > 0 and win == False:
guess = int(input("Guess a number!"))
compare()
print("Well done!")
time.sleep(3)
def compare():
global lives,win
if guess == rand_num:
print("You guessed correct!")
win = True
elif guess > rand_num:
print ("Guess lower!")
lives = lives - 1
else:
print ("Guess higher!")
lives = lives - 1
def repeat():
replay = input("would you like to play again? Y/N")
if replay == "Y":
print("enjoy!")
main()
elif replay == "N":
"Goodbye then, hope you enjoyed!"
time.sleep(3)
os._exit
else:
print("please enter Y or N")
repeat()
main()
repeat()
EDIT: putting global lives inside main() returns the error:
UnboundLocalError: local variable 'lives' referenced before assignment

You need to define the variable "lives" outside of the function main, then any function where you want to reference that global variable you say "global lives." When you are in a function and assign a value to a variable, it assumes it is in the local scope. using "global lives" tells that function to look to the global scope as the reference of lives.
import random
import time
lives = 10
win = False
guess = 0
rand_num = 45
def main():
global guess, rand_num, lives, win
win = False
rand_num = 45
lives = 10
while lives > 0 and win == False:
guess = int(input("Guess a number!"))
compare()
print("Well done!")
time.sleep(3)
def compare():
global guess, rand_num, lives, win
if guess == rand_num:
print("You guessed correct!")
win = True
elif guess > rand_num:
print ("Guess lower!")
lives = lives - 1
else:
print ("Guess higher!")
lives = lives - 1
def repeat():
replay = input("would you like to play again? Y/N")
if replay == "Y":
print("enjoy!")
main()
elif replay == "N":
"Goodbye then, hope you enjoyed!"
time.sleep(3)
os._exit
else:
print("please enter Y or N")
repeat()
main()
repeat()

You didn't declare lives to be global inside main(), so it is local to that function.
def main():
global guess, rand_num, lives
...

When you declare it inside function they are only available in that function scope, so declare global variables outside functions and code will work fine.
import random
import time
guess = None
random_num = None
lives = 3
win = False
def main():
global guess,rand_num
win = False
rand_num = 45
lives = 10
while lives > 0 and win == False:
guess = int(input("Guess a number!"))
compare()
print("Well done!")
time.sleep(3)
def compare():
global lives,win
if guess == rand_num:
print("You guessed correct!")
win = True
elif guess > rand_num:
print ("Guess lower!")
lives = lives - 1
else:
print ("Guess higher!")
lives = lives - 1
def repeat():
replay = input("would you like to play again? Y/N")
if replay == "Y":
print("enjoy!")
main()
elif replay == "N":
"Goodbye then, hope you enjoyed!"
time.sleep(3)
os._exit
else:
print("please enter Y or N")
repeat()
main()
repeat()
And now this works fine. For more info about gloval vs local variables you can read: http://www.python-course.eu/global_vs_local_variables.php

Related

Boolean value outside the function doesn't get changed

I'm learning Python and can't get my bool to change from "True" to "False" in my replay function. I've scoured StackOverflow, but can't find an answer.
I've tried canPlay = False and canPlay = not canPlay. But that's not working.
Any suggestions?
import random
from random import randint
# welcome message
print("Welcome to the number guessing game!")
# get the random seed
seedValue = input("Enter random seed: ")
random.seed(seedValue)
canPlay = True
def play():
randomNumber = randint(1, 100)
numberOfGuesses = 1
guessValue = ""
while guessValue != randomNumber:
# prompt the user for a guess
guessValue = int(input("\nPlease enter a guess: "))
# provide higher/lower hint
if guessValue == randomNumber:
print(f"Congratulations. You guessed it!\nIt took you {numberOfGuesses} guesses.")
elif guessValue > randomNumber:
print("Lower")
else:
print("Higher")
# increment the count
numberOfGuesses += 1
def replay():
playAgain = input("\nWould you like to play again (yes/no)? ")
if playAgain == "no":
canPlay = False # not changing values
canPlay = not canPlay # this doesn't work either
print("Thank you. Goodbye.")
while canPlay == True:
play()
replay()
with a global keyword inside the reply() function, you can change the value of the canPlay variable in the global namespace which is then needed in the condition of while statement while canPlay == True::
def replay():
global canPlay # <------------------ Here
playAgain = input("\nWould you like to play again (yes/no)? ")
if playAgain == "no":
canPlay = False # not changing values
canPlay = not canPlay # this doesn't work either
print("Thank you. Goodbye.")
If you do not insert that line, canPlay would be a local variable for reply() function, so it can't change global variables or be accessed by other statements outside the reply function.

Python HangMan game using functions

So I'm trying to make a little hangman game in Python. I've managed it already, but I've seen lots of other people using functions to achieve this. Here's my code without using function:
from hangman_words import word_list
import random
def select_word():
return random.choice(word_list)
hidden_word = select_word()
char_lines = "_" * len(hidden_word)
guessed_letters = []
Lives = 8
game_start = input("Would you like to play HangMan? (Y/N)\n")
if game_start.upper() == "Y":
prompt_user = True
elif game_start.upper() == "N":
print("*Sad Python Noises*")
prompt_user = False
else:
print("You to say 'Yes'(Y) or 'No'(N)")
while (Lives > 0 and prompt_user == True):
user_input = input("Choose a letter!\n\n")
user_input = user_input.upper()
if user_input.upper() in guessed_letters:
print("\nYou have already guessed that letter. Choose something else!")
elif hidden_word.count(user_input) > 0:
for i, L in enumerate(hidden_word):
if L == user_input:
char_lines = char_lines[:i] + hidden_word[i] + char_lines[i+1:]
print("\nCorrect!")
print(char_lines)
else:
guessed_letters.append(user_input)
print("\nNope, that letter isn't in the word. Try again!")
Lives -= 1
if char_lines == hidden_word:
print("Well done! You won the game!")
print(f"You had {Lives} lives remaining and your incorrect guesses were:")
print(guessed_letters)
exit()
print(f"Lives remaining: {Lives}")
print(f"Incorrect guessed letters: {guessed_letters}")
print(char_lines)
if (Lives == 0 and prompt_user == True):
print("You have ran out of lives and lost the game!.....you suck")
if prompt_user == False:
print("Please play with me")
My current code for the version using functions is like this:
from hangman_words import word_list
import random
def select_word():
global blanks
selected_word = random.choice(word_list)
blanks = "_" * len(selected_word)
return selected_word, blanks
def game_setup():
global lives
global guessed_letters
global hidden_word
lives = 20
guessed_letters = []
hidden_word = select_word()
return lives, guessed_letters, hidden_word
def play_option():
game_start = (input("Would you like to play HangMan? (Y/N)\n")).upper()
if game_start == "Y":
global prompt_user
prompt_user = True
game_setup()
return prompt_user
elif game_start == "N":
print("*Sad Python Noises*")
exit()
else:
print("You need to say 'Yes'(Y) or 'No'(N)")
def user_input_check(user_input):
if type(user_input) != str: # [Want to check if unput is of tpye Str]
print("Please input letter values!")
elif user_input != 1:
print("Please only input single letters! (e.g. F)")
else:
pass
def game_board(user_input, hidden_word, guessed_letters, blanks, lives):
if user_input in guessed_letters:
print("You have already guessed that letter. Choose something else!")
elif hidden_word.count(user_input) > 0:
for i, L in enumerate(hidden_word):
if L == user_input:
blanks = blanks[:i] + hidden_word[i] + blanks[i+1:]
print("Correct!")
print(blanks)
else:
guessed_letters.append(user_input)
print("Nope, that letter isn't in the word. Try again!")
lives -= 1
print(f"Lives remaining: {lives}")
print(f"Incorrect guessed letters: {guessed_letters}")
print(blanks)
return
def win_check(blanks, hidden_word, lives, guessed_letters):
if blanks == hidden_word:
print("Well done! You won the game!")
print(f"You had {lives} lives remaining and your incorrect guesses were:")
print(guessed_letters)
exit()
def lives_check(lives, prompt_user):
if (lives == 0 and prompt_user == True):
print("You have ran out of lives and lost the game!.....you suck")
exit()
play_option()
while (lives > 0 and prompt_user == True):
user_input = (input("Choose a letter!\n\n")).upper()
user_input_check(user_input)
game_board(user_input, hidden_word, guessed_letters, blanks, lives)
win_check(blanks, hidden_word, lives, guessed_letters)
lives_check(lives, prompt_user)
I think I should be using classes instead of functions really, but I'd like to get it work with functions first, then try adapting it to work with classes. If I'm using functions, how does return actually work? Does returning variable names put those variables within the global name-space? Or does return only work when you assign the returned value to a global name-space variable? Like this:
def add_one(a):
return a + 1
b = add_one(3) # b = 4
You're correct, return works by setting the function to be equal to whatever you return it as.

Hangman Revealing doubles not working?

so i have this hangman code... again, thanks in advance, and it reveals the words one by one and that works fine, but when there is multiple words like two l's in hello and two p's in apple it only reveals one not two. i don't know why this is and I've done some google greasing and what came up was enumerating but I've tried that to no avail.
This is the code:
def hangman():
global fullWordList
fullWordList = []
global wrongnums
wrongnums =[]
print("What is the word to be guessed?")
print("Words means that there are no numbers")
global guessnum
guessnum=input('>')
fullWord = guessnum
for line in fullWord:
for c in line:
fullWordList.append(c)
print (fullWordList)
print("how many chances?")
global chances
chances=int(input('>'))
print("game in beginning")
# sleep(5)
# print ("\n" * 100)
global blanks
blanks = '_ ' * len(guessnum)
print()
print(blanks)
guessing()
def guessing():
global fullWordList
global chances
print("guess a letter")
global guess
guess=input('>')
guessloop()
def guessloop():
global chances
if guess in fullWordList:
if guess in fullWordList:
letterIndex = guessnum.index(guess)
global blanks
blanks = blanks[:letterIndex*2] + guess + blanks[letterIndex*2+1:]
fullWordList.remove(guess);
global lenWord
lenWord = len(fullWordList)
print (fullWordList)
print (lenWord)
print ("Guess is correct!")
if guess in fullWordList:
guessloop()
else:
wrongnums.append(guess)
print (wrongnums)
if lenWord == 0:
print()
print("Word: ",blanks)
win()
else:
print()
print("Word: ",blanks)
guessing()
else:
if lenWord == 0:
win()
else:
print()
print("Word: ",blanks)
guessing()
elif guess in wrongnums:
print("You've guessed that!")
guessing()
else:
chances -=1
wrongnums.append(guess)
print (wrongnums)
print ("Guess is wrong! ", chances, " more failed attempts allowed.")
if chances == 0:
gameOver()
else:
guessing()
def check():
print()
print("Word: ",newBlanks)
guessing2()
def win():
print("You guessed it well done")
print("Would you like to play again?")
PG = input(">")
if PG == "yes" or PG == "Y" or PG == "Yes" or PG == "yea" or PG == "Yea":
print ("Game will restart in 5 seconds")
sleep(5)
hangman()
else:
print("Going to main menu in 5 seconds")
sleep(5)
start()
def gameOver():
print("You ran out of guesses, sorry, you lose")
print("Would you like to play again?")
PG = input(">")
if PG == "yes" or PG == "Y" or PG == "Yes" or PG == "yea" or PG == "Yea":
print ("Game will restart in 5 seconds")
sleep(5)
hangman()
else:
print("Going to main menu in 5 seconds")
sleep(5)
start()
Now i have also got a code:
def hangman():
global fullWordList
fullWordList = []
global wrongnums
wrongnums =[]
print("What is the word to be guessed?")
print("Words means that there are no numbers")
global guessnum
guessnum=input('>')
fullWord = guessnum
for line in fullWord:
for c in line:
fullWordList.append(c)
print (fullWordList)
print("how many chances?")
global chances
chances=int(input('>'))
print("game in beginning")
# sleep(5)
# print ("\n" * 100)
global blanks
blanks = '_ ' * len(guessnum)
print()
print(blanks)
guessing()
def guessing():
global fullWordList
global chances
print("guess a letter")
global guess
guess=input('>')
guessloop()
def guessloop():
global chances
if guess in fullWordList:
if guess in fullWordList:
letterIndex = guessnum.index(guess)
global blanks
guesses = (guessnum)
guesses = blanks[letterIndex]
blanks[letterIndex] = guess
fullWordList.remove(guess);
global lenWord
lenWord = len(fullWordList)
print (fullWordList)
print (lenWord)
print ("Guess is correct!")
if guess in fullWordList:
guessloop()
else:
wrongnums.append(guess)
print (wrongnums)
if lenWord == 0:
print()
print("Word: ",blanks)
win()
else:
print()
print("Word: ",blanks)
guessing()
else:
if lenWord == 0:
win()
else:
print()
print("Word: ",blanks)
guessing()
elif guess in wrongnums:
print("You've guessed that!")
guessing()
else:
chances -=1
wrongnums.append(guess)
print (wrongnums)
print ("Guess is wrong! ", chances, " more failed attempts allowed.")
if chances == 0:
gameOver()
else:
guessing()
def check():
print()
print("Word: ",newBlanks)
guessing2()
def win():
print("You guessed it well done")
print("Would you like to play again?")
PG = input(">")
if PG == "yes" or PG == "Y" or PG == "Yes" or PG == "yea" or PG == "Yea":
print ("Game will restart in 5 seconds")
sleep(5)
hangman()
else:
print("Going to main menu in 5 seconds")
sleep(5)
start()
def gameOver():
print("You ran out of guesses, sorry, you lose")
print("Would you like to play again?")
PG = input(">")
if PG == "yes" or PG == "Y" or PG == "Yes" or PG == "yea" or PG == "Yea":
print ("Game will restart in 5 seconds")
sleep(5)
hangman()
else:
print("Going to main menu in 5 seconds")
sleep(5)
start()
hangman()
This is what i edited it to and got this error:
blanks[letterIndex] = guess
TypeError: 'str' object does not support item assignment
I really am stumped, i hope this is enough data to help.
I've tried to change your code as little as possible, but I need to get code working fully to work out all the bugs, so I'm sharing what I've done with your code.
You've identified two problems - one is that as soon as there's a single match, the program moves on to the next guess, without checking for multiple positive hits.
The second problem is that the error you were getting is that 'blanks' was a string and you were trying to change a character at a specific index (line 43 of the second code sample: blanks[letterIndex] = guess). Strings are immutable, so the attempt to alter a character in place isn't possible. There's more than one way around this - one that I went with (below) is to set 'blanks' up as a list, allowing you to change any of the elements of the list (since lists are mutable). To display the list to the user, try ''.join(blanks) to make a presentable string out of the list.
I made a few changes to the code (again, trying to honour your structure and style) to come up with something that works:
removed the variable guessnum (you only need fullWord)
converted 'blanks' from being a string to a list - now you can make changes as guesses are correct. This directly relates to the question you ask.
simplified the flow of your if ... else statement in the guessing function, going through the three possible outcomes: correct guess, repeated guess, and incorrect guess. Within those are some sub-checks (if correct, is it a win? if incorrect, is it a loss?) I included some comments so you can see what changes were made and where.
when a guess is correct, 'blanks' is updated accordingly for EVERY match that occurs. (And blanks is displayed by using ''.join(blanks) to make a string of the elements.) When a guess is correct, fullWordList is also updated for EVERY match that occurs - the letter is replaced with '-'. So now a check for a win is whether the fullWordList contains only '-' elements.
There's still no catching of exceptions, but what is here works with a word like 'apple' - trying to win, lose, and repeat guesses.
Hope it helps - let me know if there's something that isn't clear. I didn't want to just re-write your code, but wanted to walk through one approach to the problem.
There are other improvements that can be made, but this at least clears your hurdles.
THE CODE
def hangman():
global fullWordList
fullWordList = []
global wrongnums
wrongnums =[]
print("What is the word to be guessed?")
print("Words means that there are no numbers")
# no need to set two variables for same thing (fullWord and guessnum)
global fullWord
fullWord=input('>')
for line in fullWord:
for c in line:
fullWordList.append(c)
print (fullWordList)
print("how many chances?")
global chances
chances=int(input('>'))
print("game in beginning")
# sleep(5)
# print ("\n" * 100)
global blanks
# treat blanks as a list rather than string (list is mutable)
blanks = ['- '] * len(fullWord)
print()
print(blanks)
guessing()
def guessing():
global fullWordList
global chances
print("guess a letter")
global guess
guess=input('>')
guessloop()
def guessloop():
global chances, guess, blanks, blankList, fullWordList
# three possibilities: correct guess, repeated guess, incorrect guess
# 1. correct guess
if guess in fullWordList:
#generates list of indices of ALL matches
# stackoverflow.com/questions/9542738/python-find-in-list
letterIndex = [i for i, x in enumerate(fullWordList) if x == guess]
print letterIndex
for idx in letterIndex:
# change elements in blank list if there's a match
blanks[idx] = (guess +' ')
# update fullWordList to replace correct guesses with '-'
fullWordList[idx] = ('-')
# display the updated blank list as a string
print ''.join(blanks)
# replace all occurrences of guess from fullWordList with '-'
print ("Guess is correct!")
# add guess to wrongnums to record it as 'already guessed'
wrongnums.append(guess)
# check if it's a winning guess
if fullWordList == ['-']*len(fullWord):
print()
# display updated list as string
print("Word: ", ''.join(blanks))
win()
# 2. repeated guess
elif guess in wrongnums:
# don't add to wrongnums if already guessed (letter is already in there)
if guess in wrongnums:
print("You've guessed that!")
print ''.join(blanks)
# 3. incorrect guess
else:
chances -=1
wrongnums.append(guess)
print (wrongnums)
print ("Guess is wrong! ", chances, " more failed attempts allowed.")
print ''.join(blanks)
if chances == 0:
gameOver()
guessing()
def check():
print()
print("Word: ",newBlanks)
guessing2()
def win():
print("You guessed it well done")
print("Would you like to play again?")
PG = input(">")
if PG == "yes" or PG == "Y" or PG == "Yes" or PG == "yea" or PG == "Yea":
print ("Game will restart in 5 seconds")
sleep(5)
hangman()
else:
print("Going to main menu in 5 seconds")
sleep(5)
start()
def gameOver():
print("You ran out of guesses, sorry, you lose")
print("Would you like to play again?")
PG = input(">")
if PG == "yes" or PG == "Y" or PG == "Yes" or PG == "yea" or PG == "Yea":
print ("Game will restart in 5 seconds")
sleep(5)
hangman()
else:
print("Going to main menu in 5 seconds")
sleep(5)
start()
hangman()

NameError: guesses not defined

I'm just starting out on python and I'm wondering exactly why my variable guesses is not defined. I feel as if it's a indentation issue but once I change the indentation I usually come upon a syntax error any help understanding this issue would be greatly appreciated.
import random
def game():
guesses = []
secret_num = random.randint(1, 10)
while len(guesses) < 5:
try:
guess = int(input("Guess a number between 1 and 10 "))
except ValueError:
print("{} isn't a number!".format(guess))
else:
if guess == secret_num:
print("You got it! My number was {}".format(secret_num))
break
elif guess < secret_num:
print("My number is higher than {}".format(guess))
else:
print("My number is lower tha {}".format(guess))
guesses.append(guess)
else:
print("You didn't get it my secret number was {}".format(secret_num))
play_again = input("Do you want to play again? Y/N")
if play_again.lower() != 'n':
game()
else:
print("Bye thanks for playing!")
This doesn't throw any errors on my computer. Note you'll have to call the game() function if you want to actually run the code.
import random
def game():
guesses = []
secret_num = random.randint(1, 10)
while len(guesses) < 5:
try:
guess = int(input("Guess a number between 1 and 10 "))
except ValueError:
print("{} isn't a number!".format(guess))
else:
if guess == secret_num:
print("You got it! My number was {}".format(secret_num))
break
elif guess < secret_num:
print("My number is higher than {}".format(guess))
else:
print("My number is lower tha {}".format(guess))
guesses.append(guess)
else:
print("You didn't get it my secret number was {}".format(secret_num))
play_again = input("Do you want to play again? Y/N")
if play_again.lower() != 'n':
game()
else:
print("Bye thanks for playing!")
game() # to run the code

Could This Python Program Be Simplified Or Better Written?

Okay so I have been learning quite a bit of Python over the past few days, two or three, and I decided to take my knowledge and create something simple, but sort of entertaining, so I created a Guessing Game.
After about 30 minutes of creating this program and getting it to work 100% I was wondering if there was anything I could have done better, etc. I want to make sure I learn from any mistakes so I appreciate it!
So here is the code:
import random
def guessingGame():
randomNumber = random.randrange(1, 10)
yourGuess = int(input("Take A Guess, Numbers 1 Through 10: "))
while yourGuess != randomNumber:
print("DOH! You Did Not Guess Right, TRY AGAIN")
yourGuess = int(input("Take A Guess, Numbers 1 Through 10: "))
else:
if yourGuess == randomNumber:
print("Congrats You Beat The Guess Game!")
playGame = input("Would You Like To Play The Guessing Game (Y/N): ")
if playGame == "Y" or playGame == "y":
print("Okay Lets Play!")
guessingGame()
elif playGame == "N" or playGame == "n":
print("Okay Thanks Anyways!")
break
Thanks Again!
Instead of
if playGame == "Y" or playGame == "y":
print("Okay Lets Play!")
guessingGame()
I kind of like
if playGame.lower() == "y":
# ...
I even better like:
def quit():
print("Okay Thanks Anyways!")
actions = {"y": guessingGame}
actions.get(playGame.lower(), quit)()
from random import randint
def getInt(prompt):
while True:
try:
return int(input(prompt))
except ValueError:
print("That's no integer!")
def play():
secret = randint(1,10)
while True:
guess = getInt("Take a guess (1-10):")
if guess==secret:
print("Congrats, you beat The Guess Game!")
break
else:
print("D'oh! You guessed wrong. Try again!")
def main():
while True:
inp = input("Would you like to play The Guessing Game? (Y/N)").lower()
if inp=="y":
print("Okay, let's play!")
play()
elif inp=="n":
print("Alright. Thanks anyways!")
break
else:
print("You don't follow directions too good, eh?")
if __name__=="__main__":
main()
A few things I noticed:
You should handle the case where user tries to guess something that doesn't look like a number, say the letter 'a' for example.
Python style guide says to prefer lower_with_underscores over CamelCase for variable names.
The line yourGuess = int(input("Take A Guess, Numbers 1 Through 10: ")) is unnecessarily duplicated, see below for one possible way to refactor that part.
General cleanup:
import random
def guessing_game():
random_number = random.randint(1, 10)
assert random_number in range(1, 11)
your_guess = None
while your_guess != random_number:
try:
your_guess = int(input("Take A Guess, Numbers 1 Through 10: "))
except ValueError:
print("That wasn't a number")
continue
if your_guess != random_number:
print("DOH! You Did Not Guess Right, TRY AGAIN")
else:
print("Congrats You Beat The Guess Game!")
break
play_game = None
while play_game not in ['y', 'n']:
play_game = input("Would You Like To Play The Guessing Game (Y/N): ").lower()
if play_game == "y":
print("Okay Lets Play!")
guessing_game()
else:
assert play_game == "n":
print("Okay Thanks Anyways!")
I imagine you could use a "break" statement inside a while loop, as in
import random
def guessingGame():
randomNumber = random.randrange(1, 10)
while True:
yourGuess = input("Take A Guess, Numbers 1 Through 10: ")
if !yourGuess.isdigit():
print ("That's not a number!")
elif int(yourGuess) not in range(1,10):
print("I said between 1 and 10!")
elif int(yourGuess) != randomNumber:
print("DOH! You Did Not Guess Right, TRY AGAIN")
else:
break
print("Congrats You Beat The Guess Game!")
playGame = input("Would You Like To Play The Guessing Game (Y/N): ")
if playGame.lower() == "y":
print("Okay Lets Play!")
guessingGame()
elif playGame.lower() == "n":
print("Okay Thanks Anyways!")
break
Read the Pep 8 documentation on naming conventions and Python's style of coding.
import random
def guessing_game(x=1, y=10):
"""
A simple number guessing game.
"""
while int(input("Take A Guess, Numbers 1 Through 10: ")) \
!= random.randrange(x, y):
print("DOH! You Did Not Guess Right, TRY AGAIN")
print("Congrats You Beat The Guess Game!")
if input("Would You Like To Play The Guessing Game (Y/N): ") == 'Y':
print("Okay Lets Play!")
guessing_game()
else:
print("Okay Thanks Anyways!")
if __name__ == '__main__':
guessing_game(1, 10)

Categories