I'm in second year Comp. Sci at University and I've come across a problem in my most recent assignment. I have to make a Hangman game, 100% like their output and specifications. I would format the list with numbers but I don't know how, new to SO. My problem arises in the block:
for i in range(0, stringSize, 1):
answerStr[i] = '_'
where it gives me the error
int object does not support item assignment
In other languages I could just make a string of size (userChosenWord) but I'm having trouble with Python's string library as well as its dynamic typing. In the assignment, I have to output the current string as _____, and if the user was to guess e for the word horse, I'd have to tell the user Letters matched so far: ____e. I hope that makes sense.
Also, if any of you have tips/comments on my code, please let me know. I'm always looking to learn.
wordList = ['cow', 'horse', 'deer', 'elephant', 'lion', 'tiger', 'baboon', 'donkey', 'fox', 'giraffe'] #will work for words <=100 chars
inputList = "abcdefghijklmnopqrstuvwxyz"
illegalInputList = "!##$%^&*()_+-=`~;:'\"<,>.?/|\\}]{["
def game():
attemptsMade = 0
print("Welcome to Hangman. Guess the mystery word with less than 6 mistakes.")
userInputInteger = int(input("Please enter an integer number (0<=number<10) to choose the word in the list:"))
if (0 > userInputInteger or userInputInteger > 9):
print("Index is out of range.")
game()
for i in range(0, len(wordList)):
if (userInputInteger == i):
#userChosenWord is string from wordList[i]
userChosenWord = wordList[i]
print("The length of the word is:", len(userChosenWord))
break
stringSize = len(userChosenWord)
answerStr = len(userChosenWord)
#make a temp string of _'s
for i in range(0, stringSize, 1):
answerStr[i] = '_'
keyStr = userChosenWord
def play():
guessChar = input("Please enter the letter you guess:")
if guessChar not in inputList:
print("You must enter a single, alphabetic character.")
play()
if guessChar in illegalInputList:
print("Input must be an integer.")
play()
if (guessChar == ('' or ' ')):
print("Empty input.")
play()
attemptsMade += 1
if guessChar in userChosenWord:
for i in range(0, stringSize, 1):
if (keyStr[i] == guessChar):
answerStr[i] = guessChar
print("Letters matched so far: %s", answerStr)
else:
print("The letter is not in the word.")
play()
if (answerStr == userChosenWord):
print("You have guessed the word. You win. \n Goodbye.")
sys.exit()
if (attemptsMade <= 6):
play()
if (attemptsMade > 6):
print("Too many incorrect guesses. You lose. \n The word was: %s", userChosenWord)
replayBool = bool(input("Replay? Y/N"))
if (replayBool == 'y' or 'Y'):
play()
elif (replayBool == 'n' or 'N'):
print("Goodbye.")
game()
Partial answer. There's more going on but with respect to 'int' object does not support item assignment:
You are setting answerStr to a number len(userChosenWord) which is the length of userChosenWord.
But you try to use it as if it was a list. To make an empty list of length len(userChosenWord) do:
answerStr = [0]*len(userChosenWord)
or equivalently:
answerStr = [0 for i in userChosenWord]
Related
Hangman. As you probobly understand i am new to coding and python, sorry for bad code.
The best way i can think of to describe this problem is through the following way: In the "try:" section i try to index = list_of_letters.index(guesssed_letter_string). i want to check if the guessed_letter_string is in list_of_letters: i earlier in the code translate the input from well the only input() in the code to guessed_letter_string (its the same thing). when you input a letter in the middel of the word it works like index[3] but when you input the first letter in the word the index locks at 0 and every other letter replaces it. is there a way to fix this
import random
list_of_words = ["mom", "dad", "sister", "brother"]
random_word = random.choice(list_of_words)
list_of_letters = list(random_word)
print(random_word)
print(list_of_letters)
rounds_failed = 1
rounds_max = 16
list_of_letters_guessed = []
under_grejer = []
count_of_right_letters_list = []
print(f"You have {rounds_max - rounds_failed} rounds left to find out the word")
for every in list_of_letters:
under_grejer.extend("_")
while True:
if rounds_failed == rounds_max:
print("To many attempts, no more rounds")
break
if len(list_of_letters) == 0:
print("YOU FUCKING WON")
break
print(f"This is round: {rounds_failed}")
print(" ".join(under_grejer))
print("Letters that are correct(not in order): "+", ".join(count_of_right_letters_list))
print("List of letters guessed: "+", ".join(list_of_letters_guessed))
guess = input("NAME A Letter: ")
guess_letters_list = (list(guess))
guess_count_letters = len(guess_letters_list)
if guess_count_letters > 1:
print("Dummy you just need to input a letter, nothing else")
guesssed_letter_string = " ".join(guess_letters_list)
try:
index = list_of_letters.index(guesssed_letter_string)
print("Congrats you got the letter: " + guesssed_letter_string)
print(f"thats the {index + 1}nd letter in the word")
rounds_failed += 1
count_of_right_letters_list.extend(guesssed_letter_string)
print(index)
list_of_letters.pop(index)
under_grejer[index] = guesssed_letter_string
except ValueError:
print("try again mate that letter was not in the word")
list_of_letters_guessed.append(guesssed_letter_string)
rounds_failed += 1
continue
It's not about the first letter only. Your problem is that with list_of_letters.pop(index) you remove the guessed letter form list_of_letters; parts of your code rely on this to check if you guessed all occurrences of that letter before already, but on the other hand this reduces the index of all letters behind the guessed one for later iterations.
For example, for brother, if you guess r it correctly says position 2, but if you then guess o next, it again says position 2 because your list_of_letters now reads ["b","o","t","h","e","r"].
You could either try to work with list_of_letters_org = list_of_letters.copy() which you will never change, and pick the right one for every task, or you could for example change the program structure by adding a list of booleans that store which letters were guessed already.
I have created a hangman type game and it all works apart from if the user enters a capital letter it does not register it. The game should be case insensitive. This is the code I have tried for that part of the game.
def game():
total = len(''.join(set(myword)))
wrong_guess = 0
correct_letters = 0
while wrong_guess <= 7:
print_output()
letter = input("Guess:")
if len(letter) >= 1:
if letter.isalpha():
if letter.lower() in myword:
correct_letters += 1
for i,x in enumerate(myword):
if x is letter.lower():
output[i] = letter
else:
wrong_guess += 1
else:
print("Invalid input, please enter a guess")
else:
print("Invalid input, please enter a guess")
python has a built in function called string.lower()
do this
letter = input("Guess: ").lower()
The following code is not the proper way to compare strings or characters:
if x is letter.lower():
The is operator compares whether two instances are the same or not, it does not compare equality. You want to use the equality operator, ==:
if x == letter.lower():
I am very new to python and I am attempting to make a hangman game.
I would like to change a string to show the number of guessed letters but for some reason I keep on getting weird results. Here is my code:
import random
guesses_left = 9
def show_guesses_left():
print("You have", guesses_left, "guesses left")
wordlist = ['nerd', 'python', 'great', 'happy', 'programmer', 'long', 'short', 'stupid']
word = random.choice(wordlist)
wordwin = word
hidden_word = ["?" for q in word]
letters_guessed = ''.join(hidden_word)
print("Welcome to Hangman!!")
print("My word is", len(word), "letters long")
print(wordwin)
print(letters_guessed)
def request_guess():
global guesses_left
global word
global letters_guessed
x = input(f"What is your guess? \n{letters_guessed}")
if x in word:
print("Great you guessed a letter")
t = word.find(x)
word = word.replace(x, "")
print(t)
letters_guessed = letters_guessed[:t] + letters_guessed[t:t+1].replace('?', x) + letters_guessed[t+1:]
elif type(x) is not str or len(x) > 1:
print("Invalid guess, Your guess must be 1 letter long")
else:
print("Wrong!")
guesses_left -= 1
show_guesses_left()
def start_game():
global letters_guessed
global word
global guesses_left
letters_guessed = ''.join(hidden_word)
while True:
if guesses_left > 0 and len(word) != 0:
request_guess()
elif len(word) == 0:
print(f"YOU WIN!!!, the word was {wordwin}")
break
else:
print("You lose! Better luck next time!")
break
start_game()
I keep on getting this result where it only works for the for some letters and the placing is wrong. Here is my result:
Welcome to Hangman!!
My word is 4 letters long
long
????
What is your guess?
????l
Great you guessed a letter
0
What is your guess?
l???n
Great you guessed a letter
1
What is your guess?
ln??o
Great you guessed a letter
0
What is your guess?
ln??g
Great you guessed a letter
0
YOU WIN!!!, the word was long
Why cant i just slice the string change one character and slice the rest?
Why does it work the first time and not the second?
If anybody can explain to me what is going on it would be appreciated
Solution
import random
guesses_left = 9
def show_guesses_left():
print("You have", guesses_left, "guesses left")
wordlist = ['nerd', 'python', 'great', 'long', 'short', 'stupid', 'happy', 'programmer']
word = random.choice(wordlist)
wordwin = list(word)
hidden_word = list('?' * len(word))
letters_guessed = ''.join(hidden_word)
print("Welcome to Hangman!!")
print("My word is", len(word), "letters long")
print(letters_guessed)
def request_guess():
global guesses_left
global word
global letters_guessed
x = input("\nWhat is your guess?\n" + letters_guessed + "\n")
if x in word:
print("\nGreat you guessed a letter")
for i, j in enumerate(word):
if j == x:
hidden_word[i] = j
letters_guessed = ''.join(hidden_word)
print(letters_guessed + "\n")
elif type(x) is not str or len(x) > 1:
print("Invalid guess, Your guess must be 1 letter long")
else:
print("\nWrong!")
guesses_left -= 1
show_guesses_left()
def start_game():
global letters_guessed
global word
global guesses_left
letters_guessed = ''.join(hidden_word)
while True:
if guesses_left > 0 and letters_guessed != word:
request_guess()
elif letters_guessed == word:
print("YOU WIN!!!, the word was " + word)
break
else:
print("\nYou lose! Better luck next time!")
break
start_game()
Notes
Got it to work!
Sorry short on time will be back to help more, but take a look around. I used some different methods than you originally had, seems like there was a issue with your letters_guessed not revealing letters past a letter already guessed. This will work for double letters as well, which also seemed to be an issued with your original code.
Again sorry, will be back to explain more!
The main problem is the code you use to get the index of the guessed letter:
t = word.find(x)
word = word.replace(x, "")
This shortens word after each correct guess, so t will not be the desired value after the first correct guess.
However, even if you fix this, you will still not properly handle the case that the guessed letter occurs multiple times.
Here is a short example that shows how to solve both problems:
answer = 'long'
hidden = '?' * len(answer)
print("Welcome to hangman!")
while True:
guess = input("Guess a letter: ")
result = ''
if guess in answer:
for answer_letter, hidden_letter in zip(answer, hidden):
if guess == answer_letter:
result += guess
else:
result += hidden_letter
hidden = result
print(hidden)
if hidden == answer:
print("You guessed it!")
break
The main problem is that you are basing that splicing on a variable that you modify on the go. In particular, the variable word, where you look for the position of x, the guessed letter. The position is correct until word gets modified in length, as you replace the letter with an empty string.
An easy fix for that is to simply change the replace statement, and put either an empty space, or another character, that the user would not normally put. In my example, I would replace:
word = word.replace(x, "")
with
word = word.replace(x, " ")
That of course breaks the program exit logic: you can never win.
There is still another issue, that is multiple occurrences of the same letter are not accounted properly. In fact, the program loops until exhaustion, when multiple instances of the same letter are in word.
That is due to the fact that find will only reveal the position of the first instance of a given letter, and you don't account for possible duplicates.
There are several ways to fix that, but I think the main issue is identified.
For an alternate implementation, check https://eval.in/1051220
I am a new programmer with experience with Visual Basic for Applications and have recently changed to python.
I'm working on a number guessing game and so far progress has been great. The user enters 4 digits into the program. The program also generates a 4 digit number and the program returns Ys or Ns to show whether any digits are correct or not. EG 1357 as a user guess and 1358 as the programs number shows YYYN as output.
I'm trying to rework the program to make it simpler for users by showing H or L to suggest that they need to guess higher or lower IF the digit guessed is incorrect. If it's correct, then a Y should be shown as per normal. I am aware that it's a condition in the loop I need to change or another loop I need to add but I am struggling to see where to add this and how to write it. Does anybody have a solution for this?
Here is part of my code for the section of the program which returns the result for the guesses.
lives = 10
while lives > 0:
number = input("Enter your guess: ")
letter = ''
for i in range(len(numToGuess)):
letter += 'Y' if int(number[i]) == numToGuess[i] else 'N'
if letter == 'Y' * len(numToGuess):
print("Good job!")
break
print(letter)
lives -= 1
else:
print("Game over! You used up all of your tries.")
Does anybody have a solution for this?
I prefer to use lists for this. Meaning, I'd convert both the correct answer and the user guess into separate digits saves in two lists and then compare them.
Let's say the correct answer is '1234':
lives = 10
correct_answer = 1234
correct_answer = [int(char) for char in str(correct_answer)]
while lives > 0:
letter = ''
number = input("Enter your guess: ")
number = [int(char) for char in str(number)]
if number == correct_answer:
print("Correct!")
break
for i in range(len(correct_answer)):
if correct_answer[i] == number[i]:
letter += 'Y'
elif correct_answer[i] > number[i]:
letter += 'H'
else:
letter += 'L'
print("Your guess is wrong: ", letter)
lives -= 1
print("Game over!")
Now for example:
Enter your guess: 1111
Your guess is wrong: YHHH
Enter your guess: 1235
Your guess is wrong: YYYL
Enter your guess: 1234
Correct!
Game over!
>>>
You can use zip function for compare the letters :
>>> a='1357'
>>> b='1358'
>>> l=[]
>>> for i,j in zip(a,b):
... if i==j :l.append('Y')
... else :l.append('N')
...
>>> ''.join(l)
'YYYN'
And for check the answer you can use a generator expression within all :
>>> all(i=='Y' for i in l)
False
You don't need to change your loop condition. Just change the logic of your if expression.
letter = ''
for i in range(len(numToGuess)):
if int(number[i]) == numToGuess[i]:
letter += 'Y'
elif int(number[i]) > numToGuess[i]:
letter += 'H'
else:
letter += 'L'
Or, in one line:
letter = ''
for i in range(len(numToGuess)):
letter += 'Y' if int(number[i]) == numToGuess[i] else ('H' if int(number[i]) > numToGuess[i] else 'L')
I'm got the bulk of my first real attempt at a python program--a letter guessing game.
I've got the bulk of the work done, but I'm stuck on the last little bit
I want to make it so that the game alternates back and forth between user and AI turns, until the world has been fully revealed. I'm good so far up to here. At this point, I want to make it so the player to guess the most letters correctly wins a point. The computer moderator picks another word and starts again. The first player to five points wins the game.
I have a while loop that alternates between user/AI turns, but I can't get it to break properly once the word has been fully unveiled? After that it should be pretty simple to just compare the number of userCorrectLetters to the number of aiCorrectLetters and use that to determine who wins the point for the round.
Then I assume the entire thing should go inside a while loop that doesn't break until one of the players has reached 5 points.
The other thing I'm having problems with is how to disallow the user from re-guessing a character position that has already been solved.
import random
#set initial values
player1points= 0
ai= 0
userCorrectLetters= []
aiCorrectLetters=[]
wrongLetters=[]
wrongPlace= []
correctLetters = []
endGame = False
allLetters = set(list('abcdefghijklmnopqrstuvwxyz'))
alreadyGuessed = set()
userGuessPosition = 0
availLetters = allLetters.difference(alreadyGuessed)
#import wordlist, create mask
with open('wordlist.txt') as wordList:
secretWord = random.choice(wordList.readlines()).strip()
print (secretWord)
secretWordLength = len(secretWord)
def displayGame():
mask = '_' * len(secretWord)
for i in range (len(secretWord)):
if secretWord[i] in correctLetters:
mask = mask[:i] + secretWord[i] + mask [i+1:]
for letter in mask:
print (letter, end='')
print (' ')
print ('letters in word but not in correct location:', wrongPlace)
print ('letters not in word:', wrongLetters)
##asks the user for a guess, assigns input to variable
def getUserGuess(alreadyGuessed):
while True:
print ('enter your letter')
userGuess = input ()
userGuess= userGuess.lower()
if len(userGuess) != 1:
print ('please enter only one letter')
elif userGuess in alreadyGuessed:
print ('that letter has already been guessed. try again')
elif userGuess not in 'abcdefjhijklmnopqrstuvwxyz':
print ('only letters are acceptable guesses. try again.')
else:
return userGuess
def newGame():
print ('yay. that was great. do you want to play again? answer yes or no.')
return input().lower().startswith('y')
def userTurn(wrongLetters, wrongPlace, correctLetters):
print ('\n')
displayGame ()
print ('which character place would you like to guess. Enter number?')
userGuessPosition = input ()
if userGuessPosition not in ('123456789'):
print ('please enter a NUMBER')
userGuessPosition = input()
slice1 = int(userGuessPosition) - 1
##player types in letter
guess = getUserGuess(wrongLetters + correctLetters)
if guess== (secretWord[slice1:int(userGuessPosition)]):
print ('you got it right! ')
correctLetters.append(guess)
userCorrectLetters.append(guess)
displayGame()
elif guess in secretWord:
wrongPlace.append(guess)
print ('that letter is in the word, but not in that position')
displayGame()
else:
wrongLetters.append(guess)
print ('nope. that letter is not in the word')
displayGame()
def aiTurn(wrongLetters,wrongPlace, correctLetters):
print ('\n')
print ("it's the computers turn")
aiGuessPosition = random.randint(1, secretWordLength)
aiGuess=random.sample(availLetters, 1)
print ('the computer has guessed', aiGuess, "in position", + aiGuessPosition)
slice1 = aiGuessPosition - 1
if str(aiGuess) == (secretWord[slice1:userGuessPosition]):
correctLetters.append(aiGuess)
aiCorrectLetters.append(aiGuess)
print ('this letter is correct ')
return
elif str(aiGuess) in secretWord:
wrongPlace.append(aiGuess)
print ('that letter is in the word, but not in that position')
return
else:
wrongLetters.append(aiGuess)
print ('that letter is not in the word')
return
wordSolved = False
while wordSolved == False:
userTurn(wrongLetters, wrongPlace, correctLetters)
aiTurn(wrongLetters, wrongPlace, correctLetters)
if str(correctLetters) in secretWord:
break
The problem is here:
if str(correctLetters) in secretWord:
You might expect that str(['a', 'b', 'c']) returns 'abc' but it does not. It returns "['a', 'b', 'c']".
You should replace that line with:
if "".join(correctLetters) in secretWord:
There is one more problem with your code, except for this one:
Let's say the correct word is foobar. If the user guesses the first 5 letters, but in reversed order, correctLetters will be ['a', 'b', 'o', 'o', 'f'], and the line if "".join(correctLetters) in secretWord: will evaluate to False bacause 'aboof' is not in 'foobar'.
You could fix that problem by replacing if "".join(correctLetters) in secretWord: with:
if len(correctLetters) > 4:
Basically, this will end the execution of the program as soon as the user guesses 5 correct letters. There is no need to check if the the letters are in secretWord, because you already do that in userTurn function.
You are comparing the string representation of the list correctLetters to the string secretWord. For example:
>>> secretWord = 'ab'
>>> correctLetters = ['a','b']
>>> str(correctLetters)
"['a', 'b']"
>>> str(correctLetters) in secretWord
False
Try comparing a string made of the correct letters to the secret word:
>>> ''.join(correctLetters) == secretWord
True