how to fix this python hangman game? - python

I have coded this hangman game to test something, and it doesn't work properly.
Here is the code:
import random
from string import ascii_lowercase, ascii_uppercase
secret_words = ["screen", "secret", "game", "hangman"]
def lowerChar(c):
if 'A' <= c <= 'Z':
return ascii_lowercase[ascii_uppercase.index(c)]
else:
return c
def get_guess():
word = random.choice(secret_words)
length = len(word)
limit = 5
count = 0
display = "*" * length
print(display, " Is the word")
while count < 5:
letter = input("Please Enter Your guess letter")
for l in word:
if letter.lower() == lowerChar(l):
print("Right guess!")
index = word.find(l)
display = display[:index] + letter + display[index + 1: ]
print(display)
if not '*' in display:
print("You won!")
break
else:
count += 1
print("You got it incorrect, you have: ", limit - count , " Additional trials")
get_guess()

You are doing too much inside the block for l in word. You have to check, whether the character is contained in the word or not, outside this loop:
import random
secret_words = ["screen", "secret", "game", "hangman"]
def get_guess():
word = random.choice(secret_words)
count = 0
display = "*" * len(word)
print(display, " Is the word")
while count < 5:
letter = input("Please Enter Your guess letter")
if letter.lower() not in word:
count += 1
print("You got it incorrect, you have: ", limit - count , " Additional trials")
else:
print("Right guess!")
new_display = ''
for w, l in zip(word, display):
if letter.lower() == w:
new_display += letter.lower()
else:
new_display += l
display = new_display
print(display)
if not '*' in display:
print("You won!")
break
get_guess()

An alternative solution to Daniel's would be introducing a variable called goodGuess that allows you to check if the person has made a correct guess in the for loop, and then once you have exited the for loop, then checking if the player has made an incorrect guess, see below
import random
from string import ascii_lowercase, ascii_uppercase
secret_words = ["screen", "secret", "game", "hangman"]
def lowerChar(c):
if 'A' <= c <= 'Z':
return ascii_lowercase[ascii_uppercase.index(c)]
else:
return c
def get_guess():
word = random.choice(secret_words)
length = len(word)
limit = 5
count = 0
display = "*" * length
print(display, " Is the word")
while count < 5:
letter = input("Please Enter Your guess letter")
#as we do not yet know if this guess is good we set it to False until we do know
goodGuess = False
for l in word:
if letter.lower() == lowerChar(l):
#as the player has made a correct guess we set goodGuess to True
goodGuess = True
print("Right guess!")
index = word.find(l)
display = display[:index] + letter + display[index + 1: ]
print(display)
if not '*' in display:
print("You won!")
break
#checking if the player has made a correct guess
if not goodGuess:
count += 1
print("You got it incorrect, you have: ", limit - count , " Additional trials")
get_guess()
Hope this helps.

Related

Putting guessed letters instead of dashes / Hangman / Python

i made hangman and am using this code. everything works fine, i just want to replace dashes in the list [lenghtDashes] with the correctly guessed letter in the corresponding place. i could not find any information online or here as well. maybe someone knows.
im open to any improvement suggestions as well.
secWord = input("What is the word for others to guess?: ")
life = 10
#starting information
i = 1
while i < 10:
print(".")
i += 0.01
#dots so players can not see the word
print("you have 10 tries to guess the word")
print("you will have to choose between gessing a letter (l) or a word (w) in start of every turn")
print("however, if you guess the word incorrectly you will lose immediately")
ans = input("are you ready to begin?: ")
while ans != "yes":
ans = input("now? ")
#rules
i = 1
while i < 10:
print(".")
i += 0.01
#dots for taking players to start
lenghtDashes = []
for letter in range(len(secWord)):
lenghtDashes.append("_")
#making dashes list
print("let's begin")
print("the word has " + str(len(secWord)) + " letters.")
appended = "".join(lenghtDashes)
print(appended)
#info for players
usedLetters = []
guessedLetters = []
wordLis = []
while life > 0 and ans != secWord:
print("are you guessing letter or a word?")
guessThing = input("l / w : ")
#for guessing a word
if guessThing == "w":
ans = input("What is the secret word?: ")
if ans == secWord:
print("Congratulations, you have guessed the right word\nYou won!")
else:
print("You guessed the word incorrectly\n The word was " + secWord + " \n You lost!")
exit()
#=================================================================
#for guessing a letter
elif guessThing == "l":
letList = [letter for letter in secWord]
guLett = input("Guess the letter \n(single letter only): ")
usedLetters.append(guLett)
if guLett in letList:
guessedLetters.append(guLett)
letListPlus = [letter for letter, x in enumerate(letList) if x == guLett]
letListPlusPlus = [num + 1 for num in letListPlus]
print("///")
print("///")
print("///")
print("Letters that you have used : " + str(usedLetters))
print("Letter that are correct: " + str(guessedLetters))
print("The position of letter " + str(guLett) + " is " + str(letListPlusPlus))
else:
print("///")
print("///")
print("///")
print("incorrect guess, you have " + str(life - 1) + " guesses remaining")
life = life - 1
print("Letters that you have used are: " + str(usedLetters))
print("Letter that are correct: " + str(guessedLetters))
#=================================================================
Whenever you need your in-progress word to be displayed (like "o_e_f_ow"), call this function:
def wordWithDashes(guessedLetters, letList):
return [letter if letter in guessedLetters else "_" for letter in letList]
It creates a new list from letList with missing letters replaced with "_". You can use str on it if you want a string result.
You don't need to keep track of lenghtDashes. Just compute it from the guessed letters and the actual word whenever you need it, as the code I provided does.

