Python "Hangman" Code - python

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

Related

10.1.3 Guess the Word, Part 2 Help Needed

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)

Why is this loop not working, also how do I make the code remember the previous letters guessed?

Im new to programming and was trying to program a word guesser. I dont understand why the while loop doesnt go though three times, also the program doesnt remember the previously guessed letters.
import random
words = ["hello", "bye", "petscop"]
GuessWord = random.choice(words)
tries = 3
while tries > 0:
tries = tries - 1
inp = input("\nEnter your guess: ")
for char in GuessWord:
if char in inp:
print(char, sep="",end="")
elif char not in inp:
print("_", sep="",end="")
tries = tries - 1
I'm sorry to say, StackOverflow isn't a forum for debugging. StackOverflow is more about solving general problems that affect multiple people rather than single instances of a problem (like bugs), if that makes sense.
There is probably a better place for you to ask this question but I can't think of one off the top of my head.
In the spirit of being constructive: the following code appears twice and you should remove the second instance.
tries = tries - 1
Also, you are overwriting inp each time you enter the loop causing it to forget its previous value. There are other issues too. But that's a good start.
The main problem you have is that you decrease the number of tries by 2 each round. Therefore, at the beginning of the second round, the number of tries decreases again so it fails. This is how I would do it:
import random
# library that we use in order to choose
# on random words from a list of words
name = input("What is your name? ")
# Here the user is asked to enter the name first
print("Good Luck ! ", name)
words = ['rainbow', 'computer', 'science', 'programming',
'python', 'mathematics', 'player', 'condition',
'reverse', 'water', 'board']
# Function will choose one random
# word from this list of words
word = random.choice(words)
print("Guess the characters")
guesses = ''
# any number of turns can be used here
turns = 3
while turns > 0:
# counts the number of times a user fails
failed = 0
# all characters from the input
# word taking one at a time.
for char in word:
# comparing that character with
# the character in guesses
if char in guesses:
print(char)
else:
print("_")
# for every failure 1 will be
# incremented in failure
failed += 1
if failed == 0:
# user will win the game if failure is 0
# and 'You Win' will be given as output
print("You Win")
# this print the correct word
print("The word is: ", word)
break
# if user has input the wrong alphabet then
# it will ask user to enter another alphabet
guess = input("guess a character:")
# every input character will be stored in guesses
guesses += guess
# check input with the character in word
if guess not in word:
turns -= 1
# if the character doesn’t match the word
# then “Wrong” will be given as output
print("Wrong")
# this will print the number of
# turns left for the user
print("You have", + turns, 'more guesses')
if turns == 0:
print("You Loose")

How to reveal a specific letter in a string for Python?

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.

Python hangman game. Python 3

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!")

Notify user when they got a letter correct in a char list Python

How would I go about telling the user when they've got the correct letter in a list? Only way I know of is to insert the index, but that doesn't feel very flexible, especially when the words vary in length.
import random
possibleWords = [["apple"], ["grapefruit"], ["pear"]]
randomWord = random.choice(possibleWords)
anotherWord = ''.join(randomWord)
finalWord = list(anotherWord)
maxTries = list(range(0, 11))
attemptsMade = 0
triesLeft = 10
print("Hangman!")
print("\nYou got {} tries before he dies!".format(maxTries[10]))
print("There's {} possible letters.".format(len(finalWord)))
for tries in maxTries:
userChoice = input("> ")
if userChoice == finalWord[0]:
print("You got the first letter correct! It is {}.".format(finalWord[0]))
else:
print("Ouch! Wrong letter! {} tries remaining.".format(triesLeft))
attemptsMade += 1
triesLeft -= 1
Talking about characters in lists, or - what i think is more likely in your case - chars in words you can just check for
if userChoice in finalWord:
# [...] do stuff here
and further on use the index function to determine the position (or positions if multiple occurence).
finalWord.index(userChoice)
You could sure also go the way using index() function directly and work your way using the return values.
Use Python's "in" keyword to check if something is within a list/iterable.
if userChoice in finalWord:
Though for this, I'd just use regex or list comprehension to get the indexes while you are at it, since you might want them for the game.
char_indexes = [i for (i, l) in enumerate(finalWord) if l == userChoice]
if len(char_indexes):
Use a set for the letters that are in the word, and whenever the player guesses a letter, check if the letter is still in the set. If it’s not, it was a wrong letter; if it is, then remove that letter and just continue. If the set is empty at some point, then the player guessed all letters of the word.
Something to get you started:
def hangman (word):
letters = set(word.lower())
attempts = 5
while attempts > 0:
guess = input('Guess a character ')
if guess[0].lower() in letters:
print('That was correct!')
letters.remove(guess[0])
else:
print('That was not correct!')
attempts -= 1
if not letters:
print('You solved the word:', word)
return
hangman('grapefruit')

Categories