too many positional arguments in python - python
Explanation
I am currently writing a code that simulates a game of hangman, but cheats by attempting to evade the player's guesses by changing the word. The class and methods are defined in hangman.py, while play_hangman.py calls the instance of Hangman and the play method (cannot be changed per the instructions of the assignment).
Problem
In the play method, I received the following error: "
TypeError: askForWordLength() takes 1 positional argument but 2 were given "
I know that this means I am giving too many arguments into the call of the method, but I am unsure of how to change it. I have tried rewriting the 5th line of the following code multiple times to fix this error, but it does not cease:
Specific Section of Code*
def play(self):
MODE = 1
openSession = 1
while(openSession == 1):
word_length = self.askForWordLength(self.words)
num_guesses = self.askForNumOfGuesses()
wordStatus = self.wordStatus(word_length)
letters_already_guessed = []
print()
gameOver = 0
while (gameOver == 0):
if (MODE == 1):
self.printCountOfRemainingWords(self.remainingWords)
self.printGameStats(self.remainingWords. letters_already_guessed,
self.num_guesses, self.wordStatus)
guess = self.askPlayerForGuess(letters_already_guessed)
letters_already_guessed.append(guess)
num_guesses -= 1
remainingWords = self.retrieveRemainingWords(guess, self.remainingWords,
num_guesses, word_length)
wordStatus = self.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!')
ENTIRE CODE
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!')```
It looks like you don't understand how classes work or there is a piece of code not shown here. When you define a method in a class, the first argument always refers to the object on which the method operates, which is conventionally called self. Any subsequent arguments are defined how you want. Usually, you don't need to pass the first self argument because it is passed according to the object you use. Any remaining arguments are your responsibility though.
For example:
class Student:
def __init__(self, name, age):
# Initializer (Commonly called Constructor in other languages)
# This is the first method that will run when you create an object and
# it runs automatically (You don't need to call it).
# This is where you'd initialize the state of the object, for example:
# Create a student with name and age.
# name and age are regular parameters of the __init__ method. We'd like
# to save them as attributes of our student object which is represented
# by self.
self.name = name
self.age = age
# Maybe we'd like to save a list of grades too
self.grades = []
def add_grade(self, grade):
# self is our object, and grade is the parameter
self.grades.append(grade)
def get_average(self):
# If we don't need additional parameters, we don't have to, but self is
# mandatory
return sum(self.grades) / len(self.grades)
def print_status(self):
# Note I am calling get_average() and I don't specify self. It's determined automatically.
print("Name:", self.name)
print("Age:", self.age)
print("Average:", self.get_average())
# We created the class, but we need to create some objects to use it.
s1 = Student("Dan", 15)
s2 = Student("Maya", 14)
# Note we only pass the custom parameters we specified which are `grade`
# self is determined by the object we are using (s1 or s2)
s1.add_grade(81)
s1.add_grade(86)
s2.add_grade(89)
s2.add_grade(93)
s1.print_status()
s2.print_status()
I hope this example helps you understand how methods work. In your code, I don't understand why you pass the methods as arguments of the play method and I don't see where you call this method or where you even create a Hangman object, so I can't help further.
Related
FOR loop in function exists before ending
I know there are already countless clones of Wordle. Nevertheless I try to program my own version. In the function is_real_word it should be checked whether the entered word of the user occurs in the word list. If so, the variable check = True. However, the FOR loop is always exited when the counter is at 1. The file "5_letter_words.txt" contains 3 entries: wetter, wolle, watte And last but not least also the return value for eingabewort is sometimes NONE. And I don't know why? import random def word_list(): wordle = [] with open("5_letter_words.txt", "r") as file: for line in file: myTuple = line.strip() wordle.append(myTuple) return wordle def random_word(wordlist): return random.choice(wordlist) def is_real_word(guess, wordlist): for word in wordlist: if guess == word: return True return False def check_guess(guess, randomword): randomword_tuple = [] guess_tuple = [] length = len(randomword) output = ["-"] * length for index in range(length): if guess[index] == randomword[index]: output[index] = "X" randomword = randomword.replace(guess[index], "-", 1) for index in range(length): if guess[index] in randomword and output[index] == "-": output[index] = "O" randomword = randomword.replace(guess[index], "-", 1) return ''.join(output) def next_guess(wordlist): guess = input('Please enter a guess: ') guess = guess.lower() valid = is_real_word(guess, wordlist) if valid == False: print('Thats not a real word!') next_guess(wordlist) else: return guess def play(): target = [] target = word_list() zufallswort = str() zufallswort = random_word(target) eingabewort = next_guess(target) print('Eingabewort: ', eingabewort) print('Zielwort: ', zufallswort) play()
Could you check if your function word_list returns the list? You dont give a clear path, only the file name. If it works, try: def is_real_word(guess, wordlist): for word in wordlist: if guess == word: check = 1 break return check
How can I use the same Word as in the function above? If ther's no way to do it how can I use the same random number without using a global variable?
def read_input(random_words): word = choose_random_words() rand = random.randrange(0, 3) letter = find_row_letter(word[rand]) print(rand) user_input = timed_input("Input: %s " % letter) return user_input This function chooses a random word out of a list. This Word is then linked to a letter of the alphabet. You can see the timed_input as a normal input, as it is not important for my question. def handle_input(random_words): letter = read_input(random_words) word = print(letter) if word == letter: print("Correct") else: print("False") In this function I want to compare if the user input from function read_input is the same as the chosen word from the same function.
Make read_input return the word too def read_input(random_words): word = choose_random_words() rand = random.randrange(0, 3) letter = find_row_letter(word[rand]) user_input = timed_input("Input: %s " % letter) return user_input, word def handle_input(random_words): letter, word = read_input(random_words)
What you can do is declare the word variable to be global: def read_input(random_words): global word word = choose_random_words() rand = random.randrange(0, 3) letter = find_row_letter(word[rand]) print(rand) user_input = timed_input("Input: %s " % letter) return user_input That allows you to access the word variable from anywhere.
Can't print first and last character of code
Hey guys so I have my program working to a certain extent. My program is suppose to check if there is an "A" in the user input and if done so it will swap that "A" with the next letter. Here are the examples: "tan" = "TNA" "abracadabra" = "BARCADABARA" "whoa" = "WHOA" "aardvark" = "ARADVRAK" "eggs" = "EGGS" "a" = "A" In my case this is what works and doesn't work: Works: tan to TNA Doesn't work: abracadabra = BARCADABAR whoa = WHO aardvark = ARADVRA eggs = EGG a = a just equals nothing. What I'm getting at is that the last character isn't printing and I'm not sure how to do so. def scrambleWord(userInput): count = 0 Word_ = "" firstLetter_ = "" secondLetter_ = "" while count < len(userInput): if count+1 >=len(userInput): break #copy last character firstLetter_ = userInput[count] #assigning first letter secondLetter_ = userInput[count+1] #assigning next letter if firstLetter_ == 'A' and secondLetter_ != 'A': Word_ += (secondLetter_ + firstLetter_) #Swap then add both letters count+=1 else: Word_+=firstLetter_ count+=1 return Word_ def main(): userInput = input("Enter a word: ") finish = scrambleWord(userInput.upper()) print(finish) main()
Probably because you are just breaking without writing the userinput[count] into the word. if count+1 >=len(userInput): Word_ += userInput[count] break #copy last character This should help
Removing extra whitespace between words using for loop Python
I need to remove all excess white space and leave one space, between my words while only using if and while statements. and then state the amount of characters that have been removed and the new sentence edit, it must also work for punctuation included within the sentence. This is what I have come up with however it leaves me with only the first letter of the sentence i choose as both the number, and the final sentence. can anyone Help. def cleanupstring(S): lasti = "" result = "" for i in S: if lasti == " " and i == " ": i = "" else: lasti = i result += i return result sentence = input("Enter a string: ") outputList = cleanupstring(sentence) print("A total of", outputList[1], "characters have been removed from your string.") print("The new string is:", outputList[0])
Your code should be something like this: def cleanupstring(S): counter = 0 lasti = "" result = "" for i in S: if lasti == " " and i == " ": i = "" counter += 1 else: lasti = i result += i return result, counter sentence = input("Enter a string: ") outputList = cleanupstring(sentence) print("A total of", outputList[1], "characters have been removed from your string.") print("The new string is:", outputList[0]) The counter keeps track of how often you remove a character and your [0] and [1] work now the way you want them to. This is because outputList is now a tuple, the first value at index 0 is now the result and the second value at index 1 is the counter.
String Value Isn't Updating
So I've been working on reworking Hangman in Python and I've run into an issue. The output isn't updating at all. It always remains this mesh of underscores, although other parts of the code, such as the number of tries decreasing or used letters being added to the used list seem to function flawlessly. Here's the code: # IMPORT GUARDS from random import choice from os import system from time import sleep # DECLARATIONS wordList = ["apple", "pear"] gameWord = choice(wordList) strList = list(gameWord) strOut = "_" * len(gameWord) tries = 5 used = [] alphabet = "abcdefghijklmnopqrstuvwxyz" while True: system ("cls") print (strOut + "\n") print ("Tries Left:", str(tries)) print ("Letters Used:", used) Ltr = input ("Letter: ") # INPUT CHECK if len(Ltr) != 1 and Ltr.lower() in alphabet: print ("Input is of incorect size.") sleep(0.5) elif len(Ltr) == 0 and Ltr.lower() in alphabet: print ("No input value given.") sleep(0.5) if len(Ltr) == 1 and Ltr.lower() not in alphabet: print ("Invalid character input.") sleep(0.5) if len(Ltr) != 1 and Ltr.lower() not in alphabet: print ("Input is both too large and contains invalid characters.") sleep(0.5) # CORRECT INPUT if len(Ltr) == 1 and Ltr.lower() in alphabet: ltrPos = ( [pos for pos, char in enumerate(gameWord) if char == Ltr.lower]) # DECLARATIONS Counter = 0 strcounter = 0 # CHECKING THE NUM OF TIMES THE INPUT APPEARS IN THE WORD while Counter < len(strList): if gameWord[Counter].lower() == Ltr.lower(): strcounter += 1 Counter += 1 # INPUT DOES APPEAR if strcounter != 0: strcounter -= 1 strOut = list(strOut) for i in ltrPos: strOut[ltrPos[strcounter]] = Ltr.upper() strcounter += 1 strOut = "".join(strOut) # INPUT DOES NOT APPEAR AND/OR IS USED elif strcounter == 0: if Ltr not in used: print ("Letter not in word.") used.append(Ltr.lower()) tries -= 1 else: print ("Letter Already Used.") sleep(0.5) # OUT OF TRIES if tries == 0: system("cls") print ("Game Over. \nWord: " + gameWord) break # VICTORY if "_" not in strOut: system("cls") print ("Congratulations!") break system ("pause") All advice is appreciated. Thanks in advance.
The main problem is that you forgot to call the lower function in one place: ltrPos = [pos for pos, char in enumerate(gameWord) if char == Ltr.lower()] But there's more. First, you can simplify the calculation of strCounter to strcounter = len(ltrPos) Or just check if ltrPos: instead of if strcounter != 0:. Also, you can use else instead of elif. The next problem is strOut[ltrPos[strcounter]]. Here, you try to access lrtPos[strcounter], which will produce an index error as you decrement strcounter just once, instead of setting it back to zero. Instead, just iterate the indices in ltrPos directly: for i in ltrPos: strOut[i] = Ltr.upper() Also, note that you only add the letter to the used list if it is not in the word.