Python hangman game loop ending problems - python

The problem I have is that the game doesn't end because the while loop doesn't end even is the function is_word_guessed() returns True.
The rules for the game are:
You have 6 guesses to guess the word. For testing purposes, I am currently using a secret_word='apple'. I'm not adding the code for selecting a random word, it works fine.
If you guess right, you don't lose any guesses.
If you guess wrong, and the guess is a vocal, you lose 2 guesses.
if you guess wrong, and the guess is a consonant, you lose 1 guess.
If you guess a word you already have guessed, or guess a word that is not a letter, or you guess two or more words, you lose 1 warning. You start with 3 warnings, and if you lose them all, you lose one guess. The final score is the number of unique letters on the secret_word*number of guesses_remaining.
import string
secret_word='apple'
def is_word_guessed(secret_word, letters_guessed):
if secret_word == letters_guessed:
return True
else:
return False
def get_guessed_word(secret_word, letters_guessed):
b=''
for char in secret_word:
if char in letters_guessed:
b=b+char
else:
b=b+"_ "
return b
def get_available_letters(letters_guessed):
s=''
letters=string.ascii_lowercase
for char in letters:
if char not in letters_guessed:
s=s+char
return s
def get_unique_letters(secret_word):
unique=''
for char in secret_word:
if char not in unique:
unique+=char
return len(unique)
print (get_unique_letters(secret_word))
def hangman(secret_word):
print("Welcome to the game of hangman!")
print ("I am thinking a word that is", str(len(secret_word)), "long.")
warnings_remaining=3
guesses_remaining=6
letters_guessed=''
while not is_word_guessed(secret_word, letters_guessed):
# checking that user has guesses left
if guesses_remaining==0:
break
else:
# checking if we have to remove a guess
if warnings_remaining==0:
guesses_remaining-=1
warnings_remaining=3
print ("---------")
print("You have", str(guesses_remaining), "guesses left.")
print("Available letters:", get_available_letters(letters_guessed))
user_guess=input("Please guess a letter:")
# checking that the input is a valid letter
if len(user_guess) != 1 or user_guess not in string.ascii_letters:
warnings_remaining-=1
print("Oops! That is not a valid letter!", "You have", warnings_remaining, "warnings left.")
elif user_guess in letters_guessed:
warnings_remaining-=1
print("Oops! That letter has alredy been guessed. You now have", warnings_remaining, "warnings left.")
# checking if the guess is right or wrong
elif user_guess in secret_word:
letters_guessed+=user_guess
print ("Good guess:", get_guessed_word(secret_word, letters_guessed))
else:
letters_guessed+=user_guess
print ("Oops! That letter is not in my word:", get_guessed_word(secret_word, letters_guessed))
if user_guess in 'aeiou':
guesses_remaining-=2
else:
guesses_remaining-=1
if guesses_remaining==0:
print("Sorry, you ran out of guesses. The word was:", secret_word)
else:
print("Congratulations, you won!")
print("Your total score for this game is:", get_unique_letters(secret_word)*guesses_remaining)
hangman(secret_word)

You're not accounting for double letters in your letters_guessed variable. A quick fix would be to compare the letters only in your is_word_guessed() function by converting them to sets:
def is_word_guessed(secret_word, letters_guessed):
if set(secret_word) == set(letters_guessed):
return True
else:
return False

Related

How to stop Hangman python program when the user has guessed the correct words?

I'm making a simple hangman program using while-loops. The program that I've written works, but I don't know how to make it stop once the user has guessed the correct letters.
Here is what I have so far:
word = input("What's the secret word? ")
lives = int(input("Amount of lives? "))
while True:
guess = input("Guess a letter: ")
if guess in word:
print("Correct, the letter is in the secret word.")
else:
lives -= 1
print(f"The letter {guess} is not in the secret word.")
if lives > 0:
print(f"You have {lives} lives left, try again.")
else:
print("You have no lives left.")
break
The simplest way I see is to add some counter of correctly guessed letters, so you can reason when the word itself is guessed correctly.
guessed_so_far = 0
already_guessed = []
while True:
guess = input("Guess a letter: ")
if guess in word and guess not in already_guessed:
print("Correct, the letter is in the secret word.")
guessed_so_far += 1
already_guessed.append(guess)
if guessed_so_far == len(set(word)):
break
As Joshua correctly suggested, you have to compare with len(set(word))
Your guess = input(...) code has a subtle bug: what if the user inputs a len(guess) > 1 string? Ignoring that possibility for a moment:
word = input("What's the secret word? ")
letters = set(word)
...
# if the guess (assumed single character) is in the set of letters
if guess in letters:
print("Correct, the letter is in the secret word.")
# reduce the set of letters remaining by the current guess
letters = letters - set(guess)
# if there aren't any letters left to guess
if len(letters) == 0:
print("Congrats! You won!")
break

cant figure out how to loop for hangman in python

I am trying to loop over my hangman project but cannot seem to figure out a way without creating an infinite loop. I want to avoid having to ask for user input in multiple places in my guess function and be able to put it in in one place. I feel like I have all the logic down, I would just need to figure out the looping portion. How can I solve this?
from random import choice
print('Welcome to Hangman!!!, Guess the secret word ')
user_guess = input('What is your first guess at the secret word? ')
org_word = choice(['cat','dog','mug','plate'])
word = set(org_word)
already_guessed = ''
chances = 10
def hang_man():
guess()
check_win()
def guess():
global chances
global correct_letters
global already_guessed
#check for valid input
if len(user_guess) > 1 or user_guess.isnumeric():
print('you entered an invalid input and you lost a guess')
chances -= 1
if chances == 0:
print('Sorry you are out of guesses, You Lost :(')
else:
print(f'you now have {chances} guesses left')
#check if letter was already guessed
elif user_guess in already_guessed:
print('you already entered that letter and you lost a guess')
chances -=1
#incorrect guess
elif user_guess not in word:
print('That guess was not in the word and you lost a guess')
chances -= 1
already_guessed += user_guess
if chances == 0:
print('Sorry you are out of guesses, You Lost :(')
else:
print(f'you now have {chances} guesses left')
#correct guess
elif len(user_guess) == 1 and user_guess in word:
print(f'Great, your guess of {user_guess} was in the word')
word.remove(user_guess)
def check_win():
if len(word) == 0 :
print(f'Congrats, you guessed the correct word {org_word}')
hang_man()
You could amend check_win() to return true when guessed correctly:
def check_win():
if len(word) == 0 :
print(f'Congrats, you guessed the correct word {org_word}')
return True
Then while the word hasn't been guessed:
def hang_man():
while not check_win():
guess()
Edit: Thanks for the spot Pranav Hosangadi.

Loop wont run as expected

