I am writing a python based terminal game of Hangman for a project.
Currently, the correctly guessed letters and letters remaining are displayed correctly if the player makes a correct guess or an incorrect guess.
I am having an issues displaying the letters if the player makes an invalid guess.
I have a for loop that displays the guessed letters and unguessed letters which works as expected.
However, I have an if else statement at the start of the function that determines if the user inputs a correct character.
The problem I have is that the letters are only displayed if the user makes a valid entry.
So if the user repeats a letter, inputs a number instead of a letter, or inputs multiple characters, the code to display the letters doesn’t run so the user wont be able to see their “gamescreen”.
This is the main function for the main game.
def new_game(category, difficulty):
"""
Starts a new game which takes the category and difficulty
parameters chosen by the user to generate a word from the spreadsheet.
"""
# Generate the word the player is trying to guess
random_word = random.choice(
SHEET.worksheet(difficulty + "_" + category)
.get_values().pop()).upper()
# Print the category and difficulty level chosen by the user
print(f"Category: { category.capitalize() }")
print(f"Difficulty level: { difficulty.capitalize() }")
guessed_letters = ""
wrong_guesses = 0
print_hangman(wrong_guesses)
# Print random word for testing.
print(f"your word is: {random_word}")
# Display blank letters in word for user.
print(len(random_word) * " _ " + "\n ")
# Create a loop that ends when the player loses. Break if player wins.
while wrong_guesses < 7:
player_choice = input("Please pick a letter...: \n").upper()
print(f"Category: { category.capitalize() }")
print(f"Difficulty level: { difficulty.capitalize() } \n")
print_hangman(wrong_guesses)
clear()
# Prints error message if player choice is not a letter from a-z.
if not player_choice.isalpha():
print(
f"{player_choice} is not a valid letter... " +
f"You have {7 - wrong_guesses} guess(es) remaining...")
print_hangman(wrong_guesses)
guessed_letters = guessed_letters + player_choice
wrong_letters = 0
# Prints the players guessed letters and remaining blank spaces.
for letter in random_word:
if letter in guessed_letters:
print(
f" { letter.upper() } ", end=""
)
else:
print(" _ ", end="")
wrong_letters += 1
print("")
print("\nPreviously guessed letters: \n")
print(f"{list(guessed_letters.upper())}" + "\n ")
# Print error message if player inputs more than one letter.
elif len(player_choice) != 1:
print(
"Please input one letter at a time..." +
f"You have {7 - wrong_guesses} guess(es) remaining...")
print_hangman(wrong_guesses)
print("\nPreviously guessed letters: \n")
print(f"{list(guessed_letters.upper())}" + "\n ")
# Print error message if player repeats the same letter.
elif player_choice in guessed_letters:
print(
f"{player_choice.upper()} has already been guessed..." +
f"You have {7 - wrong_guesses} guess(es) remaining...")
print_hangman(wrong_guesses)
print("\nPreviously guessed letters: \n")
print(f"{list(guessed_letters.upper())}" + "\n ")
# Runs if player makes a valid input.
else:
if player_choice in random_word:
print(
f"Correct, {player_choice.upper()} is in the word! " +
f"You have {7 - wrong_guesses} guess(es) remaining...")
else:
# Add 1 to the wrong_guesses variable
wrong_guesses += 1
print(
f"Sorry, {player_choice.upper()} is not in the word... " +
f"You have {7 - wrong_guesses} guess(es) remaining..."
)
print_hangman(wrong_guesses)
# Adds all letters guessed by the user
# to the guessed_letters variable.
guessed_letters = guessed_letters + player_choice
wrong_letters = 0
# Loop that displays correct letters and letters remaining.
for letter in random_word:
if letter in guessed_letters:
print(
f" { letter.upper() } ", end=""
)
else:
print(" _ ", end="")
wrong_letters += 1
print(" ")
print("\nPreviously guessed letters: \n")
print(f"{list(guessed_letters.upper())}" + "\n ")
if wrong_letters == 0:
print(
colorama.Fore.GREEN +
"Congratulations, you won! \n"
)
print(f"The word is {random_word.upper()}!\n")
sub_menu()
break
else:
print(
colorama.Fore.RED +
"\nSorry, you lose... Please try again...\n")
print(f"The word was {random_word.upper()}...\n")
sub_menu()
I’ve copied the loop into the first validity checker at line 391 to test and it does work.
I can also put the loop into the other error statements but this ends up making the code very bulky.
I’ve tried moving the loop into its own function but it is referencing other variables that are only in the new_game function.
I also tried to define an inner function but I couldn't get it to work, I had variables in the inner function that were needed in the outer function.
Any help on figuring this out would be greatly appreciated.
Also any other tips to clean up this code would be great if you notice anything ridiculous!
I have a lot of repeating print statements that I tried to avoid repeating but I couldn't get it to work the way I wanted unless I printed them out every time.
You can put the for loop in its own function and pass it the variables it needs when calling it. The function might look like this:
def display_letters(random_word, guessed_letters, wrong_letters):
for letter in random_word:
if letter in guessed_letters:
print(
f" { letter.upper() } ", end=""
)
else:
print(" _ ", end="")
wrong_letters += 1
return wrong_letters
I'm not sure about this but could you not just have the letters display after you fall out of the if statement? As in, immediately after the if statement (but not in it) just run the for loop. That might work.
Related
I am a beginner in Python and I am making Hangman game project
So whenever I try to put the same alphabet twice it takes 2 lives
instead of just taking one
because both conditions are getting true.
My code is running fine but output is coming wrong due to both
conditions in if statement
given is satisfied
here is my code below
import time #importinf random module
#from hangman_art import logo #importing logo which i have in my PC, you ignore.
print("Welcome to HANGMAN")
#print(logo) #printing the logo which imported
user = input("\nWhat's Your Name : ") # take input for user name
print(f"\nHello {user}! Best Of Luck") #just for code to feel good.
x = (input("\nReady to play??? : ")) #input from user weather he/she wants to play or no.
if x == "yes" or x =="YES" or x =="Yes" or x == "y" or x == "Y": print("\nGame Loading in
3..2..1")
else:
print("\nOk Sadly ending the game!! BYE BYE")
exit()
#time.sleep(3)
print("\nGame Start!!")
#time.sleep(1)
print("\nRules as follows :-\n1. Guess the right word letter by letter.\n2. You only got 6
lives.\n3. Do not repeat the same alphabet entry it will reduce your life.\n4. Enjoy the game.")
#time.sleep(3)
import random #importing random module for code to choose any random number.
word_list=["TIGER","ELEPHANT","LION","CAT","DOG","HORSE"] #you can add n numbers of words.
chosen_word = random.choice(word_list) #giving variable to chosen random word.
length = len(chosen_word) #variable to find length of chosen word.
display=[] #creating an empty list.
in_game = True #for while loop to run continously
lives = 6 #user get 6 lives.
display=[]
duplicate=[] #creating an empty list to store duplicate values.
for _ in range (length):
display += "_"
#here looping for guess and game
while in_game:
guess = input("\nCome On Guess a word letter by letter : ").upper()
#make a list called duplicate
#add guess letter to duplicate list
#check if the entered letter is already present in that list
#if present then show msg stating already used word
#else follow the normal process
#duplicate=[]
if guess in display:
print("\nYou guessed",guess)
for position in range(length): #for getting length of number to be guessed
letter = chosen_word[position]
if letter == guess:
print("\nYou guessed",guess,"which is right aplhabet!!")
display[position] = letter
print(" ".join(display)) #joiningdisplay
if guess in duplicate:
lives -= 1 #this condition for taking life if duplicate entry.
print(f"\n{user} Do not repeat same alphabet entry. A LIFE LOST due to continues same
alphabet entry.") #here condition gets true and then goes to another if statment there also it gets true and code takes 2 life.
if lives == 0:
in_game = False
print(f"\n{user} You lost all your life, YOU LOSE.")
duplicate.append(guess)
#here 2 conditions are getting true so code is taking 2 lives please help
if guess not in chosen_word:
print("\nYou guessed", guess, "which is not the alphabet, life lost.")
lives -= 1
if lives == 0:
in_game = False
print(f"\n Try next
time {user}, You lost all your life, YOU LOSE.")
if not "_" in display:
in_game = False
print(f"\n Congrats {user} You WIN.")
from hangman_art import stages
print(stages[lives])
There are 2 if conditions that are true, so each will minus 1 live. You should use if and elif to ensure only 1 true condition is allowed. The code can be improved with 3 changes, see below:
<truncated>
while in_game:
guess = input("\nCome On Guess a word letter by letter : ").upper()
<truncated>
if guess in duplicate:
lives -= 1
print(f"\n{user} Do not repeat same alphabet entry. A LIFE LOST due to continues same alphabet entry.")
if lives == 0:
in_game = False
print(f"\n{user} You lost all your life, YOU LOSE.")
# duplicate.append(guess) #1. remove line from here
elif guess not in chosen_word: #2. change if to elif
print("\nYou guessed", guess, "which is not the alphabet, life lost.")
lives -= 1
if lives == 0:
in_game = False
print(f"\n Try next time {user}, You lost all your life, YOU LOSE.")
duplicate.append(guess) #3. add this line here instead
if not "_" in display:
in_game = False
print(f"\n Congrats {user} You WIN.")
Here's another way to do it, with MAX_WRONG = 6 means user gets 6 lives.
import random
WORDS = ['apple', 'banana', 'kiwi', 'orange', 'helicopter']
MAX_WRONG = 6
def game_play():
word = random.choice(WORDS).upper()
current_guess = '-' * len(word) #hidden answer
wrong_guesses = 0
used_letters = []
while wrong_guesses < MAX_WRONG and current_guess != word:
print ('\nRemaining tries:', MAX_WRONG - wrong_guesses)
print ('So far, the word is: ', current_guess)
print ('You have used the following letters: ', used_letters)
guess = input('Enter your letter guess:').upper()
if guess == word:
current_guess = word
break #exit the while-loop
while guess in used_letters: #check for duplicate input
print ('You have guessed "' + guess + '" already!')
guess = input ('Enter your letter guess: ').upper()
used_letters.append(guess) #append guess to used_letters
if guess in word:
print ('You have guessed correctly!')
new_current_guess = ''
for idx in range(len(word)): #update hidden answer
if guess == word[idx]:
new_current_guess += guess
else:
new_current_guess += current_guess[idx]
current_guess = new_current_guess
else:
print ('Sorry that was incorrect')
wrong_guesses += 1
if wrong_guesses == MAX_WRONG:
print ('\nYou have been hanged!')
print ('The correct word is', word)
elif current_guess == word:
print ('\nYou have won!! The word is:', word)
game_play()
Output:
Remaining tries: 6
So far, the word is: ----------
You have used the following letters: []
Enter your letter guess: helicopter
You have won!! The word is: HELICOPTER
I've written a hangman program in python. The program is finished, but I have a problem with my main function. If I set a win or loss, it no longer execute my print statements from before. This means that if I have to guess a word, for example, it doesn't fill in the last letter in the placeholder, it just breaks out the loop without filling in the last letter. The same goes with my hangman. If I don't have any more attempts left, it won't finish drawing my hangman (just leave out the last part). Who knows why that is? Please help
Here is my code:
##### HANGMAN IN PYTHON #####
count_attempts = 0
guess_word = []
def guidance():
print('Welcome to Hangman in Python!')
print('''The point here is to guess a word by trying out letter combinations and
defining them with ENTER.''')
print('''For each word, you have 10 tries! If you can not solve the word,
the game is over.''')
print('You have 9 attempts to guess the word.')
print('Have fun!')
print('')
def user_word():
userinput = str(input("Type in the word you want to be guessed: "))
for character in userinput:
if character.isdigit():
print('There is a number in your word!')
userinput = str(input('Please try again: '))
return userinput.upper()
def change(userinput):
global guess_word
list_WordToBeGuessed = list(userinput)
for characters in list_WordToBeGuessed:
guess_word.append(' _')
def play_game(userinput):
global count_attempts
length_word = len(userinput)
user_guessed = []
print('Word to guess: ', *guess_word)
print("")
list_WordToBeGuessed = list(userinput)
guess = str(input('Guess a letter: ')).upper()
for number in guess:
if number.isdigit():
guess = str(input('Input not valid. Guess a letter: ')).upper()
if guess in user_guessed:
print('You have already given this letter. ')
elif guess in list_WordToBeGuessed:
user_guessed.append(guess)
print("You've guessed a letter correctly!")
for i in range(0, length_word):
if list_WordToBeGuessed[i] == guess:
guess_word[i] = guess
else:
count_attempts += 1
user_guessed.append(guess)
print('Sry your given letter is not in the word!')
print("You have failed", count_attempts, "of 5 attempts")
def draw_hangman(count_attempts):
print('-------' )
print(' | ' + ('|' if count_attempts > 0 else ''))
print(' | ' + ('O' if count_attempts > 1 else ''))
print(' | ' + ('/ \\' if count_attempts > 2 else ''))
print(' | ' + ('|' if count_attempts > 3 else ''))
print('--- ' + ('/ \\' if count_attempts > 4 else ''))
print("")
def main():
guidance()
userinput = user_word()
change(userinput)
while True:
draw_hangman(count_attempts)
play_game(userinput)
if count_attempts >= 5:
print("You haven't any attempts left. Bad luck")
break
elif ' _' not in guess_word:
print("")
print('You won, congratulation!')
break
main()
you are breaking out of a loop before it can draw the hangman and word.
in the endgame conditions, you can simply call draw_hangman(count_atttempts) before each print statement and change(userinput) as well.
Edit:
You will have to redraw the word as well. Since this is built into your play_game() function it is difficult, but you can use
for i in guess_word:
guess = guess + i + " "
print(guess)
before the print statements along with the draw_hangman(count_attempts) change you made before. Please note you will need to create a new variable called guess in your main() function prior to adding this code.
Since you have a "break" in your endgame condition, the loop stops and last "draw_hangman(count_attempts)" is not called. You can simply add "draw_hangman(count_attempts)" before "print("You haven't any attempts left. Bad luck")"
I am creating a "guess the word" game in python for my intro to programming class. The word is shown with dashes (-) in place of the vowels. The user is supposed to guess the word based off of a provided hint (the words/hints go together as parallel tuples). The user gets 5 guesses and if the word is guessed correctly, a certain amount of points are awarded. The user can then either choose to keep playing & accumulate points, or quit. The code was working until I added the coding to ask the user if he/she would like to keep playing. What is it that I need to fix in order for it to work?
#Clear Screen
print("\n"*50)
import random
#Variables
keep_playing = "y"
round_score = 0
overall_score = 0
new_words = ""
vowels = "AaEeIiOoUuYy"
#Parallel tuples
while keep_playing.lower() == "y":
guesswords = ("Japan","France","Mexico","Italy","Australia")
guesshints = ("Sushi comes from here","Croissants come from here","Tacos come from here","Pizza comes from here","Vegemite comes from here")
#Random
index = random.randrange(len(guesswords))
guesses = 5
#Replacing vowels
for letter in guesswords[index]:
if letter not in vowels:
new_words += letter
else:
new_words += "-"
#Output
print(new_words.center(80, " "))
print("Hint:",guesshints[index])
while guesses > 0:
input_string = "\nGuess the word! You have " + str(guesses) + " guesses remaining: "
user_guess = input(input_string)
if user_guess.upper() == guesswords[index].upper():
print("YOU WIN")
round_score = (guesses * 2)
overall_score += round_score
print("Your score for this round is ",round_score)
break
guesses -= 1
print("Your overall score is ",overall_score)
keep_playing = input("Would you like to keep playing? (y/n)")
print("GAME OVER")
My hangman program is fully functioning except there is one problem, let's say the word is mathematics, I guess m, a, t, h, e - but once I guess the other m, it says I guessed it (as opposed to saying "You already guessed this letter") but it doesn't replace the _.
My Code:
def start():
import random
words = ["barbershop", "cuddle", "furious", "demolition", "centaur", "forest", "pineapple", "mathematics", "turkish"]
word = random.choice(words);
hiddenword = len(word) * "-"
used_letters = []
lives = 6
print "Welcome to Hangman! You have 6 guesses, good luck!"
while True:
print word
print "".join(hiddenword)
guess = raw_input("> ")
hiddenword = list(hiddenword)
if len(guess) > 1:
print "Error: 1 Letter Maximum"
elif len(guess) < 1:
guess = raw_input("> ")
else:
if guess.isdigit() == True:
print "Error: Hangman only accepts letters."
else:
if guess in used_letters and word.count(guess) == 1:
print "You already guessed that letter"
else:
if guess.lower() in word:
print "You got the letter " + "'" + guess + "'" + "!"
hiddenword[word.index(guess)] = guess
used_letters.append(guess)
else:
lives -= 1
print "-1 Guesses"
print "Guesses:", lives
used_letters.append(guess)
if lives == 0:
print "GAME OVER: You're out of guesses, try again!"
break
if hiddenword == word:
print "Cangratulations, you got the word!"
break
start()
P.S. - I know I have a lot of excess code e.g. if statements, please do not comment on that.
The problem appears to be with the line:
hiddenword[word.index(guess)] = guess
The string method .index(x) returns the index of the first incidence of x. So this line will persistently fill in the first "m" in mathematics.
Assuming you want the game to reveal all instances of a letter when it is guessed (e.g., show both m's in "mathematics" when you guess "m"), you can substitute this:
for i, x in enumerate(word):
if word[i] == guess:
hiddenword[i] = guess
for your line:
hiddenword[word.index(guess)] = guess
Also, to get the "Congratulations!" message to appear, you will need to change if hiddenword == word to if ''.join(hiddenword) == word, since hiddenword is a list at this point.
Removing multiple occurences of a character in a string in python is easily achieved using:
your_string.replace("m", "");
http://www.tutorialspoint.com/python/string_replace.htm
For an assignment I need to write a basic HANGMAN game. It all works except this part of it...
The game is supposed to print one of these an underscore ("_") for every letter that there is in the mystery word; and then as the user guesses (correct) letters, they will be put in.
E.G
Assuming the word was "word"
User guesses "W"
W _ _ _
User guesses "D"
W _ _ D
However, in many cases some underscores will go missing once the user has made a few guesses so it will end up looking like:
W _ D
instead of:
W _ _ D
I can't work out which part of my code is making this happen. Any help would be appreciated! Cheers!
Here is my code:
import random
choice = None
list = ["HANGMAN", "ASSIGNEMENT", "PYTHON", "SCHOOL", "PROGRAMMING", "CODING", "CHALLENGE"]
while choice != "0":
print('''
******************
Welcome to Hangman
******************
Please select a menu option:
0 - Exit
1 - Enter a new list of words
2 - Play Game
''')
choice= input("Enter you choice: ")
if choice == "0":
print("Exiting the program...")
elif choice =="1":
list = []
x = 0
while x != 5:
word = str(input("Enter a new word to put in the list: "))
list.append(word)
word = word.upper()
x += 1
elif choice == "2":
word = random.choice(list)
word = word.upper()
hidden_word = " _ " * len(word)
lives = 6
guessed = []
while lives != 0 and hidden_word != word:
print("\n******************************")
print("The word is")
print(hidden_word)
print("\nThere are", len(word), "letters in this word")
print("So far the letters you have guessed are: ")
print(' '.join(guessed))
print("\n You have", lives,"lives remaining")
guess = input("\n Guess a letter: \n")
guess = guess.upper()
if len(guess) > 1:
guess = input("\n You can only guess one letter at a time!\n Try again: ")
guess = guess.upper()
while guess in guessed:
print("\n You have already guessed that letter!")
guess = input("\n Please take another guess: ")
guess = guess.upper()
guessed.append(guess)
if guess in word:
print("*******************************")
print("Well done!", guess.upper(),"is in the word")
word_so_far = ""
for i in range (len(word)):
if guess == str(word[i]):
word_so_far += guess
else:
word_so_far += hidden_word[i]
hidden_word = word_so_far
else:
print("************************")
print("Sorry, but", guess, "is not in the word")
lives -= 1
if lives == 0:
print("GAME OVER! You ahve no lives left")
else:
print("\n CONGRATULATIONS! You have guessed the word")
print("The word was", word)
print("\nThank you for playing Hangman")
else:
choice = input("\n That is not a valid option! Please try again!\n Choice: ")
You have hidden_word = " _ " * len(word)
This means that at start for a two letter word, you have [space][underscore][space][space][underscore][space].
When you then do word_so_far += hidden_word[i], for i = 0, you will append a space, not an underscore.
The quickest fix would seem to be:
Set hidden_word to just be _'s (hidden_word = " _ " * len(word))
When you print out the word, do
hidden_word.replace("_"," _ ") to add the spaces around the underscores back
#Foon has showed you the problem with your solution.
If you can divide your code up into small functional blocks, it makes it easier to concentrate on that one task and it makes it easier to test. When you are having a problem with a specific task it helps to isolate the problem by making it into a function.
Something like this.
word = '12345'
guesses = ['1', '5', '9', '0']
def hidden_word(word, guesses):
hidden = ''
for character in word:
hidden += character if character in guesses else ' _ '
return hidden
print(hidden_word(word, guesses))
guesses.append('3')
print(hidden_word(word, guesses))
Below code solves the problem.you can do some modifications based on your requirement.If the Guessed letter exists in the word.Then the letter will be added to the display variable.If not you can give a warning .But note that it might tempt you to write ELSE statement inside the for loop(condition:if guess not in word).If you do like that then the object inside the Else statement will be repeated untill the For loop stops.so that's why it's better to use a separete IF statement outside the for loop.
word="banana"
display=[]
for i in word:
display+="_"
print(display)
while True:
Guess=input("Enter the letter:")
for position in range(len(word)):
if Guess==word[position]:
display[position]=word[position]
print(display)
if Guess not in word:
print("letter Doesn't exist")