I am attempting to write a program in python that simulates a game of cheating hangman, but am receiving positional argument errors upon compilation. I wrote the class and methods in hangman.py and called the play method in play_hangman.py. When I attempt to run it, it gives the following error:
play() missing 9 required positional arguments: 'askForWordLength', 'askForNumberOfGuesses', 'remainingWords', 'words', 'wordStatus', 'printCountOfRemainingWords', 'printGameStats', 'askPlayerForGuess', and 'retrieveRemainingWords'
play_hangman.py
from hangman import Hangman
game = Hangman()
game.play()
y = input("Would you like to play again? yes or no: ")
while y == 'yes':
game.play()
y = input("Would you like to play again? yes or no: ")
hangman.py
import re
class Hangman:
# hangman self method
def hangman(self):
self.hangman = Hangman() # object of the Hangman class
def words(self):
with open('dictionary.txt') as file: # opens dictionary text file
file_lines = file.read().splitlines() # reads and splits each line
all_words = [] # empty list to contain all words
valid_words = [] # empty list to contain all valid words
for word in file_lines: # traverses all words in the file lines
if len(word) >= 3: # accepts word if it has at least 3 letters
all_words.append(word) # appends accepted word to list
# list of all invalid characters in python
CHARACTERS = ["~", "`", "!", "#", "#", "$", "%", "^", "&", "*", "(",
")", "-", "_", "=", "+", "[", "]", "{", "}", "|", "\","
"", "'", "?", "/", ">", ".", "<", ",", "", ";", ":"]
for i in CHARACTERS: # traverse list of invalids
for word in all_words:
if i not in word: # if invalid character is not in word
valid_words.append(word) # accept and append to list
return valid_words # return list of valid words
def askForWordLength(self, valid_words):
word_lengths = [] # empty list for possible word lengths
for word in valid_words: # traverse list of valid words
length = word.__len__() # record length of current word
if (length not in word_lengths):
word_lengths.append(length) # accept and append to list
word_lengths.sort()
# inform user of possible word lengths
print('The available word lengths are: ' + str(word_lengths[0]) + '-'
+ str(word_lengths[-1]))
print()
# have user choose from possible word lengths
while(1):
try:
length = int(input('Please enter the word length you want: '))
if (length in word_lengths):
return length
except ValueError:
print('Your input is invalid!. Please use a valid input!')
print()
def askForNumberOfGuesses(self):
while(1):
try:
num_guesses = int(input('Enter number of guesses you want: '))
if (num_guesses >= 3):
return num_guesses
except ValueError:
print('Your input is invalid!. Please use a valid input!')
print()
def wordStatus(self, length):
status = '-'
for i in range(0, length):
status += '-'
return
def remainingWords(self, file_lines, length):
words = []
for word in file_lines:
if (word.__len__() == length):
words.append(word)
return words
def printGameStats(self, letters_guessed, status, num_guesses):
print('Game Status: ' + str(status))
print()
print('Attempted Guesses' + str(letters_guessed))
print('Remaining Guesses' + str(num_guesses))
def askPlayerForGuess(self, letters_guessed):
letter = str(input('Guess a letter: ')).lower()
pattern = re.compile("^[a-z]{1}$")
invalid_guess = letter in letters_guessed or re.match(pattern, letter) == None
if (invalid_guess):
while (1):
print()
if (re.match(pattern, letter) == None):
print('Invalid guess. Please enter a correct character!')
if (letter in letters_guessed):
print('\nYou already guessed that letter' + letter)
letter = str(input('Please guess a letter: '))
valid_guess = letter not in letters_guessed and re.match(pattern, letter) != None
if (valid_guess):
return letter
return letter
def retrieveWordStatus(self, word_family, letters_already_guessed):
status = ''
for letter in word_family:
if (letter in letters_already_guessed):
status += letter
else:
status += '-'
return status
def retrieveRemainingWords(self, guess, num_guesses, remaining_words,
wordStatus, guesses_num, word_length,
createWordFamiliesDict,
findHighestCountWordFamily,
generateListOfWords):
word_families = createWordFamiliesDict(remaining_words, guess)
family_return = wordStatus(word_length)
avoid_guess = num_guesses == 0 and family_return in word_families
if (avoid_guess):
family_return = wordStatus(word_length)
else:
family_return = findHighestCountWordFamily(word_families)
words = generateListOfWords(remaining_words, guess, family_return)
return words
def createWordFamiliesDict(self, remainingWords, guess):
wordFamilies = dict()
for word in remainingWords:
status = ''
for letter in word:
if (letter == guess):
status += guess
else:
status += '-'
if (status not in wordFamilies):
wordFamilies[status] = 1
else:
wordFamilies[status] = wordFamilies[status] + 1
return wordFamilies
def generateListOfWords(self, remainingWords, guess, familyToReturn):
words = []
for word in remainingWords:
word_family = ''
for letter in word:
if (letter == guess):
word_family += guess
else:
word_family += '-'
if (word_family == familyToReturn):
words.append(word)
return words
def findHighestCountWordFamily(self, wordFamilies):
familyToReturn = ''
maxCount = 0
for word_family in wordFamilies:
if wordFamilies[word_family] > maxCount:
maxCount = wordFamilies[word_family]
familyToReturn = word_family
return familyToReturn
def printCountOfRemainingWords(self, remainingWords):
show_remain_words = str(input('Want to view the remaining words?: '))
if (show_remain_words == 'yes'):
print('Remaining words: ' + str(len(remainingWords)))
else:
print()
def play(self, askForWordLength, askForNumberOfGuesses, remainingWords,
words, wordStatus, printCountOfRemainingWords, printGameStats,
askPlayerForGuess, retrieveRemainingWords):
MODE = 1
openSession = 1
while (openSession == 1):
word_length = askForWordLength(words)
num_guesses = askForNumberOfGuesses()
wordStatus = wordStatus(word_length)
letters_already_guessed = []
print()
game_over = 0
while (game_over == 0):
if (MODE == 1):
printCountOfRemainingWords(remainingWords)
printGameStats(remainingWords, letters_already_guessed,
num_guesses, wordStatus)
guess = askPlayerForGuess(letters_already_guessed)
letters_already_guessed.append(guess)
num_guesses -= 1
remainingWords = retrieveRemainingWords(guess, remainingWords,
num_guesses, word_length)
wordStatus = wordStatus(remainingWords[0], letters_already_guessed)
print()
if (guess in wordStatus):
num_guesses += 1
if ('-' not in wordStatus):
game_over = 1
print('Congratulations! You won!')
print('Your word was: ' + wordStatus)
if (num_guesses == 0 and game_over == 0):
game_over = 1
print('Haha! You Lose')
print('Your word was: ' + remainingWords[0])
print('Thanks for playing Hangman!')```
Your play() method requires many arguments:
def play(
self,
askForWordLength,
askForNumberOfGuesses,
remainingWords,
words,
wordStatus,
printCountOfRemainingWords,
printGameStats,
askPlayerForGuess,
retrieveRemainingWords
):
...
When you call the function, you need to provide all of those arguments, aside from self, otherwise, Python won't know what the value of those variables should be.
Related
I am trying to pass words to a function that will be checked with words in a seperate file. It only passes the last word created from the first file and not each word. So I think how it should work is as soon as it creates a word it should pass that word to the function then check it and return the results, but I'm confused as to how. If the word matches a word in the second file it should print the word then a 0 or if it doesn't match a word then print 1.
import sys
argc = len(sys.argv)
cmdlength = argc - 1
if cmdlength != 2:
print ("Usage error, expected 2 args got " + str(cmdlength))
exit()
else:
word = ""
with open(sys.argv[1],"r") as fh:
while True:
ch=fh.read(1)
if not ch:
print(word)
print("End of file")
break
if ch == ' ':
print(word)
word = ''
else:
word += ch
def check_word(word):
count = 0
count2 = 0
with open(sys.argv[2],"r") as fh2:
lines = fh2.readlines()
for line in lines:
if word in line:
print(word , ": " , "0")
count += 1
else:
print(word, ": " , "1")
count += 1
check_word(word)
When you call the check_word function, you are doing it once after the while loop ends, for that reason only the last word is passed to the function. You should call the function after each word is armed, in your case, when ch == ' ':
if ch == ' ':
print(word)
check_word(word)
word = ''
I was instructed to have a user input at least 8 words into a list and then perform various manipulations to the data within the list. One of the manipulations it asks me to do is to create a loop that makes every other letter in the strings capitalized (hElLo WoRlD.) For better readability, I left out the other manipulations that I have done to the code.
import sys
def main():
words = []
wordCount = 0
userWord = input("Enter at least 8 words or 'bye' to leave the program: ").split(' ')
while True:
if len(userWord)<8:
print("Please print at least 8 words, try again.")
sys.exit()
elif wordCount >= 8 and userWord[wordCount] != 'bye':
words.append(userWord[wordCount])
wordCount = wordCount + 1
else:
break
every_other (userWord)
def every_other(words):
words6 = words.copy()
st = ""
for i in range(len(words6)):
if (i%2) == 0:
st += words6[i].upper()
else:
st += words6[i]
print ('This is your list with every other letter capitalized: ', words6)
return st
main()
I am not getting any error messages but the code doesn't seem to be running starting at def every_other.
You'll have to print the function every_other as it returns a string:
import sys
def main():
words = []
wordCount = 0
userWord = input("Enter at least 8 words or 'bye' to leave the program: ").split(' ')
while True:
if len(userWord)<8:
print("Please print at least 8 words, try again.")
sys.exit()
elif wordCount >= 8 and userWord[wordCount] != 'bye':
words.append(userWord[wordCount])
wordCount = wordCount + 1
else:
break
print('This is your list with every other letter capitalized: ', every_other(userWord))
def every_other(words):
words6 = words.copy()
st = ""
for i in range(len(words6)):
if (i%2) == 0:
st += words6[i].upper()
else:
st += words6[i]
return st
#print ('This is your list with every other letter capitalized: ', words6) # This will never run as the function has already returned
main()
If you want to capitalize every second character:
import sys
def main():
words = []
wordCount = 0
userWord = input("Enter at least 8 words or 'bye' to leave the program: ").split(' ')
while True:
if len(userWord)<8:
print("Please print at least 8 words, try again.")
sys.exit()
elif wordCount >= 8 and userWord[wordCount] != 'bye':
words.append(userWord[wordCount])
wordCount = wordCount + 1
else:
break
print('This is your list with every other letter capitalized: ', every_other(userWord))
def every_other(words):
st = ""
new_st = ""
for w in words:
st+=w
print(str(st))
for count, val in enumerate(st):
if (count % 2) == 0:
val = val.upper()
new_st+=val
return new_st
main()
I want to create a hangman game. I want it to keep calling x and printing new_word until there is no "_". I have tried it but the slots keep refreshing. It keeps reprinting. It won't update the value itself.
word = 'EVAPORATE'
wordlist = list(word)
dict = dict(enumerate(wordlist))
slots = list('_' * len(word))
x = input("Guess the letter: ")
def game():
for a,b in dict.items():
if b == x:
slots[a] = x
new_word = ' '.join(slots)
print(new_word)
game()
This seems to work for me:
word = 'EVAPORATE'
wordlist = list(word)
dict = dict(enumerate(wordlist))
slots = list('_' * len(word))
def game():
while '_' in slots:
x = input("Guess the letter: ")
for a,b in dict.items():
if b == x.upper():
slots[a] = x
new_word = ' '.join(slots)
print(new_word)
game()
I have added in a while loop just inside def game(): so that the code will keep running until slots has no underscores left in it. I then moved x = input("Guess the letter: " to inside the while loop so the user can always have another guess until the word is completed.
A few things to add:
Don't you ever use keywords such as list or dict for variables
You have to count the matchs for each letter, example E appears twice, so, you have to count it twice
You have to know when the game ends, because you want to loop the question "guess letter" until the game ends
Add a While loop
Enjoy your game
word = 'EVAPORATE'
wordlist = list(word)
word_length = len(word)
word_dict = dict(enumerate(wordlist))
slots = list('_' * len(word))
def game():
total_letters = word_length
while not game_ended(total_letters):
x = input("Guess the letter: ")
matchs = 0
for pos,letter in word_dict.items():
if letter == x:
matchs += 1
slots[pos] = x
new_word = ' '.join(slots)
total_letters -= matchs
print(new_word)
def game_ended(word_len):
return word_len == 0
game()
just put everything from the input until the end in a while loop
word = 'EVAPORATE'
wordlist = list(word)
# it is not a good idea name a variable the same as a builtin, so change from 'dict' to 'worddict'
worddict = dict(enumerate(wordlist))
slots = list('_' * len(word))
def game(x):
# we also need to change it here
for a,b in worddict.items():
if b == x:
slots[a] = x
new_word = ' '.join(slots)
print(new_word)
while any([i == '_' for i in slots]):
x = input("Guess the letter: ")
game(x)
the while check if any letter in slots is a _, if there is any, keep playing.
note that I also pass the input as a variable to game (it's not necessary, but it's better)
the error is when I enter d, and Enter a sentence: David, y r u l8
David,why\nare\nyou\nlate\n , but I need it to return David, why are you late
def update_dictionary(fileName,dictionary):
try:
a = open(fileName)
except IOError:
print( fileName,"does not exist.")
print("The dictionary has",len(dictionary),"entries.")
return dictionary
with a:
print(fileName,"loaded successfully.")
for word in a:
c,b = word.split(",")
dictionary[c] = b
print("The dictionary has",len(dictionary),"entries.")
return dictionary
def deslang(filename,dic):
x = ""
words = filename.split(" ")
for i in range(len(words)):
if words[i] in dic:
words[i] = dic[words[i]]
for i in range(len(words)-1):
x = x + words[i] + " "
x = x + words[len(words) -1]
return x
def main():
name = {}
while 1:
u_input = input("Would you like to (a)dd words to the dictionary, (d)e-slang a sentence, or (q)uit?: ")
if u_input == "q":
break
if u_input == "a":
fileName = ""
while len(fileName) == 0:
fileName = input("Enter a filename: ")
name = update_dictionary(fileName,name)
if u_input == "d":
sentence = ""
while len(sentence) == 0:
sentence = input("Enter a sentence: ")
print(deslang(sentence, name))
if name =="main":
main()
You need to strip the newlines off each of the dictionary lines. In other words:
for word in a:
c,b = word.rstrip().split(",")
dictionary[c] = b
When you iterate a file like for word in a:, you get a string for each line in the file, including the newline at the end. So, your dictionary ends up full of entries like 'y': 'why\n' instead of 'y': 'why'.
You can strip the trailing newline from word.split(",") by calling str.strip.
word.strip().split(",")
You can also use read() to load the contents of the file which doesn't include newlines.
I apologize if this is just a dumb slip-up on my part, but I am relatively inexperienced with Python and I can't figure out why this isn't working.
I have a class called Game, which contains a word_list that has been read in from a text file. One of the method of the class is as follows:
def make_guess(self, guess):
print("Guess: ", guess)
if guess == self.target_word:
print("Got it!")
if guess in self.word_list:
num_right = self.compare_letters(guess, self.target_word)
else:
print("Not valid guess; not in list")
No matter what input I give it, I can never make it trip the if guess in self.word_list path. I tried comparing the type of the variables (each word in the list, and my input), but they appeared to be the same to me.
The whole definition of the class if it helps:
class Game:
def __init__(self, difficulty):
self.difficulty = difficulty
if 0 < difficulty < 3:
self.remaining_guesses = 5
elif 3 <= difficulty < 5:
self.remaining_guesses = 4
else:
self.remaining_guesses = 3
self.word_list = []
self.dictionary = open("wordsEn.txt")
for word in self.dictionary:
percent = int(floor(1000*random()))
if len(word) == 6 and percent < 2:
self.word_list.append(word)
self.dictionary.close()
percent = int(floor(len(self.word_list)*random()))
self.target_word = self.word_list[percent]
def make_guess(self, guess):
print("Guess: ", guess)
if guess == self.target_word:
print("Got it!")
if guess in self.word_list:
num_right = self.compare_letters(guess, self.target_word)
else:
print("Not valid guess; not in list")
def display_word_list(self):
print("in display")
print(self.remaining_guesses)
for word in self.word_list:
print(word)
print("Target: ", self.target_word)
def compare_letters(self, guess, target_word):
for letter in guess:
if letter == letter:
print("yes")
`
In main, I have:
new_game = Game(difficulty)
guess = input("Guess: ")
new_game.make_guess(guess)
Even if I deliberately guess a word that I know to be in the list, it never says that the word is in fact in the list. What stupid mistake am I making? (and if you could point out ways I could adhere more to the Python style, that would be appreciated as well!)
You need to strip newlines from lines of wordsEn.txt. After
for word in self.dictionary:
insert:
word = word.rstrip()
I'm assuming that each line of wordsEn.txt lists a single word.
Instead of adding the full line to self.word_list, add each word by calling self.dictionary = open("wordsEn.txt").read().split() instead. Here is your edited class:
class Game:
def __init__(self, difficulty):
self.difficulty = difficulty
if 0 < difficulty < 3:
self.remaining_guesses = 5
elif 3 <= difficulty < 5:
self.remaining_guesses = 4
else:
self.remaining_guesses = 3
self.word_list = []
self.dictionary = open("wordsEn.txt").read().split()
for word in self.dictionary:
percent = int(floor(1000*random()))
if len(word) == 6 and percent < 2:
self.word_list.append(word)
self.dictionary.close()
percent = int(floor(len(self.word_list)*random()))
self.target_word = self.word_list[percent]
def make_guess(self, guess):
print("Guess: ", guess)
if guess == self.target_word:
print("Got it!")
if guess in self.word_list:
num_right = self.compare_letters(guess, self.target_word)
else:
print("Not valid guess; not in list")
def display_word_list(self):
print("in display")
print(self.remaining_guesses)
for word in self.word_list:
print(word)
print("Target: ", self.target_word)
def compare_letters(self, guess, target_word):
for letter in guess:
if letter == letter:
print("yes")
Demonstrating the above concept of .read().split():
>>> file = open('blah.txt')
>>> for word in file:
... word
...
'Hello,\n'
'\n'
'These\n'
'Are\n'
'Some\n'
'Vocabulary\n'
'Words\n'
'\n'
'Regards,\n'
'Me\n'
>>> file = open('blah.txt').read().split()
>>> for word in file:
... word
...
'Hello,'
'These'
'Are'
'Some'
'Vocabulary'
'Words'
'Regards,'
'Me'
>>>
In the line where you say
for word in self.dictionary:
This reads an entire line from the text file. So the variable word doesn't refer to a word in the text file. You should first read a line from the text file and then take individual words from the line. Like this :
for line in self.dictionary:
words=line.split();
for word in words: