Python Hangman Game finishing touches - python

Here is my code:
def randWord():
"""opens a file of words and chooses a random word from the file"""
infile = open('dictionary.txt','r')
wordList = infile.read()
wordList2 = wordList.split('\n')
infile.close()
randWord = str(random.choice(wordList2))
return randWord
def hangman():
"""initiates the game by explaining the rules and terminates when game is over"""
global roundsWon
global roundsPlayed
print('\nWelcome to hangman! The rules are simple: A word will be chosen at random and will be represented by a sequence of blanks. Each blank constitutes a letter in the word. You will be asked to enter a letter and if the letter is contained in the word you will be notified. You can only make an incorrect guess 8 times before you lose the round. To win the round you must guess all the letters and reveal the word. Good luck!\n\n')
word = randWord()
while True:
guess = letterGuess(word)
if checkGuess(guess,word):
roundsWon += 1
roundsPlayed +=1
print('\nYou won! The word is {}.'.format(word))
break
elif guessesLeft == 0:
print("\nI'm sorry, but you have run out of guesses. The word was {}.".format(word))
roundsPlayed +=1
break
def letterGuess(word):
"""asks the user to guess a letter and prints the number of guesses left"""
blankedWord(word)
guess = input('\nGuess a letter: ')
return guess
def blankedWord(word):
"""converts the random word into the proper blanked form based on the letter guessed and lets the user know if their letter is in the word"""
displayWord=''
for letter in word:
if guessedLetters.find(letter) > -1:
displayWord = displayWord + letter #checks if the letter guessed is contained in the random word string by index.
print('\n{} is contained in the word!'.format(letter))
else:
displayWord = displayWord + '-'
print(displayWord)
def checkGuess(guess,word):
"""checks if the user enters a single letter guess or the full word"""
if len(guess) > 1 and len(guess) == len(word):
return completeWordGuess(guess,word)
else:
return oneLetterGuess(guess, word)
def completeWordGuess(guess,word):
"""analyzes the complete word guess to check if is correct"""
global guessesLeft
if guess.lower() == word.lower(): #kept it lower case for simplicity
return True
else:
guessesLeft -=1
return False
def oneLetterGuess(guess,word):
"""checks to see if the single letter guess is included in the whole word"""
global guessedLetters
global guessesLeft
global guessesMade
if word.find(guess) == -1: #checks for failure on .find function
guessesLeft -= 1
guessesMade += 1
print('\nThat letter is not in the word. You have made {} incorrect guesses and have {} guesses left.'.format(guessesMade,guessesLeft))
guessedLetters = guessedLetters + guess.lower()
if allGuessedLetters(word):
return True
return False
def allGuessedLetters(word):
"""checks if all of the letters in the word have been uncovered/guessed"""
for letter in word:
if guessedLetters.find(letter) == -1: #checks for failure on .find function
return False
return True
def gameStats():
"""prints the final statistics of a play session"""
print('\nYou have played {} games and you have won {} rounds!'.format(roundsPlayed,roundsWon))
import random
guessesMade = 0
guessesLeft = 8
roundsPlayed = 0
roundsWon = 0
guessedLetters = ''
userMode = 1
while userMode==1:
if userMode == 1:
hangman()
guessesLeft = 8
guessedLetters = ''
userMode = eval(input('\nEnter 1 to play again, type 0 to end the game: '))
else:
break
gameStats()
The program seemingly runs well except for one part: If the user guesses the first letter of the word the program treats it as the complete right word and counts it as a win. So if I the word was 'rhino' and I guessed an 'r' it would show as a win. I don't see the mistake, however I have a feeling it is in the function completeWordGuess and I am not sure if I should be returning True for the first conditional. Any help is appreciated.

I think the main problem - and I say I think because I haven't had a chance to tear your code apart looking for other ways it's not working, and I probably won't - is that you've put your return False call in allGuessedLetters in the wrong place. This is what you had:
def allGuessedLetters(word):
"""checks if all of the letters in the word have been uncovered/guessed"""
for letter in word:
if guessedLetters.find(letter) == -1: #checks for failure on .find function
return False
return True
The problem is that, if the first letter does not return False, the control flow moves to return True, given that "return True" is a part of every iteration of the for loop. The only way that method doesn't return True is if the first letter hasn't been guessed yet.
If you alter it like so:
def allGuessedLetters(word):
"""checks if all of the letters in the word have been uncovered/guessed"""
for letter in word:
if guessedLetters.find(letter) == -1: #checks for failure on .find function
return False
return True
the method works as intended, because the control flow only moves to return True once the entirety of the for loop has been encountered and every letter has been evaluated, resulting in a termination if any of them don't match.