I am just learning python, and I am trying to make hangman, but I am having two problems. First, when you enter the same letter twice, it follows two of my conditions, and the prompt for both gets printed twice. For example:
> C:\Users\Me\PycharmProjects\Python\venv\Scripts\python.exe C:/Users/Me/PycharmProjects/Python/Hangman.py
shark
There are 5 letters in this word.
You have 3 wrong guesses left.
Guess a letter.
s
Good guess. That letter was in the word.
You have 3 wrong guesses left.
Guess a letter.
s
*You already entered that letter.
Good guess. That letter was in the word.*
You have 3 wrong guesses left.
Guess a letter.
Another issue I am having is making the win condition. If the correct_guesses reaches zero, it should end the game, but it doesnt actually work, as it always ends the game after 4 correct inputs.
import random
my_list = ["hangman", "dragon", "tiger", "octopus", "shark", "money", "school", "stadium", "biker", "whale", "sphinx"]
my_list2 = []
word = random.choice(my_list)
print(word) #Delete later
print("There are", len(word), "letters in this word.")
def start():
guesses_left = 3
correct_guesses = len(set(word))
while guesses_left > -1:
print("You have", str(guesses_left), "wrong guesses left.\n")
guess = input("Guess a letter. \n").lower()
if len(guess) != 1:
print("Please enter a single letter.")
continue
if guess in my_list2:
print("You already entered that letter.")
continue
if guess not in my_list2:
my_list2.append(guess)
if guess in word:
print("Good guess. That letter was in the word.")
correct_guesses -= 1
continue
if guess not in word:
print("That letter isn't in the word.")
guesses_left -= 1
continue
if correct_guesses == 0:
print("Congratulations! You won the game.")
break
if guesses_left <= 1:
print("Sorry, you lost. Play again.")
start()
print(my_list2) #Delete later
The second time 's' is entered it still matches:
if guess in word:
print("Good guess. That letter was in the word.")
correct_guesses -= 1
How about:
if guess in word and guess not in my_list2:
print("Good guess. That letter was in the word.")
correct_guesses -= 1
Or you could change the overall structure to:
if
...
elif
...
else
...
I see you've edited the code signigicantly based on the other answer. Your last problem of it not stopping to say that you've won is because the code never reaches the win condition, as if the entered letter is correct or not, it will hit a continue before you test for correct_guesses == 0. You can fix that by simply moving the test to the start of the loop instead of the end.
def start():
guesses_left = 3
correct_guesses = len(set(word))
while guesses_left > -1:
if correct_guesses == 0: #
print("Congratulations! You won the game.") # Move it here
break #
print("You have", str(guesses_left), "wrong guesses left.\n")
guess = input("Guess a letter. \n").lower()
if len(guess) != 1:
print("Please enter a single letter.")
continue
if guess in my_list2:
print("You already entered that letter.")
continue
if guess not in my_list2:
my_list2.append(guess)
if guess in word:
print("Good guess. That letter was in the word.")
correct_guesses -= 1
continue
if guess not in word:
print("That letter isn't in the word.")
guesses_left -= 1
continue
if guesses_left <= 1:
print("Sorry, you lost. Play again.")

How terminate this loop after a a given number of attempts?

For the most part it seems to be working, but not how I'm trying to get it to work. When I run it I am allowed unlimited tries to guess every single letter in the word until I spell out the word.
But that's not what I am going for, I'm trying to give the users 5 guesses with single letters if the letter is in the word then it will tell them "Yes", there is a(n) (users guess) in my word, but if the letter is not in my word then it will tell them "No", there is not a(n) (users guess) in my word.
After 5 attempt's at guessing different letters I want them to have to guess the full word but I can't figure out how.
This is what I have now:
import random
def get_word():
words = ['cat', 'dog', 'man', 'fox', 'jar']
return random.choice(words).upper()
def check(word,guesses,guess):
status = ''
matches = 0
for letter in word:
if letter in guesses:
status += letter
else:
status += '*'
if letter == guess:
matches += 1
count = 0
limit = 5
if matches > 1:
print ('Yes! there is a(n)',guess,' in my word.')
guesses += guess
elif matches ==1:
print ('Yes! there is a(n)',guess,' in my word.')
guesses += guess
while count > limit:
input('What do you think my word is')
else:
print('No, there is not a(n)',guess,' in my word.')
guesses += guess
while count > limit:
input('What do you think my word is')
return status
def main():
word = get_word()
guesses = ""
guessed = False
print ('I am thinking of a 3 letter word with no repeating letters. You get five guesses of the letters in my word and then you have to guess the word.')
while not guessed:
text = 'Guess a letter in my word:'
guess = input(text)
guess = guess.upper()
count = 0
limit = 5
if guess in guesses:
print ('You already guessed "' + guess + '"')
elif len(guess) == len(word):
guesses += guess
if guess == word:
guessed = True
else:
print('No, there is not a(n) "' + guess + '"')
elif len(guess) == 1:
guesses += guess
result = check(word,guesses,guess)
if result == word:
guessed = True
else:
print (result)
else:
print ('Invalid entry.')
print ('Yes! you correctly guessed')
main()
For starters while not guessed: will continue until guessed is true -> the word was guessed. Next if you want there to be 5 guesses then an answer guess you want to do for i in range(0, 5): then run your guess logic replacing
if result == word:
guessed = True
with
if result == word:
guessed = true
break
to break out of the loop on a correct guess. Then to allow a guess afterwards, outside of the loop, check if already guessed and allow a guess if not.
Also as a side note you should check that they enter one character with something like
guess = input(text)
while len(guess) != 1:
guess = input(text)
I tried to mostly keep your original code and trail of thought. The main changes I made was getting rid of the check-function as I felt it didn't do anything too useful. I also changed the guessed-variable into a list, and utilized it's properties for your evaluations.
import random
def get_word():
words = ['cat', 'dog', 'man', 'fox', 'jar']
return random.choice(words).upper()
def main():
word = get_word()
guesses = []
guessed = False
print('I am thinking of a 3 letter word with no repeating letters.'
' You get five guesses of the letters in my word and then you have'
' to guess the word.\n')
while not guessed and len(guesses)<5:
text = 'Guess a letter in my word:\n'
guess = input(text)
guess = guess.upper()
if guess in guesses:
print ('You already guessed "', guess, '"\n')
elif len(guess) > 1:
guesses.append(guess)
if guess == word:
guessed = True
else:
print('No, ', guess, 'is not the word!\n')
elif len(guess) == 1:
guesses.append(guess)
if guess in word:
print('Yes there is a(n) ', guess, 'in the word!\n')
else:
print('No, there is not a(n)', guess, 'in the word!\n')
else:
print ('Invalid entry.\n')
if guessed:
print ('You correctly guessed the word!\n')
else:
correct_guesses = [guess for guess in guesses if guess in word]
print('Last chance, what is the full word? (HINT: You have'
'correctly guessed ', str(correct_guesses), ')"')
fword = input()
if fword.upper() == word:
print('You correctly guessed the word!\n')
else: print('Tough luck! You are out of chances! The correct'
'word was ', word, '\n')
main()
playing = True
while playing:
print('Would you like to play again?')
answ = input()
if answ.upper() == 'YES':
main()
else:
print('Thank you for playing.')
playing = False

