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()
Related
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()
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
How do I end this game? If the whole word is guessed it's over or you loose all life, but I am unable to end it if someone guesses all letters one by one.
secret_word = "something".upper()
lifes = u'\u2764'
total_lifes = 5
print("You have 5 lifes in total to guess the answer")
guess = None
for_list = "?"*len(secret_word)
my_list = list(for_list)
def change_user_output(value):
for j in range(0, len(secret_word)):
if (value == secret_word[j]):
my_list[j] = value
new_user_output = " ".join(my_list)
print(new_user_output)
while total_lifes > 0:
print(lifes * total_lifes)
print("Guess any letter : ")
guess = input().upper()
if(guess == secret_word):
print("WOW that is correct, the secret word is %s"%secret_word)
break
if(guess in secret_word):
print("You guessed it right %s is in SECRET WORD"%guess)
change_user_output(guess)
else:
print("There is no such letter in the SECRET WORD, you loose a life")
change_user_output(guess)
total_lifes -= 1
if total_lifes == 0:
print("You've lost all lifes, GAME OVER FOR YOU")
print("The SECRET WORD was : %s"%"".join(secret_word))
The problem is that if (guess == secret_word): will always be False since guess is a single letter and it gets replaced by a new input every iteration guess = input().upper(). So your loop will never quit in case of correct guess, it will quit only when you finish the lives.
You could add the following to check if the guessed letters match those in the secret word:
if(guess in secret_word):
print("You guessed it right %s is in SECRET WORD"%guess)
change_user_output(guess)
# New code below here.
if set(list(secret_word)) == set(my_list):
print("WOW that is correct, the secret word is %s"%secret_word)
break
You create a set of all letters needed. You add each guessed letter to another set.
If the set of needed letters is a subset of the guessed letters set, you are done:
secret_word = "apple".upper()
lifes = '#'
total_lifes = 5
print("You have 5 lifes in total to guess the answer")
guess = None
for_list = "?"*len(secret_word)
my_list = list(for_list)
characters_needed = set(secret_word) # set of all letters needed
characters_guessed = set() # set of guessed letters
len_secret = len(secret_word)
def change_user_output(value):
for j in range(0, len(secret_word)):
if (value == secret_word[j]):
my_list[j] = value
new_user_output = " ".join(my_list)
print(new_user_output)
while total_lifes > 0:
print(lifes * total_lifes)
print("Guess any letter : ")
guess = input().upper()
# check for correct lenghts of input:
if len(guess) not in (1,len_secret):
print("1 letter or the whole word! Try again.")
continue
if(guess == secret_word):
print("WOW that is correct, the secret word is {}".format(secret_word))
elif(len(guess) > 1):
print("Thats not the SECRET WORD.")
total_lifes -= 1
continue
# if you input a whole word, this will decrease the lives
# as no multiletter-input can be in your set of characters
if(guess in characters_needed):
print("You guessed it right {} is in SECRET WORD".format(guess))
characters_guessed.add(guess)
change_user_output(guess)
else:
print("There is no such letter in the SECRET WORD, you loose a life")
change_user_output(guess)
total_lifes -= 1
if (characters_needed.issubset(characters_guessed)):
print("You guessed all the characters. The secret word is {}".format(secret_word))
break
if total_lifes == 0:
print("You've lost all lifes, GAME OVER FOR YOU")
print("The SECRET WORD was : %s"%"".join(secret_word))
Output (for a,p,l,e):
#####
Guess any letter : a
You guessed it right A is in SECRET WORD
A ? ? ? ?
#####
Guess any letter : p
You guessed it right P is in SECRET WORD
A P P ? ?
#####
Guess any letter : l
You guessed it right L is in SECRET WORD
A P P L ?
#####
Guess any letter : e
You guessed it right E is in SECRET WORD
A P P L E
You guessed all the characgters. The secret word is APPLE
I also added some safeguarding around allowing whole word or 1 character to be inputted.
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
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.