Related

How to insert a character into a string at a certain index? [duplicate]

This question already has answers here:
Changing one character in a string
(15 answers)
How to add a string in a certain position?
(10 answers)
Closed 11 months ago.
Is there a way to insert a character into a string at a certain index? I am making a hangman game, and as players guess the letters, the "_" or blanks become filled with letters.
import random
import sys
forever = True
lives = 7
chosen_word = "none"
playing = True
length = "none"
letter = "none"
guessed = 0
user_input = False
words = [
"snag", "jungle", "important", "peasant", "baggage", "hail", "clog", "pizza", "sauce", "password", "scream",
"newsletter", "bookend", "pro", "dripping", "pharmacist", "lie", "catalog", "ringleader", "husband", "laser",
"diagonal", "comfy", "myth", "dorsal", "biscuit", "hydrogen", "macaroni", "rubber", "darkness", "yolk", "exercise",
"vegetarian", "shrew", "chestnut", "ditch", "wobble", "glitter", "neighborhood", "dizzy", "fireside", "retail",
"drawback", "logo", "fabric", "mirror", "barber", "jazz", "migrate", "drought", "commercial", "dashboard",
"bargain",
"double", "download", "professor", "landscape", "ski", "goggles", "vitamin",
]
print("Let's play Hangman! Guess the letters!")
chosen_word = (random.choice(words))
length = len(chosen_word)
while playing:
print("_" * length)
letter = (input(f"You have {lives} guesses left."))
if letter in chosen_word:
location = chosen_word.find(letter)
insert_word = list(chosen_word)
print(insert_word)
print("Great Job! You got a letter!")
else:
print("That letter is not in the word.")
lives -= 1
while forever:
if lives <= 0:
playing = False
print("You lost. Good game.")
user_input = (input("Would you like to play again?"))
if user_input == "False":
print("Good bye.")
sys.exit()
elif user_input == "True":
playing = True
print("Let's play Hangman again! Guess the letters!")
I have been able to locate the index where the character is supposed to go in, but I have no idea how to make the character replace the "_" already in that spot. I am currently trying to convert the word into a list first and insert the character in there.
two things to keep in mind:
first-
you need to keep asking for input as long as player has guesses remaining or guessed the right letter.
second - you need to initialize hangman before the loop as a list as that is the only way you will keep track of players guess.
chosen_word = (random.choice(words))
length = len(chosen_word)
hangman = ['_' for i in range(length)]
while playing:
print("guess a letter")
letter = input()
if letter in chosen_word:
pos = chosen_word.index(letter)
chosen_word = list(chosen_word)
chosen_word[pos] = '-'
chosen_word = ''.join(chosen_word)
hangman[pos] = letter
print(hangman)
else:
lives -= 1
if lives == 0:
print("you lose")
playing = False
break
if '_' not in hangman:
print("winner")
playing = False
you are putting the input for guessing a letter outside the loop while playing is True. you need to keep it inside the conditional loop. As for inserting a character at an index for a string you just have to turn it into a list and then revert it back into a string using the .join method
Like #ddejohn said, convert it into a list first and then join the list back together after the insertion.
def insert_into_string(string, index, character):
string_list = list(string)
string_list[index] = character
return "".join(string_list)
Example usage:
>>> insert_into_string("H_llo world!", 1, "e")
'Hello world!'
Try to initialize a list using list comprehension, like this:
secret_word = ['_' for l in word_chosen]
Then use the find method at the word_choosen to find the position, and then use that position to replace the '_' in the secret_word list.
Here is a example code:
def start_game():
secret_word = 'programming'
guessed_word = ['_' for w in secret_word]
print(guessed_word)
while True:
guessed_letter = input('Guess a letter: ').lower()
found_at = 0
while secret_word.find(guessed_letter, found_at) > -1 and guessed_letter is not '':
found_at = secret_word.find(guessed_letter, found_at)
guessed_word[found_at] = guessed_letter
found_at += 1
# check for win condition
if '_' not in guessed_word:
print('Congratulation! You\'ve won!')
break
if guessed_letter == "exit":
print("Thanks for playing :D")
break
print(guessed_word)
if __name__ == '__main__':
start_game()
You can replace character from list then use join method to create a string
print ("WELCOME TO HANGMAN")
chosen_word = (random.choice(words))
chosen_word = chosen_word .upper()
word_ = '_'*len(chosen_word )
print (word_)
for chance in range (lives):
letter = (input(f"You have {lives-chance} guesses left."))
letter = letter .upper()
word_ = list(word_)
UI_pos= [pos for pos, char in enumerate(chosen_word ) if char == letter ]
for pos in UI_pos:
word_[pos] = letter
word_ = ''.join(word_)
print(word_)

