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)
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 in high school and am currently teaching myself Python. I am programming Hangman and it is going well so far (it is not very organized yet) but I am having a problem. I created a list of words that I would use for the game and replaced them with asterisks using the range function. Here is the code for that:
words = ['utopia', 'prosecute', 'delirious', 'superficial', 'fowl', 'abhorrent', 'divergent',
'noxious', 'scarce','lavish', 'hinder', 'onerous', 'colossal', 'infringe']
picked_words = random.choice(words)
for i in range(len(picked_words)):
print(picked_words.replace(picked_words,'*'), end = '')
I am at the point where I am guessing the letters and I need to slowly reveal the position of certain letters. I have tried looking for certain functions (I even thought that the find() function would work since it prints the location of a letter in a string but it did not) and I am at a loss. Especially for words with multiples of the same letter such as "onerous" and "infringe." I will write the code that I have so far for this section:
def right_letter(correct):
if correct == True:
print("There are {} {}'s.".format(number_of_char, guess))
for x in range(len(picked_words)):
print(picked_words.replace(picked_words,guess, #find way to fill in specific letters),end = '')
I have no clue what parts of the code are necessary to get an answer but my code is really unorganized because I do not know proper techniques yet. The portion that says for x in range(len(picked_words))... is where I am having trouble. The rest of the code ran fine before I added the print statement underneath it. Basically I am asking how to change a certain character or specific characters and put them where they belong. For example, if the randomized word was "infringe" and the first guess was "i" how do I go from ******** to i***i***?
Also, in case anyone was wondering what I originally thought the solution was...
picked_words[(picked_words.find(guess))]
I thought that it would simplify and become picked_words[index]
Here's an example of converting your code to the hangman game.
Note how variable display in the code is updated to show user the correct guessed letters.
import random
def hangman():
words = ['utopia', 'prosecute', 'delirious', 'superficial', 'fowl', 'abhorrent', 'divergent',
'noxious', 'scarce','lavish', 'hinder', 'onerous', 'colossal', 'infringe']
max_guesses = 5
word = random.choice(words)
guesses = 0
display = "*" * len(word)
print(display, " Is the word")
while guesses < max_guesses:
letter = input("Please Enter Your guess letter: ")
if letter.lower() not in word:
guesses += 1
print("You got it incorrect, you have: ", max_guesses - guesses , " Additional trials")
else:
print("Right guess!")
new_display = ''
for w, l in zip(word, display):
if letter.lower() == w:
new_display += letter.lower()
else:
new_display += l
display = new_display
print(display)
if not '*' in display:
print("You won!")
return
hangman()
Basically you will need to find a partial match between your letter and the word here.
The easiest way i can think of is Pythons in Operator. It can be used like this
if picked_letter in picked words
% here you need to figure out at which position(s) the letter in your word occurs
% and then replace the * at the correct positions. A nice way to do this is
% the use of regular expressions
picked_words = re.sub('[^[^picked_letter]*$]', '*', picked_words)
%this will replace every letter in your word with the Asterisk except for the one picked
else
%do Nothing
Note that running this Code in a loop would replace every character in your string except the picked one EVERY time., therefore it is probably best to design your picked_letter as a list containing all characters that have been picked so far. This also makes it easier to check wether a letter has already been entered.
I would like to find out where in 'words' the users 'guess' is, and then print the guessed character alongside '_' in the correct position:
words = "apple"
print("_ " *len(words), end="")
guessed = ""
for char in words:
guess = input("\n start guessing")
if guess in words:
for i in guess:
guessed += guess
else:
print("wrong letter")
The following should work:
word = "apple"
guessed = "_ " *len(word)
print(guessed)
while '_' in guessed:
guess = input("\nGuess a letter\n")
if len(guess) == 1:
if guess in word:
guessed = ' '.join([x if x == guess or x in guessed else '_' for x in word])
print(f"You guessed correct, the letter {guess} is in the word:\n{guessed}")
else:
print(f"Sorry, {guess} ist not correct.")
print('Congratulations, you solved it!')
I replaced the for with a while loop that exits, when there are no underscores left in the word the user has to guess. This allows the user to guess until the word is complete. If you want to limit the user to certain amount of guesses, you could add a counter variable and break the loop accordingly.
The script furthermore checks if the input is a single character with if len(guess) == 1:. The list comprehension then replaces underscores based on the condition that whether the user already guessed the character earlier on (x in guessed) or in this round (x == guess).
Note that this solution involving f-strings works in python versions >3.6. If you're using another python version, you'll have to replace the f-strings. In addition, I should mention that this code is case sensitive. So if your word starts with an uppercase letter and the user guessed the first letter but as a lowercase, the script will consider it as a wrong letter.
I'm developing a simple text-based hangman game (a graphical interface may be included at a later date) and there is one issue I cannot overcome involving there being more than one of the same letter in the word you need to guess.
Below is what I'm currently using in my code to define the act of the user guessing what letter could be in the word (via the function guess()) as well as the code telling the user if their guess is correct or not, or if they've guessed that word already (function guessing()). [ignore the confusing function/array/variable names, I have a weird naming system and they're currently placeholders]
def guess():
global letterGuess
try:
letterGuess = str(input("guess a letter: "))
if len(letterGuess) > 1:
print("only input one letter, please.")
guess()
except ValueError:
print("you have inputted something other than a letter. please try again.")
guess()
letterGuess = letterGuess.lower()
print("you guessed",letterGuess)
def guessing():
global correctLetters
global incorrectLetters
global lives
global letterGuess
global word
global guessyLetters
print("")
print("you have",lives,"lives and have",guessyLetters,"letters to guess.")
print("correct letters guessed so far: ", correctLetters)
print("incorrect letters guessed so far:", incorrectLetters)
guess()
time.sleep(0.5)
print("")
if letterGuess in word:
if letterGuess in correctLetters:
print("you have already guessed this letter.")
else:
print("you have guessed a letter correctly!")
correctLetters.append(letterGuess)
guessyLetters -= 1
else:
if letterGuess in incorrectLetters:
print("you have already guessed this letter.")
else:
print("you have guessed incorrectly.")
incorrectLetters.append(letterGuess)
lives -= 1
Say, for example, the word is "rabbit" where there are two b's.
the code will accept that "b" is in the word "rabbit" but will only accept one of the b's, now meaning that guessing b again is impossible as the program will return "you have already guessed this letter". This makes the game impossible to win as there will always be the remaining second "B" you need to guess.
alternatively, I tried to create a while loop of "while [letterGuess] in [word]" however that only means that, so long as the letter is in the word, then the amount of letters the user needs to guess will keep depleting until it gets to 0 (pretty much, the loop means that if the user guesses one correct answer then they automatically win)
I have tried scheming a possible way of countering this by putting the individual letters of the variable/word into an array, then using that to pick out the values in the array that match the users guess. I've also decided that adding an array of blank spaces "" and printing that, showing any words that have been guessed correctly replacing the spaces.
e.g.:
word is: house. wordArray = ['h','o','u','s','e'] , spaces = ['','','','',''] (number of spaces corresponds with number of values in wordArray, if a letter is guessed then the corresponding value in spaces is replaced with the letter)
I've tried to bullet point a simplified version of what I want to try and do here:
split variable into separate letters
put separate letters into array
create array with same number of values marked "_"
if guess is in wordarray:
replace spaces[x] with wordarray[x]
for ALL spaces where wordarray[x] = guess
Summary - if I need to guess the letters in word "rabbit" and I need to guess the letter B, then I want my code to accept this letter as a correct answer AND also mark both of the B's as guessed instead of one. I propose that this could be done using ~two arrays, however I am not sure how this would be written. Could anyone provide any methods of writing this out?
Here is an example of how to go with the test driven development method (TDD) I talk about in my comment. Just for the first point of your bullet list.
word_to_guess = 'rabbit'
# How to store the letter of the word to guess in an array?
# Think of a test
# assertTrue(strToArray(word_to_guess), ['r', 'a', 'b', 'b', 'i', 't'])
# Now create the function
def strToArray(my_str):
my_array = [letter for letter in my_str]
return my_array
# Now make sure it passes.
if strToArray(word_to_guess) == ['r', 'a', 'b', 'b', 'i', 't']:
print('that work')
# Now try to think of all edges cases. e.g
# Ah... but now, we have duplicated 'b' letter, does it exists another datastructure to avoid have duplicated letters?
# Ah yes, I remember my CS classes! python's sets!
# Think of a test...
# Create the function.
def strToSets(my_str):
my_set = set(my_str)
return my_set
# Make sure it work...
if strToSets(word_to_guess) == set(['r', 'a', 'b', 'i', 't']):
print('that work')
# But what if the word_to_guess have non-alphanumeric letters or uppercase letters?
# so forth and so on...
FYI, it exists way better method to do testing in python. the example is just for you to have an idea, I personally use Nosetests.
But it is up to you to use the best tools accordingly to your needs. I recommand Doctest to start with (you are writing tests in your docstrings).
Hope it helped you in any way.
You can define a new function which takes letters guessed and the word you are trying find, then iterates over them. Whenever letter is part of the word increment a counter value and then compare it to the length of your secret word, if the isWordGuessed returns true it means they have guessed the word otherwise the word has not been guessed yet.
def isWordGuessed(secretWord, letterGuess):
# counter variable
guesses = 0
# go through each word in letterGuess
for letter in letterGuess:
# if the letter is in word increment guess by one
if letter in word:
guesses += 1
# compare guess counter with length of the word
if guesses == len(word):
return True
else:
return False
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!")