Output Error in Hangman Game [duplicate] - python

This question already has answers here:
Why do these list operations (methods: clear / extend / reverse / append / sort / remove) return None, rather than the resulting list?
(6 answers)
Closed 6 years ago.
I need to write a couple functions that make up a hangman game. I've the code, but I keep getting an error and my code doesn't run completely, so I don't even know if my code is correct. This is the code I have:
def isWordGuessed(secretWord, lettersGuessed):
'''
secretWord: string, the word the user is guessing
lettersGuessed: list, what letters have been guessed so far
returns: boolean, True if all the letters of secretWord are in lettersGuessed;
False otherwise
'''
if lettersGuessed == []:
return False
else:
for i in secretWord:
if i not in lettersGuessed:
return False
else:
if i == secretWord[-1]:
return True
def getGuessedWord(secretWord, lettersGuessed):
lst= ''
for e in secretWord:
if e in lettersGuessed:
lst += e
else:
lst += '_'
return lst
def getAvailableLetters(lettersGuessed):
'''
lettersGuessed: list, what letters have been guessed so far
returns: string, comprised of letters that represents what letters have not
yet been guessed.
'''
Alletters = string.ascii_lowercase
result = list(Alletters)
for i in lettersGuessed:
if i in result:
result.remove(i)
transtring = ''.join(result)
return transtring
def hangman(secretWord):
'''
secretWord: string, the secret word to guess.
Starts up an interactive game of Hangman.
* At the start of the game, let the user know how many
letters the secretWord contains.
* Ask the user to supply one guess (i.e. letter) per round.
* The user should receive feedback immediately after each guess
about whether their guess appears in the computers word.
* After each round, you should also display to the user the
partially guessed word so far, as well as letters that the
user has not yet guessed.
Follows the other limitations detailed in the problem write-up.
'''
print("Welcome to the Hangman game!")
print("I am thinking of a word that is " + str(len(secretWord)) + " letters!")
guesses = 8
lettersGuessed = []
Alletters = string.ascii_lowercase
while guesses > 0:
print("You have " + str(guesses) + " guesses left")
print("Available letters: " + str(Alletters))
letters = input("Please guess a letter: ")
if type(letters) != str:
print("Invalid input! please enter one letter!")
else:
letterslower = letters.lower()
lettersGuessed = lettersGuessed.append(letterslower)
if letterslower not in Alletters:
print("Opps! you have already guessed that letter: " + getGuessedWord(secretWord, lettersGuessed))
else:
if isWordGuessed(secretWord, lettersGuessed) == "True":
print("Congradualations, you won!")
else:
print("Good guess: " + getGuessedWord(secretWord, lettersGuessed))
guesses -= 1
Alletters = getAvailableLetters(lettersGuessed)
print("You have ran out of guess, the word is " + str(secretWord))
This is the output (the error is in yellow):
Welcome to the Hangman game!
I am thinking of a word that is 1 letters!
You have 8 guesses left
Available letters: abcdefghijklmnopqrstuvwxyz
Please guess a letter: c
Traceback (most recent call last):
File "submission.py", line 81, in hangman
if isWordGuessed(secretWord, lettersGuessed) == "True":
File "simple_grade_hangman.py", line 107, in isWordGuessed
if letter not in lettersGuessed:
TypeError: argument of type 'NoneType' is not iterable
What's happening here?

Your error stems from this line:
lettersGuessed = lettersGuessed.append(letterslower)
This modifies the list in-place and returns None. You're operating under the assumption that it returns a reference to the modified list, which it doesn't.
So, when you pass it as a parameter to function isWordGuessed and if i not in lettersGuessed is executed, an error will be raised since lettersGuessed is None and None can't be used as the target of an in expression.
Simply modify with append and the changes are kept:
lettersGuessed.append(letterslower)
Also, comparing a boolean (True) against a str ("True") will give you false results:
>>> True == 'True'
False
Instead, since isWordGuessed returns booleans, use it's return value in the if clause directly:
if isWordGuessed(secretWord, lettersGuessed):

Related

How do you insert repeated values with distinct indices into an empty list in python?