How to replace dash with letter - hangman

I am trying to make a hangman game for class and I am stuck on how to replace a dash (-) with a correctly guessed letter.
Like if the word was HAPPY and the user guessed the letter p, so it would replace the dash for a letter and look like this: --PP-
Here is my code so far:
def play_game(secret_word):
guesses_left = 8
hangman_dash = len(secret_word) * "-"
while guesses_left > 0:
print("The word now looks like this: " + (hangman_dash))
print("You have " + str(guesses_left) + " guesses left")
letter = input("Type a single letter, then press enter: ")
letter = letter.upper()
if len(letter) != 1:
print("Please enter only one letter.")
elif letter not in 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYXZ':
print("Please guess a letter.")
if letter in secret_word:
print("That guess is correct")
else:
print("There are no {}'s in the word".format(letter))
guesses_left = guesses_left - 1
I created a very simple example for this. Essentially if user_input in word then we find the index of the user input and replace it with the hidden letter. The code is not very well written :) but it does the job
def hangman(word):
# Replace word with dashes
hidden_word = "-" * len(word)
print("This is the hidden word " + hidden_word)
# Get user's guess
user_input = input("Guess a letter: ")
# If the user's guess exists in the string
if user_input in word:
# Find all occurences of user's guess in word
occurences = findOccurrences(word, user_input)
# For each occurenc, replace that dash in the string with the correct letter
for index in occurences:
hidden_word = hidden_word[:index] + user_input + hidden_word[index + 1:]
# Return the updated hidden_word
print(hidden_word)
# If the user's guess isn't in the string
else:
user_input = input("Sorry that letter was not found, please try again: ")
# Find all occurences method
def findOccurrences(s, ch):
return [i for i, letter in enumerate(s) if letter == ch]
hangman("hello")nput("Guess a letter: ")
if user_input in word:
occurences = findOccurrences(word, user_input)
for index in occurences:
hidden_word = hidden_word[:index] + user_input + hidden_word[index + 1:]
print(hidden_word)
else:
user_input = input("Sorry that letter was not found, please try again: ")
def findOccurrences(s, ch):
return [i for i, letter in enumerate(s) if letter == ch]
hangman("hello")
Going through the string is not worth programming. Just set the hangman_dash variable to '' every iteration of the loop and make a for loop like the one below to check if each of the letters are correct:
def play_game(secret_word):
guesses_left = 8
while guesses_left > 0:
hangman_dash=''
for i in secret_word:
if i in good_guesses:
hangman_dash+=i
else:
hangman_dash+='-'
print("The word now looks like this: " + (hangman_dash))
...
So if a letter in secret_word has been guessed (or is in the good_guesses string) then whatever that letter is will be added to hangman_dash. Otherwise, '-' will be added.
I've expanded upon the code that redline provided. It checks for alpha characters as well.
def hangman(word):
hidden_word = "-" * len(word)
print("This is the hidden word " + hidden_word)
while True:
user_input = input("Guess a letter: ")
if user_input.isalpha():
if user_input in word:
index = word.find(user_input)
hidden_word = hidden_word[:index] + user_input + hidden_word[index + 1:]
print(hidden_word)
else:
print("Sorry that letter was not found, please try again.")
else:
print("Please use letters in the alphabet.")
hangman("word")
As requested, I've added an example of words that contain two of the same letters. I hope this helps.
def hangman(secret_word):
hangman_dash = len(secret_word) * "-"
while True:
user_input = input("Guess:")
index = 0
for char in secret_word:
if char == user_input:
hangman_dash = hangman_dash[:index] + char + hangman_dash[index + 1:]
print(hangman_dash)
index += 1
hangman("happy")

Debugging a "guess the word " game

