You had a really great start but had a few bugs here and there. I will go step by step and explain each one and finally provide you with the modified code. Btw, if I replace anything, I will comment it out so you can see what the difference is.
Variable Refactor
This is more a personal thing than a bug. When your user sends an input, you stored in a variable called guesses
. I just changed it to guess
because it makes more sense that way. Things like this don't affect your code but they do help make your code easier to read, and thus debug.
Fixing Jumbled Words*: Fixing letter_list
Whenever the player gets a letter right, you used the letter_list.insert(index, guess)
to update the letters in the game. However, you initialized your list as an empty array []
. When python uses the insert
function, it tries its best to insert the letter at the right position. However, if the array is too small, then it just enters the element at the end of the array.
Here's an example (using the word STRAWBERRY SHAKE):
letters_list = ["T","R"]
letters_list.append(0, "S") #letters_list = ["S", "T", "R"]
letters_list.append(11, "S") #letters_list = ["S", "T", "R", "S"] because there are only three elements
See how it just added the letter? The solution, is to fill your list with empty "_"
s and then replace the value when the user guesses correctly. Like this:
letter_list = ["_"]*len(guess_word) #Creates dashes for however many letters the word has
...
elif guess_word.__contains__(guess):
for letter in guess_word:
if letter == guess:
#Changed to update list value instead of insert
#letter_list.insert(index, guess)
letter_list[index] = guess
index += 1
Interestingly, the dashes also make the game look nicer. Here is how it looks now:
Enter a letter as a guess: B
['_', '_', 'C', '_', 'E', '_']
chances = 0
Fixing the Infinite Loop: Adding a Counter and Fixing the While conditions
Counter Variable
To loop the program you started with while answer.join(letter_list) != guess_word or chances < 5
.
The issue with the answer.join
part is that the order that a player enters the words might not be the same as the actual word itself. For example, if I guessed "JOCKEY"
in this order: ['O', 'J', 'K', 'C', 'Y', 'E']
, the program would compare the words "OJKCYE"
and "JOCKEY"
and claim that they are not the same.
To fix this, I added a counter variable called letters_left
that keeps track of how many correct letters we need to guess in order to get solve the puzzle. Every time the user guesses a proper letter, I subtract letters_left
by 1.
To create letters_left
I used len(set(letters_left))
. A set()
in python is basically a list, but without any duplicates. This means that if I tried to make a set
with the word "APPLE"
, it would just be {"A","P","L","E"}
. Getting the length of that tells me how many unique letters there are. Here is how it all looks together:
letters_left = len(set(guess_word))
elif guess_word.__contains__(guess):
...
#After the for loop:
#Decrement counter of how many letters are left since we guessed one
letters_left -= 1
Whenever letters_left == 0
, that means the user guessed all the letters correctly!
Fixing the while conditions
So our new while loop needs to stop if letters_left
is 0 or if chances
is better than 5.
That should look like this:
while letters_left != 0 and chances < 5:
The reason why I used the and
keyword instead of the or
keyword is that I need both of these statements to be valid. That is, the game can only keep going if the user hasn't solved the puzzle AND still has chances. Setting it or
means that the user could keep going if they ran out of chances, but still didn't get it. We don't want that.
Final Code
Here is the final code that runs perfectly on my machine. It has all of the original code and a few comments that I discussed earlier.
import random
#Changed guess to guess bc it makes more sense
word_list = {
"Animals" : "ORANGUTAN",
"Animals" : "GIRAFFE",
"Animals" : "ELEPHANT",
"Animals" : "CHEETAH",
"Food & Drinks" : "ROASTED BEEF SANDWICH",
"Food & Drinks" : "MAC AND CHEESE",
"Food & Drinks" : "VIRGIN MOJITO",
"Food & Drinks" : "STRAWBERRY SHAKE",
"Brands" : "SAMSUNG",
"Brands" : "APPLE",
"Brands" : "CALVIN KLEIN",
"Brands" : "JOCKEY" }
key_list = ["Animals", "Food & Drinks", "Brands"]
key_name = random.choice(key_list)
guess_word = word_list.get(key_name)
print(f'{key_name} ({len(guess_word)} letter word)')
letter_list = ["_"]*len(guess_word)
#Added counter variable to keep track of how many letters are still needed
letters_left = len(set(guess_word))
answer = ""
chances = 0
already_inputted = ""
#Modifying while loop to check if counter is zero or if chances are bigger than 5
#Also used "and" instead of or because either condition needs to terminate
#while answer.join(letter_list) != guess_word or chances < 5:
while letters_left != 0 and chances < 5:
print(letters_left)
index = 0
guess = input('Enter a letter as a guess: ')
if already_inputted.__contains__(guess):
print('The letter is already guessed')
elif guess_word.__contains__(guess):
for letter in guess_word:
if letter == guess:
#Changed to update list value instead of insert
#letter_list.insert(index, guess)
letter_list[index] = guess
index += 1
#Decrement counter of how many letters are left since we guessed one
letters_left -= 1
else:
chances += 1
already_inputted += guess
print(f'{letter_list}
chances = {5 - chances}
already guessed = {already_inputted}')
if chances == 5:
print(f"You lost! The word was {guess_word}")
else:
print("You win!")
:)