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.
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.
def myNames():
names = []
while True:
a = input("Enter Name: ")
if a != "done":
names.append(a)
elif a == "done":
return names
def all_lengths(myNames):
num_of_strings = len(myNames)
total_size = 0
for item in myNames:
total_size += len(item)
ave_size = float(total_size) / float(num_of_strings)
print(ave_size)
all_lengths(myNames())
def longestWord(myNames):
count = 0
for i in myNames:
if len(i) > count:
count = len(i)
word = I
print ("the longest string is ", word)
how can I make it print the longest name that was inputted by the user for example: out of Samantha and John it would say that Samantha was the longest name
longestName = ""
for name in myNames:
if len(name) > len(longestName):
longestName = name
print("The longest name is", longestName)
This will check the length of each username, and if the name of that username is longer than the current longest username, it will replace it.
You already have the function for it.
Just need to call the function longestWord().
Write longestWord(myNames()) at the end of the program. Right after,
def longestWord(myNames):
count = 0
for i in myNames:
if len(i) > count:
count = len(i)
word = i # Need to type I in lower case
print ("the longest string is ", word)
Update: Since, you don't want the function to ask for names again, you can move the function calling longestWord()inside the above function where it calculates average, with the parameter as myNames i.e.
def myNames():
names = []
while True:
a = input("Enter Name: ")
if a != "done":
names.append(a)
elif a == "done":
return names
def longestWord(myNames):
count = 0
for i in myNames:
if len(i) > count:
count = len(i)
word = i
print ("the longest string is ", word)
def all_lengths(myNames):
num_of_strings = len(myNames)
total_size = 0
for item in myNames:
total_size += len(item)
ave_size = float(total_size) / float(num_of_strings)
print(ave_size)
longestWord(myNames) # Calling the function with already given names
all_lengths(myNames())
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
I'm trying to do a Caesar Cipher and I've come pretty close. The problem is my output only prints out a single letter, not the whole line ciphered line. E is the most frequently used letter in English so the idea is to find the distance between E and the most frequently used letter in the input. And then shift everything over by that distance. I'm new at python, so I'm not very good yet. Thanks so much in advance! Here's the code I have so far:
maximum_character = unciphered_text[0]
maximum_count = unciphered_text.count(unciphered_text[0])
for char in unciphered_text:
if char is not " ":
if unciphered_text.count(char) > maximum_count:
maximum_character = char
print("The most frequent character used is: ", maximum_character)
ASCII_maximum = maximum_character.lower()
ASCII_number = ord(ASCII_maximum)
print(ASCII_number)
shift_distance = ord('e')-ASCII_number
print("The shift distance is: ", shift_distance)
def caesar_cipher(unciphered_text, shift_distance):
ciphered_text = ""
for char in unciphered_text:
cipher_process = ord(char)+shift_distance
post_translation = chr(cipher_process)
ciphered_text += post_translation
return ciphered_text
answer = caesar_cipher(unciphered_text, shift_distance)
print(answer)
You misindent return statement in caesar_cipher function.
Move your return statement out from loop:
def caesar_cipher(unciphered_text, shift_distance):
ciphered_text = ""
for char in unciphered_text:
cipher_process = ord(char)+shift_distance
post_translation = chr(cipher_process)
ciphered_text += post_translation
return ciphered_text