How to a terminate a while loop? - python

I have this code that defines a word and I am making guesses of letters that form the actual word. It works perfectly, but I am unable to terminate the loop from taking in user input after I obtain the correct formation of letters. Does any one have an idea in terminating the loop?
word = "EVAPORATE"
guessed_word = "_" * len(word)
word = list(word)
guessed_word = list(guessed_word)
new_list = []
while True:
guess_letter = input("Enter a guess: ")
for index, letter in enumerate(word):
if letter == guess_letter:
guessed_word[index] = letter
print(' '.join(guessed_word))

You can simply change while True to while word != guessed_word, then it will stop after you obtain the correct answer.

This will work
word = "EVAPORATE"
word = word.lower()
word = list(word)
guessed_word = "_" * len(word)
guessed_word = list(guessed_word)
new_list = []
while True:
guess_letter = input("Enter a guess: ")
for index, letter in enumerate(word):
if letter == guess_letter:
guessed_word[index] = letter
print(' '.join(guessed_word))
if '_' not in guessed_word:
print('Congratulation!')
break

you should get to know about flow control statements being break, continue and pass. Look at break for this particular question

You can use break.
For example...
n = 5
while n > 0:
n -= 1
if n == 2:
break
print(n)
print('Loop ended.')

Related

hangman from 100 days of python solution

Is there a way to insert letters in a specific place where they (letters) are located inside a word?
This code allows me to do so, but adds '_' at the end of a list and misses the spot for a second letter if there are multiples of the same in one word. For example - pumpkin, it would add the first 'p' at its rightful place, but the second one will be right after.
These are my instructions:
Use a while loop to let the user guess again. The loop should only stop once the user has guessed all the letters in the chosen_word and 'display' has no more blanks ("_"). Then you can tell the user they've won.
import random
word_list = ["aardvark", "baboon", "camel"]
chosen_word = random.choice(word_list)
guess = input("Guess a letter: ").lower()
display = []
for i in chosen_word:
if i ==guess:
display.append(i)
else:
display.append('_')
print(display)
while '_' in display:
guess = input("Guess a letter: ").lower()
for i in chosen_word:
if i ==guess:
display.insert(chosen_word.index(i),i)
print(display)
.index(char) always gives first position.
You would have to use .index(char, start_position) to search after first position
pos = chosen_word.index(char) # first position
display.insert(pos, char)
pos = chosen_word.index(char, pos+1) # second position
display.insert(pos, char)
# etc.
You could try to do it in loop - and start with pos = -1
pos = -1
for ...:
if ...:
pos = chosen_word.index(char, pos+1)
display[pos] = char
but it can be simpler to use
for index, char in enumerate(chosen_word):
if char == guess:
display[index] = char
import random
word_list = ["pumpkin", "aardvark", "baboon", "camel"]
chosen_word = random.choice(word_list)
display = ['_'] * len(chosen_word)
print("".join(display))
while '_' in display:
guess = input("Guess a letter: ")
for index, char in enumerate(chosen_word):
if char.lower() == guess.lower():
display[index] = char
print("".join(display))

Improve the odds of winning at hangman with ai