There is one small problem with my code , after I get all the letters correct, I had to enter another letter only it will show that I got it right. What is the problem?
import random
import string
import sys
def split(word):
return list(word)
alphabet = 'abcdefghijklmnopqrstuvwxyz'
list(alphabet)
words = ['hat','pop' ,'cut' , 'soup' , 'you' , 'me' , 'gay' , 'lol' ]
guess_word = []
wrong_letters_storage = []
secret_word = random.choice(words)
word_length = print("the length of the word is " + str(len(secret_word)))
correct_letters = split(secret_word)
def words():
for letter in secret_word:
guess_word.append("-")
return print("the words that you are guessing is " + str(guess_word))
def guessing():
while True:
c = 0
b = 7
while c <= 7:
print("")
hide = ""
print("you have " + str(b) + " guess left")
print("Wrong letters : " + str(wrong_letters_storage))
command = input("guess: ").lower()
if not '-' in guess_word:
print("you win!")
break
elif command == 'quit':
print("thank you for playing my game")
break
else:
if not command in alphabet :
print("pick an alphabet")
elif command in wrong_letters_storage:
print("you have picked this word")
else :
if command in secret_word :
print("right")
c += 1
b -= 1
for x in range(0, len(secret_word)):
if correct_letters[x] == command:
guess_word[x] = command
print(guess_word)
elif not command in secret_word :
print("wrong")
wrong_letters_storage.append(command)
c += 1
b -= 1
else :
print("error")
print("*"*20)
return print("Thank you for playing my game")
words()
guessing()
print("the words that you are guessing is " + secret_word )
Your code has several "problems":
you check if the current solution has no more '-' in it, after you ask for the next character input()
return print("whatever") returns None because the print function prints and returns None
you use variables with single_letter_names that make it hard to know what they are for
you use list's instead of set()'s for lookups (its fine here, but not optimal)
You can fix your problem by moving the test statement before the input() command:
# your code up to here
while True:
c = 0
b = 7
while c <= 7:
if not '-' in guess_word:
print("you win!")
break
print("")
hide = ""
print("you have " + str(b) + " guess left")
print("Wrong letters : " + str(wrong_letters_storage))
command = input("guess: ").lower()
if command == 'quit':
print("thank you for playing my game")
break
else:
# etc.
It would probably be better to do some more refaktoring:
import random
import string
import sys
def join_list(l):
return ''.join(l)
def guessing():
# no need to put all this in global scope
alphabet = frozenset(string.ascii_lowercase) # unchangeable set of allowed letters
words = ['hat', 'pop', 'cut', 'soup', 'you', 'me', 'beautiful', 'lol']
secret = random.choice(words) # your random word
secret_word = list(secret.lower()) # your random word as lowercase list
wrong = set() # set of wrongly guessed characters
right = set() # set of already correctly guessed characters
correct = frozenset(secret_word) # set of letters in your word, not changeable
guess_word = ['-' for k in correct] # your guessed letters in a list
guesses = 7
guessed = 0
print("The length of the word is ", len(secret))
# loop until breaked from (either by guessing correctly or having no more guesses)
while True:
print("")
print(f"you have {guesses-guessed} guess left")
if wrong: # only print if wrong letters guessed
print(f"Wrong letters : {wrong}")
# print whats know currently:
print(f"Guess so far: {join_list(guess_word)}")
command = input("guess: ").strip().lower()
try:
if command != "quit":
command = command[0]
except IndexError:
print("Input one letter")
continue
if command == 'quit':
print("thank you for playing my game")
break
else:
if command not in alphabet:
print("pick an alphabet")
continue
elif command in (wrong | right):
print("you already picked this letter")
continue
else :
guessed += 1
# always lookup in set of lowercase letters
if command in correct:
right.add(command)
for i,letter in enumerate(secret_word):
if command == letter:
# use the correct capitalisation from original word
guess_word[i] = secret[i]
else:
print("wrong")
wrong.add(command)
print("*"*20)
# break conditions for win or loose
if join_list(secret_word) == join_list(guess_word):
print("You won.")
break
elif guessed == guesses:
print(f"You lost. Word was: {join_list(secret_word)}")
break
guessing()

Question about dictionary items addition in Python (Guess the word game)