Program abruptly stops based on the length of an arbitrary word

I am trying to create a hangman game. My program abruptly stops based on the length of the set of a random word chosen. It should only stop once you guess the word or you reach the maxinum number of guesses.
#Krish Patel
from random import randrange
def load_words():
word_list = ["mom"] #"apple","tomato","krish","name","pediatrician"]
return word_list
words_dict = load_words()
def get_word():
word=words_dict[randrange(0,len(words_dict))]
return word
secret_word = get_word()
letters_guessed = set()
local_guesses= 0
max_guesses = 6
num_correct_letters = 0
def play_hangman():
global secret_word
global letters_guessed
global max_guesses
global num_correct_letters
global local_guesses
print("Hello there! You are about to play a game of hangman!. Enjoy...")
while not word_guessed() and num_correct_letters != len(set(secret_word)) and local_guesses < max_guesses:
guess = input("Enter a letter: ")
if letters_guessed.add(guess) != letters_guessed:
local_guesses += 1
letters_guessed.add(guess)
else:
print("You already guessed that letter!")
print_guessed()
word_guessed()
if word_guessed() == True:
print("You have won! The secret word was: " + secret_word)
secret_word = get_word()
letters_guessed = set()
local_guesses= 0
max_guesses = 6
num_correct_letters = 0
if local_guesses >= max_guesses:
print("You went over your maximum number of allotted guesses. The secret word was: " + secret_word)
secret_word = get_word()
letters_guessed = set()
local_guesses= 0
max_guesses = 6
num_correct_letters = 0
def print_guessed():
global secret_word
global letters_guessed
print("Your guesses are " + str(letters_guessed))
def word_guessed():
global secret_word
global letters_guessed
global num_correct_letters
for i in set(secret_word):
if i in letters_guessed:
num_correct_letters += 1
return num_correct_letters == len(set(secret_word))
What should happen is that you have 6 guesses to figure out the word is mom, but the program ends after two tries.
When you call word_guessed you don't reset num_correct_letters back to 0 before counting the number of correct letters. So once you guess a single correct letter, this counter keeps increasing even though you don't guess other letters correctly. If it reaches len(set(secret_word)), the loop ends.
There's no need to check num_correct_letters in your while condition, since word_guessed() already checks it.
You don't need the loop in word_guessed, and yo don't need the variable num_correct_letters, you can simply write:
def word_guessed():
global secret_word
global letters_guessed
return set(secret_word).issubset(letters_guessed)
You're also not testing whether guess is already in letters_guessed correctly. Use guess not in letters_guessed.
You should initialize all the variables once at the beginning of the function, rather than repeating that in both of the if statements at the end. And there's no need for them to be global variables, just pass them as function parameters.
from random import randrange
def load_words():
word_list = ["mom","apple","tomato","krish","name","pediatrician"]
return word_list
words_dict = load_words()
def get_word():
word=words_dict[randrange(0,len(words_dict))]
return word
def play_hangman():
secret_word = get_word()
letters_guessed = set()
local_guesses= 0
max_guesses = 6
print("Hello there! You are about to play a game of hangman!. Enjoy...")
while not word_guessed(secret_word, letters_guessed) and local_guesses < max_guesses:
guess = input("Enter a letter: ")
if guess not in letters_guessed:
letters_guessed.add(guess)
local_guesses += 1
letters_guessed.add(guess)
else:
print("You already guessed that letter!")
print_guessed(letters_guessed)
if word_guessed(secret_word, letters_guessed):
print("You have won! The secret word was: " + secret_word)
elif local_guesses >= max_guesses:
print("You went over your maximum number of allotted guesses. The secret word was: " + secret_word)
def print_guessed(letters_guessed):
print("Your guesses are " + str(letters_guessed))
def word_guessed(secret_word, letters_guessed):
return set(secret_word).issubset(letters_guessed)
play_hangman()

How to end game in hangman if ALL letters in the secret word are in guessed_letters list

Im trying to create a for loop end game by doing for "every letter in my secret word if All letters are in gussed_letters then end game."
Ive tried to make a correct_letters list and see if all the letters in my secret word are in my correct_letters list then end the game but i cant seem to get it to work.
import random
words = ['apple',' python','parent'] #Make list of words
def randomword(words): #takes in list words
return random.choice(words) #returns a random element back
chosenword = randomword(words) # make a variable equal to the function
#variables (tries you get and list to letters gussed. )
tries = 10
guess_letters = []
def dashshow(guess_letters): #takes in guess_letters
for letter in chosenword: #checks each letter in chosenword
if letter in guess_letters: #if letter in guess_letters print that letter
print(letter)
else: #or else print a dash
print('-')
def playgame(tries):# Takes tries
while tries != 0: #While tries is not 0
guess = str(input("Guess a letter of the word: ")).lower() #Ask for a guess
guess_letters.append(guess) #add guess to guess_letters list
if guess in chosenword: #if your guess in chosenword
print("You got a letter correct!")
tries -= 1
elif guess not in chosenword:
print("That letter is not in the word")
tries -= 1
dashshow(guess_letters) # last call the dashshow function
randomword(words)
playgame(tries)
I made the dashshow function count how many dashes left and return a value for whether any are left. If not, the game is over and has been won.
import random
words = ['apple',' python','parent'] #Make list of words
def randomword(words): #takes in list words
return random.choice(words) #returns a random element back
chosenword = randomword(words) # make a variable equal to the function
#variables (tries you get and list to letters gussed. )
tries = 10
guess_letters = []
def dashshow(guess_letters): #takes in guess_letters
dashes = 0
for letter in chosenword: #checks each letter in chosenword
if letter in guess_letters: #if letter in guess_letters print that letter
print(letter)
else: #or else print a dash
print('-')
dashes = dashes+1
return(dashes>0)
def playgame(tries):# Takes tries
keepPlaying = True
while (tries != 0) and keepPlaying: #While tries is not 0
guess = str(input("Guess a letter of the word: ")).lower() #Ask for a guess
guess_letters.append(guess) #add guess to guess_letters list
if guess in chosenword: #if your guess in chosenword
print("You got a letter correct!")
tries -= 1
elif guess not in chosenword:
print("That letter is not in the word")
tries -= 1
if not dashshow(guess_letters): # last call the dashshow function
keepPlaying=False
print("you win!")
randomword(words)
playgame(tries)
you can create variable is list letters of secret word, remove letter if it similars guess
Try this
def playgame(tries):# Takes tries
chosenword_ = list(chosenword)
while tries != 0 and chosenword_: #While tries is not 0
guess = str(input("Guess a letter of the word: ")).lower() #Ask for a guess
guess_letters.append(guess) #add guess to guess_letters list
if guess in chosenword: #if your guess in chosenword
print("You got a letter correct!")
tries -= 1
try:
chosenword_.remove(guess)
except ValueError:
pass
elif guess not in chosenword:
print("That letter is not in the word")
tries -= 1
dashshow(guess_letters) # last call the dashshow function

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

If Statement Firing Regardless of Conditions, Variable not Aggregating Past One

Please see my comments. They explain my problems. I have an if statement that is firing no matter what and a variable that is not aggregating properly and I don't know why. Thanks in advance. (The following is a hangman program currently in development. printBody() will eventually print out the whole man.)
import random
words = []
lettersGuessed = []
isGuessed = 0
wordFile = open(r'C:\Users\Sarah\PycharmProjects\hangman\words.txt')
for word in wordFile:
words.append(word.strip())
limbCount = 0
def printBody(limbCount):
limbCount += 1
if limbCount == 1:
print("\n0")
elif limbCount == 2:
print("\n0")
print("\n |")
return limbCount
mysteryWord = random.choice(words)
while len(mysteryWord) <= 1:
mysteryWord = random.choice(words)
for letter in mysteryWord:
print("?", end = "")
print("\n")
def isWon(mysteryWord, lettersGuessed):
#win conditions
count = 0
for letter in mysteryWord:
if letter in lettersGuessed:
count += 1
if count == len(mysteryWord):
isGuessed = 1
return isGuessed
count = 0
victory = 0
while not victory:
guess = input("Guess a letter \n")
if guess.upper() or guess.lower() in mysteryWord:
lettersGuessed.append(guess)
for letter in mysteryWord:
if letter in lettersGuessed:
print(letter, end ='')
else:
print("?", end = '')
#this statement is firing no matter what and I don't know why
if guess.upper() or guess.lower() not in mysteryWord:
#when I call printBody() limbCount increases to one but then stays there. It won't go up to two or three.
printBody(limbCount)
print("\n")
count = 0
victory = isWon(mysteryWord, lettersGuessed)
print("Congratulations, you correctly guessed ", mysteryWord)
try:
guess.upper() not in mysteryWord or guess.lower() not in mysteryWord
I believe you are having this problem since it is checking "is guess.upper() truthy", and since it is a string (which is truthy) it will enter that if statement

Categories