I'm new (and to stack overflow, this is the first question I have ever asked) to python, I have been self-teaching myself for a couple of weeks. I was doing some beginner projects when I decided to make a hangman ai.
#importing
import random
import time
import sys
from collections import Counter
#---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#defining some variables
list_of_words = open("dictionary.txt", "r")
list_of_words = list_of_words.read().split()
SYMBOL = "abcdefghijklmnopqrstuvwxyz"
#---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#main game loop
def main():
while True:
print("\nGenerating word...")
word = list_of_words[random.randint(0, len(list_of_words) - 1)].lower()
word_guess = []
wrong_attempts = 0
wrong_letters = []
game_state = True
for symbol in word:
if symbol in SYMBOL:
word_guess.append("_")
else:
word_guess.append(symbol)
word_show = " ".join(word_guess)
word = list(word)
while game_state != False:
print("\n" + word_show)
print("\nWrong attempts [{0}/5]" .format(wrong_attempts))
if len(wrong_letters) > 0:
print("\nLetters guessed [{0}]" .format(", ".join(wrong_letters)))
letter = "-"
while letter not in SYMBOL or letter == "" or len(letter) > 1:
try:
letter = input("\nGuess a letter or enter 0 to call the ai: ")
except:
print("\nUnexpected error ocurred, try again")
if letter == "0":
correct_letters = [letter for letter in word_guess if letter in SYMBOL]
letter = ai_solver(wrong_letters, word_guess)
elif letter in wrong_letters or letter in word_guess:
print("\nYou already guessed letter [{0}]" .format(letter))
letter = ""
if letter in word:
for i in range(len(word)):
if letter == word[i]:
word_guess[i] = letter
else:
wrong_letters.append(letter)
wrong_attempts += 1
word_show = " ".join(word_guess)
if "".join(word_guess) == "".join(word):
print("\nYou won!")
game_state = False
elif wrong_attempts == 5:
print("\nYou lost!")
print("The word was [{0}]" .format("".join(word)))
game_state = False
option = input("\nWant to play again?[Y/N]: ")
if option.lower().startswith("n"):
sys.exit(0)
def ai_solver(letters_attempted, word_guess):
letters_attempted = letters_attempted if len(letters_attempted) != 0 else ""
available_words = []
for word in list_of_words:
append = False
if len(word) == len(word_guess):
append = True
for i in range(len(word_guess)):
if word[i] in letters_attempted:
append = False
break
if word_guess[i] != "_":
if word[i] != word_guess[i]:
append = False
break
if append == True:
print("[{0}]" .format(word))
available_words.append(word)
common_letters = [letter for letter in "".join(available_words) if letter not in word_guess]
common_letters = Counter("".join(common_letters)).most_common(1)
return common_letters[0][0]
main()
What I tried to do is, to filter all the possible words that have the same length as word_guess.
Then filter out any words that contained a letter that was guessed incorrectly by checking letters_attempted.
Then it would filter out all words that had letters that did not match with word_guess.
if word_guess[i] != "_":
if word[i] != word_guess[i]:
append = False
break
Although it works fine, sometimes it would lose, what can I add to increase the chances of winning?
Thank you!
Your two filter steps are a good first start. There are several different steps you could take to try to improve things. Let's call the words that fit the criteria so far the candidate words.
The first step would be to analyze all the candidate words and figure out which letter appears most frequently in the candidate words. (Not counting repeated letters multiple times.) That letter would make a good next guess.
A slightly more sophisticated approach would look at information gain from a guess. That is, it might be that half the candidate words have a 's', but all such words end in 's'. There might be slight fewer candidate words with a 't', but the 't' can appear anywhere in the word. So, when you guess 't' you actually get a lot more information about what the word could be, because you are shown the location of the 't' when you guess it correctly. Particularly when you don't have enough guesses to figure out every word, such a strategy may help you figure out more words in the guesses that you have.

Replace letter in word

If the guess is correct it will replace the letter with '-'. in the for loop how can i store the previous result and do a update with the new result?
import random
WORDS = ('linux', 'windows')
correct_word = random.choice(WORDS)
for n in range(5):
guess = input('Enter a letter: ')
letter = ''.join(x if x in guess else '-' for x in correct_word)
if letter in correct_word:
print("So far you have: ", letter)
else:
print("So far you have: ", letter)
Try keeping the letters guessed so far in a variable, like this (I removed the if statement because both branches do the same thing). Also added input validation:
import random
WORDS = ("linux", "windows")
correct_word = random.choice(WORDS)
def get_single_letter_input():
while True:
guess = input("Enter a letter: ")
if len(guess) == 1:
return guess
word_so_far = "".join("-" for letter in correct_word)
for n in range(5):
guess = get_single_letter_input()
word_so_far = "".join(x if x in guess else word_so_far[i]
for i, x in enumerate(correct_word))
print(f"So far you have: {word_so_far}")
You could try doing a regex replacement with re.sub. This answer assumes that you would be OK with using correct_word itself to maintain the state, by being updated with dashes for each matching letter which the user might choose.
import random
WORDS = ('linux', 'windows')
correct_word = random.choice(WORDS)
for n in range(5):
guess = input('Enter a letter: ')
if len(guess) > 1 or len(guess) == 0
print("Please choose a single letter only")
if letter in correct_word:
print("Correct choice")
correct_word = re.sub(guess, '-', correct_word)
else:
print("Letter not present")
Just keep your guessed word in a variable. Also I would recommend not to use fixed range as you do, but get the length of chosen word
def guess():
words = ('linux', 'windows')
correct_word = random.choice(words)
guessed_word = ["-" for letter in correct_word]
for n in range(len(correct_word)):
guess = input('Enter a letter: ')
for i in range(len(correct_word)):
if correct_word[i] == guess:
guessed_word[i] = guess
print("So far you have: ", "".join(x for x in guessed_word))
Here is quick draft for you, I strong believe that you can implement your fully idea:
import random
WORDS = ('linux', 'windows')
correct_word = random.choice(WORDS)
question = list( '-' * len(correct_word))
for n in range(5):
guess = input('Enter a letter: ')
for index, letter in enumerate(correct_word):
if letter is guess:
question[index] = letter
print("So far you have: ", ''.join(question))

Saving results of loop iterations in a game

