While loop goes on forever despite condition being met
Question:
My while loop is supposed to end once each letter in display is not an underscore.
However despite display updating to remove all underscores. The loop keeps going on, and I can’t figure out why.
import random
word_list = ["aardvark", "baboon", "camel"]
chosen_word = random.choice(word_list)
word_length = len(chosen_word)
print(f'Pssst, the solution is {chosen_word}.')
display = []
for _ in range(word_length):
display += "_"
guess = input("Guess a letter: ").lower()
def check_letter():
for position in range(word_length):
letter = chosen_word[position]
if letter == guess:
display[position] = letter
print(display)
check_letter()
for item in display:
while item == "_":
guess = input("Guess a letter: ").lower()
check_letter()
print("You've Won")
Answers:
item is a copy of your display element. This may be what you want
for i in range(word_length):
while display[i] == "_":
guess = input("Guess a letter: ").lower()
check_letter()
import random
word_list = ["aardvark", "baboon", "camel"]
chosen_word = random.choice(word_list)
word_length = len(chosen_word)
display = []
print(f'Pssst, the solution is {chosen_word}.')
display = []
for _ in range(word_length):
display += "_"
guess = input("Guess a letter: ").lower()
def check_letter(display):
for position in range(word_length):
letter = chosen_word[position]
if letter == guess:
display[position] = letter
print(display)
check_letter(display)
for item in display:
while item == "_":
guess = input("Guess a letter: ").lower()
check_letter(display)
if (''.join([str(elem) for elem in display]) == chosen_word) :
break
print("You've Won")
I played with your code for much longer than I thought I would. The problem is subtle.
The issue with your code is that item
never changes it’s value (despite the for loop). And that’s why the problem is subtle – the for loop (for item in display:
) only iterates once because the while loop it contains is endless. The while loop is endless is because nothing in the while loop changes the value of item
.
All that said, I can see why you are asking here at SO. Here’s a bit of code that eliminates the for loop for just a while loop. I’ve eliminated the item
variable – it doesn’t change anyway. Rather, the condition that keeps us in the loop is there is still an underscore in the display
variable.
import random
word_list = ["aardvark", "baboon", "camel"]
chosen_word = random.choice(word_list)
word_length = len(chosen_word)
print(f'Pssst, the solution is {chosen_word}.')
display = []
for _ in range(word_length):
display += "_"
guess = input("Guess a letter: ").lower()
def check_letter():
for position in range(word_length):
letter = chosen_word[position]
if letter == guess:
display[position] = letter
print(display)
check_letter()
while '_' in display:
guess = input("Guess a letter: ").lower()
check_letter()
print("You've Won")
Here is an alternate solution. I also added a check to see if the user has already entered a given letter and output to say that letter has already been guessed.
from calendar import c
import random
word_list = ["aardvark", "baboon", "camel"]
chosen_word = random.choice(word_list)
word_length = len(chosen_word)
guessed_word = []
print(f'Pssst, the solution is {chosen_word}.')
display = []
for _ in range(word_length):
display += "_"
guess = input("Guess a letter: ").lower()
def check_letter():
for position in range(word_length):
letter = chosen_word[position]
if letter == guess:
display[position] = letter
# append the letter to the guessed_word list at the correct position
guessed_word.insert(position, letter)
print(display)
check_letter()
for item in display:
while item == "_":
gw = ''.join(guessed_word)
cw = ''.join(chosen_word)
if gw == cw:
print("You win")
break
else:
guess = input("Guess a letter: ").lower()
if guess in display:
print(f"You've already guessed {guess}")
else:
check_letter()
My while loop is supposed to end once each letter in display is not an underscore.
However despite display updating to remove all underscores. The loop keeps going on, and I can’t figure out why.
import random
word_list = ["aardvark", "baboon", "camel"]
chosen_word = random.choice(word_list)
word_length = len(chosen_word)
print(f'Pssst, the solution is {chosen_word}.')
display = []
for _ in range(word_length):
display += "_"
guess = input("Guess a letter: ").lower()
def check_letter():
for position in range(word_length):
letter = chosen_word[position]
if letter == guess:
display[position] = letter
print(display)
check_letter()
for item in display:
while item == "_":
guess = input("Guess a letter: ").lower()
check_letter()
print("You've Won")
item is a copy of your display element. This may be what you want
for i in range(word_length):
while display[i] == "_":
guess = input("Guess a letter: ").lower()
check_letter()
import random
word_list = ["aardvark", "baboon", "camel"]
chosen_word = random.choice(word_list)
word_length = len(chosen_word)
display = []
print(f'Pssst, the solution is {chosen_word}.')
display = []
for _ in range(word_length):
display += "_"
guess = input("Guess a letter: ").lower()
def check_letter(display):
for position in range(word_length):
letter = chosen_word[position]
if letter == guess:
display[position] = letter
print(display)
check_letter(display)
for item in display:
while item == "_":
guess = input("Guess a letter: ").lower()
check_letter(display)
if (''.join([str(elem) for elem in display]) == chosen_word) :
break
print("You've Won")
I played with your code for much longer than I thought I would. The problem is subtle.
The issue with your code is that item
never changes it’s value (despite the for loop). And that’s why the problem is subtle – the for loop (for item in display:
) only iterates once because the while loop it contains is endless. The while loop is endless is because nothing in the while loop changes the value of item
.
All that said, I can see why you are asking here at SO. Here’s a bit of code that eliminates the for loop for just a while loop. I’ve eliminated the item
variable – it doesn’t change anyway. Rather, the condition that keeps us in the loop is there is still an underscore in the display
variable.
import random
word_list = ["aardvark", "baboon", "camel"]
chosen_word = random.choice(word_list)
word_length = len(chosen_word)
print(f'Pssst, the solution is {chosen_word}.')
display = []
for _ in range(word_length):
display += "_"
guess = input("Guess a letter: ").lower()
def check_letter():
for position in range(word_length):
letter = chosen_word[position]
if letter == guess:
display[position] = letter
print(display)
check_letter()
while '_' in display:
guess = input("Guess a letter: ").lower()
check_letter()
print("You've Won")
Here is an alternate solution. I also added a check to see if the user has already entered a given letter and output to say that letter has already been guessed.
from calendar import c
import random
word_list = ["aardvark", "baboon", "camel"]
chosen_word = random.choice(word_list)
word_length = len(chosen_word)
guessed_word = []
print(f'Pssst, the solution is {chosen_word}.')
display = []
for _ in range(word_length):
display += "_"
guess = input("Guess a letter: ").lower()
def check_letter():
for position in range(word_length):
letter = chosen_word[position]
if letter == guess:
display[position] = letter
# append the letter to the guessed_word list at the correct position
guessed_word.insert(position, letter)
print(display)
check_letter()
for item in display:
while item == "_":
gw = ''.join(guessed_word)
cw = ''.join(chosen_word)
if gw == cw:
print("You win")
break
else:
guess = input("Guess a letter: ").lower()
if guess in display:
print(f"You've already guessed {guess}")
else:
check_letter()