How to end a program if the user guesses the secret phrase. My code runs in a never ending loop

So my problem with my code is that I can't figure out how I can check if the correct guesses equal the random Secret Phrase given. Thus I want to check if the user has guessed all the letter in the secret phrase. Basically, my code is running in a never ending loop. I have tried making if statements to check if the guesses from the user equals to the secret phrase but it will not work.
#Define a filename
filename = "puzzles.txt".lower()
#Imports
import random
import string
#Open the file and read
with open(filename) as f:
lines = f.readlines()
randomSecretPhrase = (random.choice(lines)) #Choose random phrase from file
#***Output secret word to screen test***
print(randomSecretPhrase)
#Initalize
correct = []
incorrect = []
count = 0
def game():
for i in randomSecretPhrase:
if i in correct:
print(i,end=' ')
#elif i != ' ':
elif i in string.ascii_letters:
print('_',end=' ')
else :
print(' ',end=' ')
print("\n\n")
print('Number of times guessed: ', count)
print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
def guessed_letters():
#Will check the user input to verify valid letter is entered
while True:
guess = input("Guess a letter: ").lower()
if guess in correct or guess in incorrect:
print("You have already guessed that letter. Please guess again.")
print(count)
elif guess.isnumeric():
print("Please enter only letters not numbers! Guess again.")
elif len(guess) > 1:
print("Please enter only one letter at a time. Please guess again.")
elif len(guess) == 0:
print("Please enter a letter.")
elif len(correct) == len(randomSecretPhrase):
print('You win')
else:
break
#Keep track of correct and incorrect guesses
if guess in randomSecretPhrase:
correct.append(guess)
print('~~~~~~~~~~~~~~~~~~~~~~~~')
print("You have guessed correctly!")
print('\n')
else:
print('~~~~~~~~~~~~~~~~~~~~~~~~')
incorrect.append(guess)
print("You have guessed incorrectly!")
print('\n')
#Main program
while True:
#Call game()
game()
#Call guessed_letters()
guessed_letters()
#Count how many times guesses
count += 1
check()
Output Example:
Number of times guessed: 6
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Guess a letter: w
~~~~~~~~~~~~~~~~~~~~~~~~
You have guessed correctly!
a c l e a n s w e e _
Number of times guessed: 7
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Guess a letter: p
~~~~~~~~~~~~~~~~~~~~~~~~
You have guessed correctly!
a c l e a n s w e e p
Number of times guessed: 8
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Guess a letter:
You mean something like this:
def check():
for i in randomSecretPhrase:
if i not in correct:
return False
return True
Your main program is this:
while True:
#Call game()
game()
#Call guessed_letters()
guessed_letters()
#Count how many times guesses
count += 1
check()
which, hopefully clearly, never ends.
You can give them a maximum number of tries like this:
while count < 3: #or other maximum
#Call game()
game()
#Call guessed_letters()
guessed_letters()
#Count how many times guesses
count += 1
check()
Of course, you would have to vary this for the length of the phrases.
In order to find out if they guessed ok, you need guessed_letters to tell you what its already figured out - if the guess is right or not.
You can changed this to return a value:
def guessed_letters():
#Will check the user input to verify valid letter is entered
while True:
guess = input("Guess a letter: ").lower()
if guess in correct or guess in incorrect:
print("You have already guessed that letter. Please guess again.")
print(count)
elif guess.isnumeric():
print("Please enter only letters not numbers! Guess again.")
elif len(guess) > 1:
print("Please enter only one letter at a time. Please guess again.")
elif len(guess) == 0:
print("Please enter a letter.")
elif len(correct) == len(randomSecretPhrase):
print('You win')
else:
break
#Keep track of correct and incorrect guesses
if guess in randomSecretPhrase:
correct.append(guess)
print('~~~~~~~~~~~~~~~~~~~~~~~~')
print("You have guessed correctly!")
print('\n')
return True
else:
print('~~~~~~~~~~~~~~~~~~~~~~~~')
incorrect.append(guess)
print("You have guessed incorrectly!")
print('\n')
return False
Now, you can check in the while loop:
while True:
#Call game()
game()
#Call guessed_letters()
if guessed_letters(): #<-- check the return code
break #<-- done if correct
#Count how many times guesses
count += 1
check()
In order to proclaim "You have won", you need to think about the stopping coniditon.
You will a list, correct with the guessed letters. and compare the length of this to the length of the randomSecretPhrase, which is a string.
Just on "sweep" the letters will be ['s', 'w', 'e', 'p'] when the guess is corrected.
You need to move the check after you collect the new guess and just check the letters are correct:
def guessed_letters():
#Will check the user input to verify valid letter is entered
while True:
guess = input("Guess a letter: ").lower()
if guess in correct or guess in incorrect:
print("You have already guessed that letter. Please guess again.")
print(count)
elif guess.isnumeric():
print("Please enter only letters not numbers! Guess again.")
elif len(guess) > 1:
print("Please enter only one letter at a time. Please guess again.")
elif len(guess) == 0:
print("Please enter a letter.")
else:
break
#Keep track of correct and incorrect guesses
if guess in randomSecretPhrase:
correct.append(guess)
print('~~~~~~~~~~~~~~~~~~~~~~~~')
print("You have guessed correctly!")
print('\n')
else:
print('~~~~~~~~~~~~~~~~~~~~~~~~')
incorrect.append(guess)
print("You have guessed incorrectly!")
print('\n')
if len(correct) == len(set(randomSecretPhrase)):
print('You win')
return True
return False
This will count unique letters in the randomSecretPhrase, and compare with the correct letters after adding the guess.
You will find it easier to make small functions and tests these one at a time.
For example, when you read the file lines you include the line ending so need to remove this:
with open(filename) as f:
lines = f.readlines()
phrase = (random.choice(lines)) #Choose random phrase from file
randomSecretPhrase = phrase.strip()
#***Output secret word to screen test***
print(randomSecretPhrase)

Categories

Resources