I am trying to make a hangman game and I am running into trouble with the display. I have a loop that is supposed to put the correctly guessed letters in the right places, however it only shows the correct location for one letter at a time. I thought it would be helpful to save the result of the previous iteration, and then display that, but I am not sure how to do that.
import random,time
hanglist = []
answerlist = []
file_var = open("wordlist.100000")
for n in file_var:
hanglist.append(file_var.readline())
word = random.choice(hanglist)
print("word is",word)
guesses = 10
while guesses != 0:
print("guess a letter")
answer = input()
answerlist.append(answer)
if answer in word:
m = list(word)
for n in m:
if n == answer:
print(answer, end = '')
else:
print('_', end = '')
else:
print("close, but not exactly")
guesses -= 1
And here are the outputs
word is fabric
guess a letter
f
f______guess a letter
a
_a_____guess a letter
To solve your issue just replace if n==answer to if n in answer. But, from the above code, I can see code can't handle these issues:
If the user guesses the same word again and again
After 4 guesses are done and total word is guessed, then code should break out of the loop, which it is not happening.
While reading line, it need to strip the '\n' otherwise its really hard
My code addresses these issue:
import random,time
hanglist = []
answerlist = []
file_var = open("wordlist.100000")
for n in file_var:
# strips the '/n' at the end
hanglist.append(file_var.readline().rstrip())
word = random.choice(hanglist)
print("word is",word)
guesses = 10
while guesses!=0:
print("guess a letter")
answer = input()
if answer in answerlist:
continue
answerlist.append(answer)
if answer in word:
# to print entire word guessed till now- with current and previous iterations
word_print = ''
for n in word:
# to print all the last state occurences
if n in answerlist:
word_print += n
else:
word_print += '_'
print(word_print,end='')
# word is correctly guessed
if '_' not in word_print:
break
else:
print("close, but not exactly")
guesses = guesses-1
Your issue is with
if n == answer:
print(answer,end = '')
else:
print('_', end = '')
which only compares each letter with the current guess, answer. Instead, if you use
if n in answerlist:
print(n, end = '')
else:
print('_', end = '')
it will show the letter if that letter is in the list of their previous guesses.
Additionally: the previous m= list(word) is not necessary, as for n in word: is valid.

My anagram code doesn't account for multiple letters

So my code gets two words, and checks if one is the anagram of another one.
However doesn't work if multiple letters are exchanged, although I tried to account for that.
storedword = input("Enter your primary word \t")
global word
word = list(storedword)
word3 = input("Enter anagram word \t")
word3lowercase = word3.lower()
anaw = list(word3lowercase)
counter = int(0)
letterchecker = int(0)
listlength = len(word)
newcounter = int(0)
if len(anaw) != len(word):
print ("not anagram")
if len(anaw) == len(word):
while counter < listlength and newcounter < listlength:
tempcount = 0
if anaw[counter] == word[newcounter]:
temp = word[newcounter]
word[newcounter] = word[tempcount]
word[tempcount]=temp
letterchecker +=1
counter +=1
tempcount +=1
newcounter = int(0)
else:
newcounter +=1
if counter == len(word):
print ("anagram")
else:
print ("not anagram")
I think it's gone somewhere wrong after the if len(anaw) section, for example if the primary word is "hannah", and the secondary word is "hannnn", it thinks it's an anagram.
There is much simpler logic that can be implemented here, even without using sorted and such. Let's assume you have a function anagram:
def anagram(word1, word2):
if len(word1) != len(word2):
return False
def char_count(word):
char_count = {}
for c in word:
char_count[c] = char_count.get(c, 0) + 1
return char_count
cr1 = char_count(word1)
cr2 = char_count(word2)
return cr1 == cr2
You can test this with:
>>> print(anagram("anagram", "aanragm"))
True
>>> print(anagram("anagram", "aangtfragm"))
False
And for future readers, a super simple pythonic solution might be using Counter:
from collections import Counter
>>> Counter(word1) == Counter(word2)
Or using sorted:
>>> sorted(word1) == sorted(word2)
newcounter = int(0)
This is the line that causes the trouble (in the while loop).
Because of it you start checking the word from the beginning again.
I think you want it to be newcounter=letterchecker.
Since already used characters are put to the front of word they are ignored if you start with letterchecker
Tell me if it works
Edit:Checked with example given, seems to work.
Without using sort you could use the following approach. It removes a letter from an array of a characters of the second word. The words are only anagrams if there are no letters left (and the words are the same length to start with and have a length larger than zero):
word1="hannah"
word2="nahpan"
chars1= list(word1)
chars2= list(word2)
if len(chars1)==len(chars2) and len(chars1)>0:
for char in chars1:
if char not in chars2:
break
chars2.remove(char)
if len(chars2)==0:
print "Both words are anagrams"
else:
print "Words are not anagrams"
[EDIT THIS IS JUST FOR PALINDROMES I CANT READ]
Here is something a bit more simple:
storedword = input("Enter your primary word \t")
word3 = input("Enter anagram word \t")
if storedword == word3[::-1]:
print "Is Anagram"
else:
print "Is not anagram"

Categories