I'm trying to build a basic program where the computer selects a word out of a pre-existing list (called "words") and the user must guess the appropriate letters to guess the word. This is what the main function looks like so far:
def game():
word = random.choice(words)
while ' ' or '-' in word:
word = random.choice(words)
if ' ' or '-' not in word:
break
print(f'Hint: The chosen word is {len(word)} letters long')
letters = list(word)
progress = []
while True:
guess = str(input('Guess a letter: '))
if len(guess) > 1:
print('Sorry, guess a single letter: ')
if guess in word:
print(f'The letter {guess} is in the word')
for i, j in enumerate(letters):
if progress.count(guess) >= letters.count(guess):
break
elif j == guess:
progress.insert(i, j)
print('Current progress: ' + '-'.join(progress))
if len(progress) == len(word):
if letters[:] == progress[:]:
print('Congrats! You found the word: ' + str(word))
break
elif guess not in word:
print(f'The letter {guess} is not in the word: Try Again')
continue
My issue is with the for loop where I use enumerate(y) and the respective "elif j == guess" condition. I noticed that when running the function, the code works if the letters that are repeated are successive (ex: in the word "chilly", if I type in "l", the function correctly displays the two l's and the game works as intended). However, if the letters are repeated separately (ex: the word "cologne"), the function doesn't insert the "l" between the two o's, and keeps the two o's together regardless, thus preventing the proper word from ever being guessed. Is there a different method I could use to fix this problem?
You should remember the letters already guessed and simplyfiy the printing to any letter that you remember and use - for any other letter in the word.
Your errror stems from your list and counting method to remember which letters to print or not.
I fixed your incorrect if-condition (see How to test multiple variables against a value? for more on that).
import random
# supply list of words to function to avoid globals
def game(words):
word = random.choice(words)
# fixed your check ... not sure why you do that
while ' ' in word or '-' in word:
word = random.choice(words)
# no break needed, will break if no space/- in
print(f'Hint: The chosen word is {len(word)} letters long')
# remember which letters where guessed already
guesses = set()
while True:
guess = input('Guess a letter: ') # no str needed it is already a str
if len(guess) > 1:
print('Sorry, guess a single letter: ')
continue # back to while loop
# add to guessed letters
guesses.add(guess)
# print message
if guess in word:
print(f'The letter {guess} is in the word')
else:
print(f'The letter {guess} is not in the word: Try Again')
continue # back to while loop
print('Current progress: ', end="")
# assume we have all letters guessed
done = True
for idx, letter in enumerate(word):
if letter in guesses:
# print letter if already guessed
print(letter, end="")
else:
# invalidate assumption and print -
done = False
print("-",end="")
print()
# if assumption not invalidated: done
if done:
print('Congrats! You found the word: ' + str(word))
break
game(["eye", "ear", "egg", "anvil"])
Output:
Hint: The chosen word is 3 letters long
Guess a letter: The letter e is in the word
Current progress: e-e
Guess a letter: The letter r is not in the word: Try Again
Current progress: e-e
Guess a letter: The letter y is in the word
Current progress: eye
Congrats! You found the word: eye

How do I have a list accept lowercase in place of capitalized letters in Hangman for a randomized list in Python 3?

I have been looking around to see if I could find something that could help, but nowhere has an answer for what I'm looking for. I have a Hangman game I'm doing for a final project in one of my classes, and all I need is to make it so if a word has a capital letter, you can input a lowercase letter for it. This is the code.
import random
import urllib.request
wp = "http://svnweb.freebsd.org/csrg/share/dict/words?view=co&content-
type=text/plain"
response = urllib.request.urlopen(wp)
long_txt = response.read().decode()
words = long_txt.splitlines()
###########
# Methods #
###########
def Run():
dashes1 = "-" * len(word)
dashes2 = "-" * len(word2)
used_letter = []
dashes = dashes1 + " " + dashes2
#dashes ="-" * len(secretWord)
guessesLeft = 6
while guessesLeft > -1 and not dashes == secretWord:
print(used_letter)
print(dashes)
print (str(guessesLeft))
guess = input("Guess:")
used_letter.append(guess)
if len(guess) != 1:
print ("Your guess must have exactly one character!")
elif guess in secretWord:
print ("That letter is in the secret word!")
dashes = updateDashes(secretWord, dashes, guess)
else:
print ("That letter is not in the secret word!")
guessesLeft -= 1
if guessesLeft < 0:
print ("You lose. The word was: " + str(secretWord))
print(dashes)
else:
print ("Congrats! You win! The word was: " + str(secretWord))
print(dashes)
def updateDashes(secret, cur_dash, rec_guess):
result = ""
for i in range(len(secret)):
if secret[i] == rec_guess:
result = result + rec_guess
else:
result = result + cur_dash[i]
return result
########
# Main #
########
word = random.choice(words)
word2 = random.choice(words)
#print(word)
#print(word2)
secretWord = word + " " + word2 # can comment out the + word2 to do one
word or add more above to create and combine more words will have to adjust
abouve in Run()
splitw = ([secretWord[i:i+1] for i in range(0, len(secretWord), 1)])
print (splitw)
Run()
any bit of help is appreciated. The website I'm using has a bunch of words that are being used for the words randomly generated. Some are capitalized, and I need to figure out how to let the input of a letter, say a capital A, accept a lowercase a and count for it.
you could compare after you converted everything to lowercase.
e.g. you could do
secretWord = word.lower() + " " + word2.lower() # that should make your secret all lowercase
for the input you should do the same:
guess = input("Guess:").lower()
after that it should not matter if it is upper or lower case. it should always match if the letter is the correct one.
hope that helps
Simply check everything in lowercase:
[...]
elif guess.lower() in secretWord.lower():
[...]
and so on.
I would just change this line:
while guessesLeft > -1 and not dashes == secretWord:
to:
while guessesLeft > -1 and not dashes.lower() == secretWord.lower():
This way you are always comparing lower-case representations of the user's input to the lower-case representation of your secretWord. Since this is the main loop for your game, you want to break out of this as soon as the user's guess matches your word regardless of case. Then later in your code, you will still check whether they had any guesses left, and print out their answer and the secret word as before.
No other changes required, I think.
You could just force all comparisons to be made in the same Case, such as lowercase.
Let’s say that your word is "Bacon". and someone enters "o".
That will be a match because quite obviously “o” equals “o” so you can cross that letter off the list of letters left to guess.
But in the case that someone enters “b” then b is NOT equal to “B”.
So why not just force all letters to be compared using the same case?
So your comparison will be like
elif guess.Lower() in secretWord.Lower()
My python is rusty as hell, but the idea here should do what you want to do

Merging strings in python

I'm making a hangman game and I need to update the table showing the correct letters. So far the program prints this
Enter a word: hello
[-----] You have 6 guesses left, enter a letter: h
Correct!
[H----] You have 6 guesses left, enter a letter: e
Correct!
[-E---] You have 6 guesses left, enter a letter: l
Correct!
[--LL-] You have 6 guesses left, enter a letter: o
Correct!
[----O] You have 6 guesses left, enter a letter:
What I need the program to do is combine the strings for example [H----] --> [HE---] and so on. How would I do this? As well as end the game when there are no more dashes left.
An example of what I want the program to look like is
[H----]
[HE---]
the program also has to work in a random order for example...
[----O]
[-E--O]
[HE--O]
[HELLO]
This is my code so far
Just loop through the string to be guessed and show either the letter, if that letter was already guessed or '_' in case it hasn't.
In [127]: s = "Apple"
In [128]: already_guessed = ['p', 'e']
In [129]: '[' + ''.join([letter if letter in already_guessed else '_' for letter in s]) + ']'
Out[129]: '[_pp_e]'
Instead of recomputing display_string with "-", use the previous value of display_string. Note: You need to offset the index of display_string because of your brackets.
display_string = "[" + "".join([x if x == letter else display_string[i + 1] for i, x in enumerate(word)]) + "]"
Here's my attempt at an answer, wrote this up before you put up your code, so it may not be what you're looking for, but it works.
def hangman():
answer = raw_input('Enter a word: ') # getting the word
guesses = 6 # number of starting guesses
word = '[' + '-'*len(answer) + ']' # this is the string of interest to be printed
while True:
print word, 'You have %d guesses left' % guesses,
if guesses == 0 or '-' not in word: break
# game finishes if word is guessed, or guesses run out
letter = raw_input(', enter a letter: ') # guess a letter
guesses -= 1 # decrease number of guesses by 1 each time
for index, char in enumerate(answer): # iterate through all letters in answer
if letter == char: # check if guessed letter is in the answer
wordlist = list(word) # representing the word as a list to allow mutation
wordlist[index+1] = letter # mutate the correctly guessed letter
word = ''.join(wordlist) # recombining the list into a string

Scrabble wordgame mistake in python

I'm having trouble with a word game I'm trying to make, scrabble.
A part of my code,where it eventually gives the error, is:
def is_valid_word(word, hand, word_list):
"""
Returns True if word is in the word_list and is entirely
composed of letters in the hand. Otherwise, returns False.
Does not mutate hand or word_list.
word: string
hand: dictionary (string -> int)
word_list: list of lowercase strings
"""
hand_copy = hand.copy()
if word not in wordList:
return False
for char in word:
if char not in hand_copy:
return False
else:
hand_copy[char] -= 1
if hand_copy[char] < 0:
return False
return True
def play_hand(hand, words):
"""
Allows the user to play the given hand, as follows:
* The hand is displayed.
* The user may input a word.
* An invalid word is rejected, and a message is displayed asking
the user to choose another word.
* When a valid word is entered, it uses up letters from the hand.
* After every valid word: the score for that word is displayed,
the remaining letters in the hand are displayed, and the user
is asked to input another word.
* The sum of the word scores is displayed when the hand finishes.
* The hand finishes when there are no more unused letters.
The user can also finish playing the hand by inputing a single
period (the string '.') instead of a word.
hand: dictionary (string -> int)
words: list of lowercase strings
"""
n = HAND_SIZE
display_hand(hand)
print "You may enter '.' if you cannot create a word."
word = raw_input("Please enter a word:")
score = 0
totalscore = 0
while not len(hand) == 0 and not word == ".":
print word
if is_valid_word(word, hand, load_words()) == False:
print "That is not a valid word"
word = raw_input("Please enter a word:")
elif is_valid_word(word, hand, load_words()) == True:
score = get_word_score(word, n)
print "You word was worth " + str(score) + " points."
totalscore = totalscore + score
print "Your total score is: " + str(totalscore) + "."
print "Here is your updated hand."
hand = update_hand(hand,word)
display_hand(hand)
if len(hand) != 0:
word = raw_input("Please enter a word:")
print "Your total score is: " + str(totalscore) + "."
return
def play_game(words):
"""
Allow the user to play an arbitrary number of hands.
* Asks the user to input 'n' or 'r' or 'e'.
* If the user inputs 'n', let the user play a new (random) hand.
When done playing the hand, ask the 'n' or 'e' question again.
* If the user inputs 'r', let the user play the last hand again.
* If the user inputs 'e', exit the game.
* If the user inputs anything else, ask them again.
"""
hand = deal_hand(HAND_SIZE)
while True:
cmd = raw_input('Enter n to deal a new hand, r to replay the last hand, or e to end game: ')
if cmd == 'n':
hand = deal_hand(HAND_SIZE)
play_hand(hand, words)
print
elif cmd == 'r':
play_hand(hand, words)
print
elif cmd == 'e':
break
else:
print "Invalid command."
In my opninion this should work. I can start the game, deal a new hand, replay the last hand or end a game. But when I try to make a word from the given letters it gives this error:
Traceback (most recent call last):
File "wordgames.py", line 257, in <module>
play_game(words)
File "wordgames.py", line 241, in play_game
play_hand(hand, words)
File "wordgames.py", line 204, in play_hand
if is_valid_word(word, hand, load_words()) == False:
File "wordgames.py", line 163, in is_valid_word
if word not in wordList:
NameError: global name 'wordlist' is not defined
I've been trying a lot, but nothing helps... Please can somebody help me fixing this?
Thanks in advance!
The error is clearly stated at the bottom of the traceback:
File "wordgames.py", line 163, in is_valid_word
if word not in wordList:
NameError: global name 'wordlist' is not defined
ie you don't define wordList - the input variable is called word_list.
Also you should fix the indentation in your question to make it clear where the function definition ends and you return to global scope.
As jonsharpe points out, your traceback is also inconsistent (wordlist instead of wordList)

Python 3 : TypeError: Type str doesn't support the buffer API

I'm getting the error :
TypeError: Type str doesn't support the buffer API
when trying to run the following code :
import random
import string
WORDLIST_FILENAME = "words.txt"
def loadWords():
"""
Returns a list of valid words. Words are strings of lowercase letters.
Depending on the size of the word list, this function may
take a while to finish.
"""
print ("Loading word list from file...")
# inFile: file
inFile = open(WORDLIST_FILENAME, 'rb', 0)
# line: string
line = inFile.readline()
# wordlist: list of strings
wordlist = line.split()
print (" ", len(wordlist), "words loaded.")
return wordlist
def chooseWord(wordlist):
"""
wordlist (list): list of words (strings)
Returns a word from wordlist at random
"""
return random.choice(wordlist)
# end of helper code
# -----------------------------------
# Load the list of words into the variable wordlist
# so that it can be accessed from anywhere in the program
wordlist = loadWords()
def isWordGuessed(secretWord, lettersGuessed):
'''
secretWord: string, the word the user is guessing
lettersGuessed: list, what letters have been guessed so far
returns: boolean, True if all the letters of secretWord are in lettersGuessed;
False otherwise
'''
for x in secretWord :
if x not in lettersGuessed :
return False
return True
def getGuessedWord(secretWord, lettersGuessed):
'''
secretWord: string, the word the user is guessing
lettersGuessed: list, what letters have been guessed so far
returns: string, comprised of letters and underscores that represents
what letters in secretWord have been guessed so far.
'''
guessedWord=['_']*len(secretWord)
for x in lettersGuessed :
## 1** find the occurences of x in secretWord
occurences = []
for i, j in enumerate(secretWord):
if j == x:
occurences.append(i)
## 2* go to the same indices in guessedWord and replace them by x
for i in occurences :
guessedWord[i]=x;
return ''.join(guessedWord)
def getAvailableLetters(lettersGuessed):
'''
lettersGuessed: list, what letters have been guessed so far
returns: string, comprised of letters that represents what letters have not
yet been guessed.
'''
available_Letters=[]
all_letters=list(string.ascii_lowercase)
for x in all_letters :
if (x not in lettersGuessed):
available_Letters.append(x)
return ''.join(available_Letters)
def hangman(secretWord):
'''
secretWord: string, the secret word to guess.
Starts up an interactive game of Hangman.
* At the start of the game, let the user know how many
letters the secretWord contains.
* Ask the user to supply one guess (i.e. letter) per round.
* The user should receive feedback immediately after each guess
about whether their guess appears in the computers word.
* After each round, you should also display to the user the
partially guessed word so far, as well as letters that the
user has not yet guessed.
Follows the other limitations detailed in the problem write-up.
'''
print(" Welcome to the game, Hangman!")
print("I am thinking of a word that is 4 letters long.")
number_of_guesses = 8
lettersGuessed = []
while True :
print("--------------------------------")
print ("You have " , number_of_guesses , "left !")
print("Available letters : " , getAvailableLetters(lettersGuessed) )
print("Please guess a letter : ")
guess = input()
while True:
print("Please guess a letter : ")
if guess in lettersGuessed:
print("Oops ! you've already guessed that letter :" , getGuessedWord(secretWord, lettersGuessed))
break
else :
if(guess in secretWord ) :
lettersGuessed.append(guess)
print("Good guess:", getGuessedWord(secretWord, lettersGuessed) )
else :
number_of_guesses-=1
print("---------------------------------")
if(number_of_guesses == 0) :
print(" Sorry, you ran out of guesses. The word was else. ")
break
if(isWordGuessed(secretWord, lettersGuessed)):
print(" Congratulations, you won!")
break
secretWord = chooseWord(wordlist).lower()
hangman(secretWord)
the line that is causing the error is :
if(guess in secretWord ) :
What is the problem with this line ?
here is a link to words.txt if you want to run the code on your own machine
You loaded your words as binary data, by using the 'rb' mode when opening the file:
inFile = open(WORDLIST_FILENAME, 'rb', 0)
then tried to see if a string is contained in that binary data:
if(guess in secretWord ) :
If WORDLIST_FILENAME is text, don't use binary mode to read it. Use a text mode:
inFile = open(WORDLIST_FILENAME, 'r', encoding='ascii')
The file you linked is a simple ASCII-encoded file, so I used that codec to decode it to a Unicode string.

Categories