How can i add a letter multiple times in the different keys of a dictionary?
I made a guess the word game where the user enters the letter to complete the mysterious word.
Everything works fine with words where letters appears just one time (Ex. Dog) but I have problems when letters occur multiple times (Ex. Employee) because only the first one is filled.
I know this is probably not the most efficient way of doing this but I'm starting programming in python and was experimenting a bit with the concepts learned.
Here's the code, thanks for the help:
import os
word = input('choose the word to play with: ')
os.system('cls')
word_list = list(word)
word_dict = {}
for x in range(len(word_list)):
word_dict[str(x)] = word_list[x]
guess_dict = {}
for x in range(len(word_list)):
guess_dict[str(x)] = '_'
health = 10
victory = False
values = list(guess_dict.values())
print(values)
while victory == False:
letter = input('Choose the letter: ')
if letter in word_dict.values():
guess_dict[list(word_dict.keys())[list(word_dict.values()).index(letter)]] = letter
valori = list(guess_dict.values())
print(valori)
print()
if guess_dict == word_dict:
victory = True
print ('You won')
else:
health -= 1
print('ERROR!! ' + str(health) + ' lives remaining')
if health == 0:
print('You lose')
break
Your problem is exactly the dictionary. The dictionary has only one entry for each key. See here
In my opinion, you should use either a list, or a list of dictionaries.
import os
word = input('choose the word to play with: ')
os.system('cls')
word_list = list(word)
guess_list = [{'character': x, 'guessed': False} for x in word]
health = 10
victory = False
while True:
str = ''
for item in guess_list: #generate the string each iteration once
if False == item['guessed']:
str = str + "'_'"
else:
str = str + "'" + item['character'] + "'"
print(str)
if True == victory: #put the test here, so that the result is printed
print('You won!')
break
else:
letter = input('Choose the letter: ')
hit = False
missed_cnt = 0
for item in guess_list:
if item['character'] == letter: #if letter guessed, set flag
item['guessed'] = True
hit = True
if item['guessed'] == False: #count unguessed letters
missed_cnt +=1
if False == hit:
health -= 1
print('ERROR!! {0} lives remaining'.format(health))
if 0 == health:
print('You lose!')
break
if 0 == missed_cnt: #exit only after printing result
victory = True
Instead of a dictionary, you could use a set(). Since guessing a letter reveals all instances of that letter, removing it from the set corresponds to the same notion.
So you could do something like this:
word = input("hidden word:")
remainingLetters = set(word)
health = 10
while True:
print( "".join( "_" if letter in remainingLetters else letter for letter in word) )
letter = input("guess a letter:")
if letter in remainingLetters:
remainingLetters.remove(letter)
if remainingLetters: continue
print("you Win!")
break
health -= 1
if health == 0:
print("You lose")
break
print('ERROR!! {0} lives remaining'.format(health))
I would simply use a list of letters:
import os
from copy import deepcopy
word = list(input('choose the word to play with: '))
compare = deepcopy(word)
os.system('cls')
guess = []
for index, letter in enumerate(word):
guess.append('_')
health = 10
victory = False
while not victory:
letter = input('Choose the letter: ')
if letter in compare:
guess[compare.index(letter)] = letter
compare[compare.index(letter)] = ' '
print(guess)
print()
if guess == word:
victory = True
print ('You won')
else:
health -= 1
print('ERROR!! ' + str(health) + ' lives remaining')
if health == 0:
print('You lose')
break
The deepcopy in the beginning is because in Python if you do compare = word, compare would become a pointer to word. The variable compare by the way is to remove the already guessed characters from.
You could also check the input letter to make the code more robust:
while not victory:
letter = input('Choose the letter: ')
try:
value = float(letter)
print('Please enter a letter of type (str).')
continue
except ValueError:
pass
if len(letter) != 1:
print('Please enter only one letter!')
continue

I'm making a "hangman" game. In the game, I want to add lives and start with 7. Game Over on 0 lives.

Currently this is my code, but i don't know how to integrate the lives concept into my hangman game. When it is Game Over (0 lives), i want the game to end even if they didn't figure out the word after 7 attempts.
master = input("Enter a word: ")
print("\n"* 50 )
word = list(master)
length = len(word)
right = list("_" * length)
finished = False
while finished == False:
guess = input("Guess a letter!")
if guess not in master:
print("This letter is not in the word.")
for letter in word:
if letter == guess:
index = word.index(guess)
right[index] = guess
word[index] = "_"
print(right)
if list(master) == right:
print("You win!")
again = input("Again? y/n ")
if again == "y" or "Y":
master = input("Enter a word: ")
print("\n" * 50)
word = list(master)
length = len(word)
right = list("_" * length)
else:
finished = True
You have to initialize a variable with the number of wrong tries allowed and decrement it by 1 every time a wrong entry has been made. Finally check if the number of tries have finished(ie. 0) before continuing the loop.
master = input("Enter a word: ")
print("\n"* 50 )
word = list(master)
length = len(word)
right = list("_" * length)
tries=7
finished = False
while finished == False:
guess = input("Guess a letter!")
if guess not in master:
print("This letter is not in the word.")
tries-=1
print(tries," tries left")
for letter in word:
if letter == guess:
index = word.index(guess)
right[index] = guess
word[index] = "_"
print(right)
if list(master) == right:
print("You win!")
again = input("Again? y/n ")
if again == "y" or "Y":
master = input("Enter a word: ")
print("\n" * 50)
word = list(master)
length = len(word)
right = list("_" * length)
else:
finished = True
elif tries == 0:
print("Game Over!")
finished = True

Categories