I'm making a Hangman game. This function is supposed to check if a guessed letter is in the word, print the progress of the guesses so far, and update the array containing the guesses. "guess" is an array of underscores, each getting replaced by the correct letter as the game progresses:
def check_guess(word, guess, letter):
for i in range(len(word)):
if word[i] == letter:
guess[i] = letter
print(guess[i], end=' ')
else:
print('_', end=' ')
print ('\n')
return guess
So say the word is "eaten", guess is an array of five underscores, and the letter is 'e'. If I type:
guess = check_guess(word, guess, 'e')
It'll print correctly, but it won't update guess to
['e', '_', '_', 'e', '_']
It stays an array of five underscores.
In fact, it only updates the array if I code it like this:
def check_guess(word, guess, letter):
for i in range(len(word)):
if word[i] == letter:
guess[i] = letter
print(guess[i], end=' ')
print ('\n')
return guess
I'm completely stumped why the longer version does not update the array, but the shorter one does. I'm doing guess[i] = letter in both.
Thanks for any help in figuring this out. I like to understand why things work when they do!
well. first things first.
your code wont work for sintax issues. apparently you are trying to set a variable inside a print command, not sure why.
def check_guess(word, guess, letter):
for i in range(len(word)):
if word[i] == letter:
guess[i] = letter
print(guess[i], end=' ')
else:
print('_', end=' ')
print ('\n')
return guess
Results:
File "<ipython-input-1-14d09305bfe6>", line 5
print(guess[i], end=' ')
^
SyntaxError: invalid syntax
So lets disconsider "end" for a while to see exactly what your function is doing:
it asks for three parameters; word, guess, letter.
it goes through each letter in word in an uncoventional way (instead of getting the positions and reffering to 'em, you could just get the letters pretty straighforward)
it checks if the letter given == the letter at word
if so, it associates the letter at guess
and prints the letter
else it prints an underline
it returns the updated guess
Okay. So apparently guess could (should) be a global variable, as well as the "word".
Maybe it would be cleaner/wiser to only pass the letter as a function parameter. It would also be cleaner to go through each letter in the word instead of the position indexer, but at the same time we can enumerate it so we know how to refer to the guess variable. Also, besides printing one letter at a time, we can just print the whole guess at the end of the function. Also, if its a game you want it to be interative/recurrent until the player wins or loses, so it shld be inside a loop.
My version, wld look like this:
first part:
## declaring main variables ##
word = "Upvote this if helpful"
word = word.lower()
guess = list('_'*len(word))
for position, letter in enumerate(word):
if letter == ' ':
guess[position] = ' '
trials = 5
breaker = False
game function:
## defining guess function ##
def guess_function(letter):
letter = letter.lower()
missed_guess = True
global trials
global guess
global breaker
global word
for position, word_letter in enumerate(word):
if letter == word_letter:
missed_guess = False
guess[position] = letter
if missed_guess:
trials = trials - 1
print ('Letter %s not in word. You lose 1 trial. You got %d chances left!\n' %(letter, trials))
if trials == 0:
print ('Oh no! You lost! The word was: %s' %word)
breaker = True
return
else:
if '_' in guess:
print ('Word so far: %s\n%s chances left! Keep it going!\n' %(''.join(guess), trials))
else:
print ('You made it! The word was:\n%s\n\nCONGRATS!!' %(''.join(guess)))
breaker = True
return
game on:
breaker = False
while breaker==False:
input_letter = raw_input("Give me a letter!")
guess_function(input_letter)
sample game:
Give me a letter!a
Letter a not in word. You lose 1 trial. You got 4 chances left!
Give me a letter!u
Word so far: u_____ ____ __ _____u_
4 chances left! Keep it going!
Give me a letter!p
Word so far: up____ ____ __ ___p_u_
4 chances left! Keep it going!
Give me a letter!v
Word so far: upv___ ____ __ ___p_u_
4 chances left! Keep it going!
Give me a letter!o
Word so far: upvo__ ____ __ ___p_u_
4 chances left! Keep it going!
Give me a letter!t
Word so far: upvot_ t___ __ ___p_u_
4 chances left! Keep it going!
Give me a letter!e
Word so far: upvote t___ __ _e_p_u_
4 chances left! Keep it going!
Give me a letter!h
Word so far: upvote th__ __ he_p_u_
4 chances left! Keep it going!
Give me a letter!i
Word so far: upvote thi_ i_ he_p_u_
4 chances left! Keep it going!
Give me a letter!s
Word so far: upvote this i_ he_p_u_
4 chances left! Keep it going!
Give me a letter!f
Word so far: upvote this if he_pfu_
4 chances left! Keep it going!
Give me a letter!l
You made it! The word was:
upvote this if helpful
CONGRATS!!
I found the culprit. It's a silly "else" oversight:
if word[i] == letter:
guess[i] = letter
print(guess[i], end=' ')
else:
print('_', end=' ')
The code is saying if the letter matches, print it. Otherwise, print _ no matter what even if the list guess does not have "_" at that position. D'oh!
My bigger question now is why would guess when used in check_guess be a global variable? Shouldn't I need to say return guess for the list to update when called outside of this particular function? I can start another question if that would be best.
def check_guess(word, guess, letter):
for i in range(len(word)):
if word[i] == letter:
guess.append(letter)
else:
guess.append("_")
print ('\n')
return guess
guess=[]
check_guess("eaten", guess, 'e')
This works for me and updates guess. For the first one you need to define an empty list >> guess first then add to it as you go by.
Related
I'm trying to program hangman and I run into a problem. In line 48 you see that I'm trying to copy the word that has been guessed so far. But the problem is when the program asks for the next letter. For example, if the user have guessed the letter 'h', it says h____ and the next turn I guess the letter e it says _e___ but I want it to say in this example he___.
word = 'hello'
guessed = False
guess_word = secret_word(word)
a = '____'
while guessed == False:
letter = ask_letter_from_user()
if is_the_letter_in_the_word(word, letter):
locatie_letter_in_woord = location_of_letter_in_word(word, letter)
a = replace(guess_word, locatie_letter_in_woord, letter)
print(a)
Seems like a and guess_word should actually be one variable.
You are passing guess_word to the replace function after every guessed letter, but you are never updating its value. Instead, you're updating a.
Get rid of a. Next time, give all your variables meaningful names, then you might realized that you have two variables for one purpose :-)
Instead of calling replace(guess_word, locatie_letter_in_woord, letter), simply do a = a[:locatie_letter_in_woord] + letter + a[locatie_letter_in_woord+1:]. This will prevent the previous letter from being overwritten.
Output:
wich letter do you want to try?: h
well done! you guessed the letter
youre guessed letters are: h
a: h___
wich letter do you want to try?: e
well done! you guessed the letter
youre guessed letters are: h,e
a: he__
Try this:
you can turn the word into a list and have each letter checked one by one
word = 'hello'
guessed = False
found = []
guess_word = secret_word(word)
while guessed == False:
guess= ask_letter_from_user()
if is_the_letter_in_the_word(word, letter):
print('well done! you guessed the letter')
word_as_list = list(guess_word)
indices = [i for i, letter in enumerate(word) if letter == guess]
for index in indices:
word_as_list[index] = letter
found.append(letter)
print('youre guessed letters are: ' + list_joining(found))
guess_word = "".join(word_as_list)
print(guess_word)
In line 47 in place of:
a = replace(guess_word, locatie_letter_in_woord, letter)
write
a = replace(a, locatie_letter_in_woord, letter)
wich letter do you want to try?: h
well done! you guessed the letter
youre guessed letters are: h
h___
wich letter do you want to try?: e
well done! you guessed the letter
youre guessed letters are: h,e
he__
wich letter do you want to try?:
Still, this program has a problem. When you are calling the function:
def location_of_letter_in_word(word, letter):
return word.find(letter)
Look carefully for the second l in hello; it will return the location of the first l.
I am currently stuck on exercise 10.1.3 on CodeHS, which is essentially a part in making a hangman game, without the hangman. I have my code nearly complete for this section of the game, yet for some reason whenever new input is given (for a letter), it clears previous input.
Here is my code:
secret_word = "character"
dashes = "-" * len(secret_word)
print(dashes)
#Prints the first row of dashes to indicate word length
def get_guess():
while True:
guess = input("Guess: ")
if isinstance(guess, int):
print("Your guess must be a lowercase letter.")
else:
if guess.islower():
if len(guess) == 1:
return guess
else:
print("Your guess must have exactly one character.")
def update_dashes(secret_word, dashes, guess):
result = ""
for i in range(len(secret_word)):
if secret_word[i] == guess:
result = result[:i] + guess + result[i + 1:]
else:
result = result + "-"
return result
while True:
guess = get_guess()
if guess in secret_word:
print("The letter is in the word.")
else:
print("That letter is not in the word.")
print(update_dashes(secret_word, dashes, guess))
#We believe the issue is here, it is printing the full set each time this loops.
When run, this is the output:
---------
Guess: c
The letter is in the word.
c----c---
Guess: h
The letter is in the word.
-h-------
Guess:
The code should be adding the "h" to the word, yet it is 'overwriting' what is already there.
This is what I want it to print:
---------
Guess: c
The letter is in the word.
c----c---
Guess: h
The letter is in the word.
ch---c---
Guess:
Note that the word that should be guessed is "character".
And finally, this is the part of the assignment that relates to what the current problem is:
Step 2 - Update the Dashes
Here’s the tricky part. Write a function called update_dashes that
takes three string arguments - the secret word, the current state of
dashes, and the most recent guess - and returns the new state of
dashes.
So, for example, if the word is "eggplant", the current value of
dashes is "e-------", and the guess is "g", the function should return
"egg-----".
If the word is "eggplant", the current value of dashes is "e-------",
and the guess is "z", the function should return "e-------" (nothing
changes, since the guess was incorrect).
Here’s how you might go about this.
In your function, start with an empty result string. Write a for loop
from 0 up to but not including the length of your secret word. Say you
use the variable i in your for loop. Compare the character in
secret_word at index i to the guess. If they’re equal, then that means
the guess matches that letter in the word, so you should add the guess
to the result. Otherwise, the guess does not match that letter in the
word, so you should add whatever was at index i in dashes to your
result.
Wait, why don’t I just add a dash in the second case?
If you just add a dash whenever the guess doesn’t match the character
in secret_word at index i, that will wipe out any correct guesses the
user has already made! Imagine the case where the word is “eggplant”,
the state of dashes is “e——-“, and the guess is “g”. If you always add
a dash when the guess doesn’t match the character in secret_word at
index i, the result would be “-gg—–”. Suddenly, the “e” is gone,
because “g” did not match “e”! By instead using dashes at index i, you
might append either a letter or a dash, depending on whether or not
the user had already guessed that letter prior to the current guess.
Once your for loop is done, your result string should have letters and
dashes in all the right places, so you can just return it!
As the instructions say, when the guess doesn't match you should add the corresponding element of dashes to the result, not just a dash. You need to do this so that all the previous correct guesses are copied to the result.
def update_dashes(secret_word, dashes, guess):
result = ""
for i in range(len(secret_word)):
if secret_word[i] == guess:
result += guess
else:
result += dashes[i]
return result
Additionally, your main loop has to assign the result back to dashes so it accumulates all the correct guesses.
while True:
guess = get_guess()
if guess in secret_word:
print("The letter is in the word.")
dashes = update_dashes(secret_word, dashes, guess)
else:
print("That letter is not in the word.")
print(dashes)
I'm trying to do a guessing game in python but I cant figure some stuff out. I have to enter a word and it will print a lot of spaces and the person is suppose to guess the word. It has to look like this after the word it's been typed. The user will enter a letter and is suppose to look like this (word is dog):
Enter a letter: a
So far you have:
***
if they guess the "o" for example, it will replace the * with an 'o' and so on until you get all the words right. And that's what I can't figure out, can somebody please help me? here is my program for far:
def main():
letters_guessed = set()
# Read word
word = input("\n Please Enter a word: ")
# print 100 spaces
print("\n" * 100)
# Storing the length of the word
word_length = len(word)
guess = '*' * word_length
while True:
print ("So far you have: ",
guess_letter = input ("Please guess a letter: ")
if len(guess_letter) != 1:
print ("Please guess one letter at a time")
if guess_letter in letters_guessed:
print ("\n You already guessed that letter, please try again")
letters_guessed.add(guess_letter)
if set(word) == set(letters_guessed):
break
print("You won, the word is " % word)
Somebody tried to help me but I just didn't understand how this works because I am new to the program, I want to be able to understand it also. Thank you. Here it was his output, just part of it.
while True:
print ("So far you have: ", "".join([c if c in letters_guessed else "*"
for c in word]))
guess_letter = input ("Please guess a letter: ")
I'll first explain the solution code you received. The following code:
[c if c in letters_guessed else "*" for c in word]
generates a list. If you see square brackets [ and ] , then we're list likely creating a list.
now what your friend is using is a generator. It's a short way of creating a for loop. In other words, this would do the same thing.
word = "dog"
letter_guessed = "go"
ourList = list() #new list
for letter in word: #we check every letter in the word
if letter in letter_guessed: #if our letter has been guessed
ourList.append(letter) # we can show that letter in our word
else:
ourList.append("*") # if the letter has not been guessed, we should
# not show that letter in our word, and thus we change it to a *
print(ourList)
This gives us the following list: ["*", "o", "g"]
What your friend then does, is take that list, and use join:
"".join[ourList]
This is a good way of turning a list of letters back into a string.
See: https://www.tutorialspoint.com/python/string_join.htm
Your own code has a few problems. Is it possible you didn't copy everything?
In python, using tabs effects the way your program runs. Because you put a tab before
print("You won, the word is " % word)
you'll run this line every single time, rather than only when the break statement is activated!
You have a similar problem with .add! Try to see if you can't spot it yourself.
I also recommend writing
print("You won, the word is " + word)
because this is much easier to use. (for more advanced formatting, look up .format() see https://pyformat.info/
I am trying to create a simple Hangman game using Python. I have faced a problem which I can't solve and would be grateful to receive some tips from you guys.
Okay I will provide you with a sample of my code and below it, I will explain what my issue is:
# Here is my list of words
words = ['eight', 'nine', 'seven'...]
# Choosing a random word from the list
word = random.choice(words)
# Creating an empty list to store the result
secret_word = []
# Creating a count variable which I will use later to determinate if the player wins
count = 1
for letter in word:
secret_word.append('_')
secret_word[0] = word[0]
user_guess = input("Enter a letter: ")
# Here if the user guesses a letter
# We will place that letter on it's spot in our secret_word
while user_guess:
if user_guess in word:
print("Correct letter.")
# adding 1 to count for every guessed letter
count += 1
# replacing the '_' with the letter
for letter in range(len(word)):
if user_guess == word[letter]:
secret_word[letter] = word[letter]
# here I am checking if the user has won
if count == len(word):
print("You Win!")
I gave you only a part of my program because I don't think that there's a need for the entire code.
My problem is in the count variable. As you can see I am adding + 1 to the variable every time when the user guesses a correct letter so when the count variable = len(word) my little program will know that the user had won.
Anyways when one single letters appears twice in the word like for example the word SEVEN haves the letter E two times my count variable still goes up by only 1 so the user cant win in a case like this. I have absolutely no idea how to fix this and would be happy to receive some hints.
Thank you and please excuse my bad English and coding skills
You could increment count whenever you replace an underscore with the correct the letter. That way, count will be equal to the number of letters correct in the word so far.
To be more clear, move count += 1 to be in the if statement when you replace underscores with the actual letter.
One problem I see with this is you're giving the player the first letter and initializing count to 1. I don't know why you're doing this, but if the first letter occurs more than once, it won't be reflected in the word, and the player will still have to guess that letter anyways.
Move the count to where you are replacing the letter.
while user_guess:
if user_guess in word:
print("Correct letter.")
# replacing the '_' with the letter
for letter in range(len(word)):
if user_guess == word[letter]:
# adding 1 to count for every guessed letter
count += 1
secret_word[letter] = word[letter]
# here I am checking if the user has won
if count == len(word):
print("You Win!")
Im working on a word game. The purpose for the user is to guess a 5 letter word in 5 attempts. The user can know the first letter. And if he doesn't get the word correct, but if he has a letter in the correct place he gets to know this.
This is my code:
import random
list_of_words = ["apple","table", "words", "beers", "plural", "hands"]
word = random.choice(list_of_words)
attempts = 5
for attempt in range(attempts):
if attempt == 0:
tempList = list(word[0] + ("." * 4))
print("The first letter of the word we are looking for: %s" % "".join(tempList))
answer = raw_input("What is the word we are looking for?:")
if len(answer) != 5:
print ('Please enter a 5 letter word')
Else:
if answer != word:
wordlist = list(word)
answerlist = list(answer)
for i in range(min(len(wordlist), len(answerlist))):
if wordlist[i] == answerlist[i]:
tempList[i] = wordlist[i]
print(tempList)
else:
print("correct, you have guessed the word in:", attempt, "attempts")
if answer != word:
print("Sorry maximum number of tries, the word is: %s" % word)
I have two questions about this code:
The first one is a small problem: If the user gives a 6 or 4 letter word it will still print the word. While I'd rather have it that the word is just ignored and the attempt isnt used..
If a letter is given correct (and also the first letter) it doesnt become a standard part of the feedback. Trying to get this with temp but of yet its not working great.
Any suggestions to clean up my code are also appreciated!
Thanks for your attention
I made some changes in your code, now it's working according to your specification. I also wrote a couple of explaining comments in it:
import random
list_of_words = ["apple", "table", "words", "beers", "plural", "hands"]
word = random.choice(list_of_words)
# changed the loop to a 'while', because i don't want to count the invalid length answers
# and wanted to exit the loop, when the user guessed correctly
attempts = 5
attempt = 0
correct = False
while attempt < attempts and not correct:
if attempt == 0:
# i stored a working copy of the initial hint (ex: "w....")
# i'll use this to store the previously correctrly guessed letters
tempList = list(word[0] + ("." * 4))
print("The first letter of the word we are looking for: %s" % "".join(tempList))
answer = raw_input("What is the word we are looking for?:")
if len(answer) != 5:
print("Please enter a 5 letter word")
else:
if answer != word:
# i simplified this loop to comparing the wordlist and answerlist and update templist accordingly
wordlist = list(word)
answerlist = list(answer)
for i in range(min(len(wordlist), len(answerlist))):
if wordlist[i] == answerlist[i]:
tempList[i] = wordlist[i]
print(tempList)
else:
correct = True
print("Correct, you have guessed the word in %s attempts" % (attempt + 1))
attempt += 1
if answer != word:
# also i used string formatting on your prints, so is prints as a string, and not as a tuple.
print("Sorry maximum number of tries, the word is: %s" % word)
There are several problems with the code.
Just 1 for now. I notice in the sample output you are entering five letter words (beeds and bread) and it still prints out Please enter a 5 letter word.
These two lines:
if len(answer) != 4:
print ('Please enter a 5 letter word')
Surely this should be:
if len(answer) != 5:
print ('Please enter a 5 letter word')
continue
This would catch an invalid input and go round the loop again.
Answering your specific questions:
You will need to have a for loop around your input, keeping the user in that loop until they enter a word of appropriate length
If you move guessed letters to the correct places, it is trivial to win by guessing "abcde" then "fghij", etc. You need to think carefully about what your rules will be; you could have a separate list of "letters in the guess that are in the answer but in the wrong place" and show the user this.
To keep the display version with all previously-guessed characters, keep a list of the display characters: display = ["." for letter in answer], and update this as you go.
Other problems you have:
Too much hard-coding of word length (especially as len("plural") != 5); you should rewrite your code to use the length of the word (this makes it more flexible).
You only tell the user they've won if they guess the whole answer. What if they get to it with overlapping letters? You could test as if all(letter != "." for letter in display): to see if they have got to the answer that way.
Your list comprehension [i for i in answer if answer in word] is never assigned to anything.