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)
Related
Im new to programming and was trying to program a word guesser. I dont understand why the while loop doesnt go though three times, also the program doesnt remember the previously guessed letters.
import random
words = ["hello", "bye", "petscop"]
GuessWord = random.choice(words)
tries = 3
while tries > 0:
tries = tries - 1
inp = input("\nEnter your guess: ")
for char in GuessWord:
if char in inp:
print(char, sep="",end="")
elif char not in inp:
print("_", sep="",end="")
tries = tries - 1
I'm sorry to say, StackOverflow isn't a forum for debugging. StackOverflow is more about solving general problems that affect multiple people rather than single instances of a problem (like bugs), if that makes sense.
There is probably a better place for you to ask this question but I can't think of one off the top of my head.
In the spirit of being constructive: the following code appears twice and you should remove the second instance.
tries = tries - 1
Also, you are overwriting inp each time you enter the loop causing it to forget its previous value. There are other issues too. But that's a good start.
The main problem you have is that you decrease the number of tries by 2 each round. Therefore, at the beginning of the second round, the number of tries decreases again so it fails. This is how I would do it:
import random
# library that we use in order to choose
# on random words from a list of words
name = input("What is your name? ")
# Here the user is asked to enter the name first
print("Good Luck ! ", name)
words = ['rainbow', 'computer', 'science', 'programming',
'python', 'mathematics', 'player', 'condition',
'reverse', 'water', 'board']
# Function will choose one random
# word from this list of words
word = random.choice(words)
print("Guess the characters")
guesses = ''
# any number of turns can be used here
turns = 3
while turns > 0:
# counts the number of times a user fails
failed = 0
# all characters from the input
# word taking one at a time.
for char in word:
# comparing that character with
# the character in guesses
if char in guesses:
print(char)
else:
print("_")
# for every failure 1 will be
# incremented in failure
failed += 1
if failed == 0:
# user will win the game if failure is 0
# and 'You Win' will be given as output
print("You Win")
# this print the correct word
print("The word is: ", word)
break
# if user has input the wrong alphabet then
# it will ask user to enter another alphabet
guess = input("guess a character:")
# every input character will be stored in guesses
guesses += guess
# check input with the character in word
if guess not in word:
turns -= 1
# if the character doesn’t match the word
# then “Wrong” will be given as output
print("Wrong")
# this will print the number of
# turns left for the user
print("You have", + turns, 'more guesses')
if turns == 0:
print("You Loose")
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
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):
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.
Just have a quick question to check. I'm working on a word game and want to find the number of points of a given hand. I've gotten most of the code correct and it runs fine. However, I keep getting an extra part of the code repeated at the bottom and I would like to know how should I remove it? Here's the code:
def play_hand(hand, wordlist):
"""
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)
word_list: list of lowercase strings
"""
print "Current Hand:", display_hand(hand)
word = raw_input('Enter word, or a "." to indicate that you are finished:')
handScore = 0
while list(word) != ['.']:
if is_valid_word(word, hand, wordlist) == True:
score = get_word_score(word,n)
handScore = handScore + score
print word, "earned", score, "points. Total:", handScore, "points"
hand = update_hand(hand, word)
if calculate_handlen(hand) == 0:
print "Your hand has finished."
print "Your final score is", handScore
break
else:
print "Current hand:", display_hand(hand)
word = raw_input('Enter word, or a "." to indicate that you are finished:')
else:
print "Invalid word, please try again."
word = raw_input('Enter word, or a "." to indicate that you are finished:')
if list(word) == ['.']:
print "Total score: %d points" %(handScore)
n = 7
hand = deal_hand(n)
play_hand(hand, load_words())
Here's the code for load_words():
def load_words():
"""
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, 'r', 0)
# wordlist: list of strings
wordlist = []
for line in inFile:
wordlist.append(line.strip().lower())
print " ", len(wordlist), "words loaded."
return wordlist
I get this in return:
Loading word list from file...
83667 words loaded.
Current Hand: a i j m n w v
None
Enter word, or a "." to indicate that you are finished:jam
jam earned 36 points. Total: 36 points
Current hand: i n w v
None
Enter word, or a "." to indicate that you are finished:win
win earned 18 points. Total: 54 points
Current hand: v
None
Enter word, or a "." to indicate that you are finished:v
Invalid word, please try again.
Enter word, or a "." to indicate that you are finished:.
Total score: 54 points
Loading word list from file...
83667 words loaded.
As you can see, there's an extra "loading word list from file... 83667 words loaded." at the bottom which isn't supposed to be there. Does anyone know what went wrong in my code?
Thanks so much!
Andrea
Perhaps load_words() function is called again from some function else which is not seen in the question.
What if you remove play_hand() and show the output here?
Note: you can always use a debugger like pudb to check the program flow.