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.

Categories