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
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()
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 am trying to make a hangman game at the minute and this is the code so far:
word = raw_input("Please enter a word")
correctguesses = []
wrongguesses = []
guesscorrect = False
while guesscorrect == False:
guess = raw_input("Guess a letter")
if len(guess) != 1:
print "Your guess was more than one letter"
for i in word:
if guess == i in word:
print "correct"
correctguesses.append(guess)
print "here are your correct guesses so far" ,(''.join(correctguesses))
for i in word:
if guess != i in word:
print "incorrect"
wrongguesses.append(guess)
print "here are your wrong guesses so far:", (''.join(wrongguesses))
my output:
correct/
here are your correct guesses so far:/ e/
incorrect/
incorrect/
incorrect/
incorrect/
here are your wrong guesses so far:/ eeee/
It is doing that because it isn't the correct letter for the 4 other letters in hello (which was the word).
word = raw_input("Please enter a word")
correctguesses = []
wrongguesses = []
guesscorrect = False
while guesscorrect == False:
guess = raw_input("Guess a letter")
if len(guess) != 1:
print "Your guess was more than one letter"
continue #to prompt for input again
for i in word:
if guess == i: #i will be a letter in the word
print "correct"
correctguesses.append(guess)
print "here are your correct guesses so far" ,(''.join(correctguesses))
for i in word:
if guess != i: #put this case in the else block of the if in the previous loop and remove this loop
print "incorrect"
wrongguesses.append(guess)
print "here are your wrong guesses so far:", (''.join(wrongguesses))
I have commented some of the details.
This course might help with basics of python and programming.
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.
I'm working on finishing my first simple program in python, a 2 player (user vs computer AI) word/letter guessing game.
I've got the bulk of the code finished, but I'm trying to get my loops sorted out so that the game will properly alternate between the user and the AI. I want to make it so that the game alternates back and forth between user and AI turns, until the world has been fully revealed. At that point, the player to guess the most letters correctly wins a point. The computer moderator picks another word and starts again. The first player to five points wins the game.
I'm not sure where to start with this. I'm still quite new to python/coding in general and I have a difficult time understanding the order in which events occur. I know I need some kind of master loop that remains True as long as the word has yet to be fully revealed, but that's about it.
Also, any other suggestions as to how to optimize the code below or clean it up in anyway would be appreciated!
import random
#set initial values
player1points= 0
ai= 0
userCorrectLetters= ''
aiCorrectLetters=''
wrongLetters=''
wrongPlace= ''
correctLetters = ''
notInWord = ''
endGame = False
allLetters = set(list('abcdefghijklmnopqrstuvwxyz'))
alreadyGuessed = set()
userGuessPosition = 0
availLetters = allLetters.difference(alreadyGuessed)
#import wordlist, create mask
with open('wordlist.txt') as wordList:
secretWord = random.choice(wordList.readlines()).strip()
print (secretWord)
secretWordLength = len(secretWord)
def displayGame():
mask = '_' * len(secretWord)
for i in range (len(secretWord)):
if secretWord[i] in correctLetters:
mask = mask[:i] + secretWord[i] + mask [i+1:]
for letter in mask:
print (letter, end='')
print (' ')
print ('letters in word but not in correct location:', wrongPlace)
print ('letters not in word:', wrongLetters)
##asks the user for a guess, assigns input to variable
def getUserGuess(alreadyGuessed):
while True:
print ('enter your letter')
userGuess = input ()
userGuess= userGuess.lower()
if len(userGuess) != 1:
print ('please enter only one letter')
elif userGuess in alreadyGuessed:
print ('that letter has already been guessed. try again')
elif userGuess not in 'abcdefjhijklmnopqrstuvwxyz':
print ('only letters are acceptable guesses. try again.')
else:
return userGuess
def newGame():
print ('yay. that was great. do you want to play again? answer yes or no.')
return input().lower().startswith('y')
userTurn=True
while userTurn == True:
displayGame ()
print ('which character place would you like to guess. Enter number?')
userGuessPosition = int(input())
slice1 = userGuessPosition - 1
##player types in letter
guess = getUserGuess(wrongLetters + correctLetters)
if guess== (secretWord[slice1:userGuessPosition]):
correctLetters = correctLetters + guess
print ('you got it right! ')
displayGame()
break
elif guess in secretWord:
wrongPlace = wrongPlace + guess
print ('that letter is in the word, but not in that position')
displayGame()
break
else:
wrongLetters = wrongLetters + guess
print ('nope. that letter is not in the word')
displayGame()
break
print ("it's the computers turn")
aiTurn=True
while aiTurn == True:
aiGuessPosition = random.randint(1, secretWordLength)
print (aiGuessPosition)
aiGuess=random.sample(availLetters, 1)
print ('the computer has guessed', aiGuess, "in position", + aiGuessPosition)
if str(aiGuess) == (secretWord[slice1:userGuessPosition]):
correctLetters = correctLetters + guess
print ('this letter is correct ')
break
elif str(aiGuess) in secretWord:
aiCorrectLetters = aiCorrectLetters + guess
correctLetters = correctLetters + guess
print ('that letter is in the word, but not in that position')
break
else:
wrongLetters = wrongLetters + guess
print ('that letter is not in the word')
break
displayGame()
break
It looks like it will only do two turns and then exit?
What is happening is that it hits your first while loop, and starts to evaluate the code inside. It does some stuff, and then hits the break which breaks you out of the loop and execution resume after the end of your first loop. It then does the same thing with the second loop, hits the end of you program and exits.
I would suggest the following refactoring:
put all of the stuff you have under your while loops into two function user_play and computer_play
write a loop something like
this
usr_pts = 0
cmp_pts = 0
while (usr_pts < 5 and cmp_pts < 5):
solved_word = False
# set up word
user_turn = False
user_correct_guess = 0
ai_correct_guess = 0
while not solved_word:
user_turn = not user_turn
if user_turn:
guess = play_user(...)
else:
guess = computer_play(...)
# what ever accounting you need to do
is_guess_in_word = test_guess_in_word(guess, ...)
if is_guess_in_word:
if user_turn:
user_correct_guess += 1
else:
ai_correct_guess += 1
solved_word = sort_out_if_word_solved(...)
if user_correct_guess > ai_correct_guess:
usr_pts += 1
elif user_correct_guess < ai_correct_guess:
cmp_pts +=1
else:
# a tie
pass