Here's my code, everything works I think except it doesn't take any value more than one. Please help me out.
word = input("What's your word?\n").upper()
forguess = " ".join(word)
char = "_"
for index in range(len(word)):
word = word[:index] + char + word[index+1:]
spacedwords = " ".join(word)
print(spacedwords)
chances = 5
while chances != 0:
print("You have " + str(chances) + " chances left\n")
letter = input("Guess the letters: \n").upper()
if letter in forguess: #check if the input letter is in original word
pos = forguess.index(letter) #gets the letter position from forguess original word
spacedwords = spacedwords[:pos] + letter + spacedwords[pos+1:] #replace word in the blank ones
print(spacedwords)
if spacedwords == forguess:
print("YOU WON!!!")
break
else:
chances -= 1
if chances == 0:
print("YOU LOOSE!!!")
The main reason why your code does not work is that, while spacedwords changes when you guess a letter, forguess does not. This way your index call always just finds the first occurrence of letter. Trying to modify your code as little as possible (there would be more efficient ways to do this), here an example of how to achieve what you want:
word = input("What's your word?\n").upper()
forguess = " ".join(word)
char = "_"
for index in range(len(word)):
word = word[:index] + char + word[index+1:]
spacedwords = " ".join(word)
print(spacedwords)
chances = 5
while chances != 0:
print("You have " + str(chances) + " chances left\n")
letter = input("Guess the letters: \n").upper()
if letter in forguess: #check if the input letter is in original word
positions = [i for i,x in enumerate(forguess) if x == letter] #gets all letter positions from forguess original word
for pos in positions:
spacedwords = spacedwords[:pos] + letter + spacedwords[pos+1:] #replace all blank positions with letter
print(spacedwords)
if spacedwords == forguess:
print("YOU WON!!!")
break
else:
chances -= 1
if chances == 0:
print("YOU LOOSE!!!")
EDIT:
As the first time around I misunderstood what the OP intended to do, here again an example that tries to modify the original code as little as possible. I introduced a new variable original that in the beginning is identical to forguess. Now, every time a letter is guessed correctly, forguess is modified (the guessed letter is changed into a NULL character), so that in the next search it will not show up again. Then, in the end spaceedwords is compared to original instead of forguess.
word = input("What's your word?\n").upper()
forguess = " ".join(word)
original = " ".join(word)
char = "_"
for index in range(len(word)):
word = word[:index] + char + word[index+1:]
spacedwords = " ".join(word)
print(spacedwords)
chances = 5
while chances != 0:
print("You have " + str(chances) + " chances left\n")
letter = input("Guess the letters: \n").upper()
if letter in forguess: #check if the input letter is in original word
pos = forguess.index(letter) #gets the letter position from forguess original word
spacedwords = spacedwords[:pos] + letter + spacedwords[pos+1:] #replace word in the blank ones
forguess = forguess[:pos] + chr(0) + forguess[pos+1:]
print(spacedwords)
if spacedwords == original:
print("YOU WON!!!")
break
else:
chances -= 1
if chances == 0:
print("YOU LOOSE!!!")
Note:
The whole problem would be much more easy to handle, if you converted you forguess into a list of single characters.
Related
I am currently creating a hangman game for a project. I have managed to code where a user can enter individual letters to guess the secret word. However, I am having trouble adding an additional feature where the user can guess the entire word upfront.
below is my code attempt, may I know what to write to have this new feature in my game?
def game_play():
word = random.choice(WORDS)
# Dashes for each letter in each word
current_guess = "-" * len(word)
# Wrong Guess Counter
wrong_guesses = 0
# Used letters Tracker
used_letters = []
while wrong_guesses < MAX_WRONG and current_guess != word:
print (HANGMAN[wrong_guesses])
print ("You have used the following letters: ", used_letters)
print ("So far, the word is: ", current_guess)
guess = input ("Enter your letter guess:")
guess = guess.upper()
# Check if letter was already used
while guess in used_letters:
print ("You have already guessed that letter", guess)
guess = input ("Enter your letter guess: ")
guess = guess.upper()
# Add new guess letter to list
used_letters.append(guess)
# Check guess
if guess in word:
print ("You have guessed correctly!")
# Update hidden word with mixed letters and dashes
new_current_guess = ""
for letter in range(len(word)):
if guess == word[letter]:
new_current_guess += guess
else:
new_current_guess += current_guess[letter]
current_guess = new_current_guess
else:
print ("Sorry that was incorrect")
# Increase the number of incorrect by 1
wrong_guesses += 1
# End the game
if wrong_guesses == MAX_WRONG:
print (HANGMAN[wrong_guesses])
print ("You have been hanged!")
print ("The correct word is", word)
else:
print ("You have won!!")
game_play()
Rather than prompting the user for a new guess each time, you could overwrite the line where you output their previous guesses so far, so the output may look something like:
Word: _ A N _ _ A N Misses: B C D
This would mean they could just keep typing guess and the line would update. See python overwrite previous line for details on how to overwrite previous line.
The input command will let you enter multiple letters. I don't see anything stopping the user entering the full word there already?
Instead of counting each letter which matches/fails you could maintain a set of correct/failed guesses and check against the number of items in the set. Maybe something like:
import random
WORDS = ['STACK', 'OVERFLOW', 'HELP']
def playgame():
word = random.choice(WORDS)
# valid characters
valid = set((chr(c) for c in range(ord('A'), ord('A') + 26)))
# unique characters in word
unique = set((c for c in word))
hits = set()
misses = set()
allowed_misses = 5
complete = False
while complete == False:
guess = input("Enter your guess: ").upper()
for c in (c for c in guess if c in valid):
if c in unique:
hits.add(c)
else:
misses.add(c)
# break out of for
if len(hits) == len(unique) or len(misses) > allowed_misses:
complete = True
break
if not complete:
# output continuation messages
print(f'Hits: {hits} misses: {misses}')
if len(hits) == len(unique):
# output sucess message
print(f'Success: hits {hits} misses {misses}')
else:
# output fail message
print(f'Fail: hits {hits} misses {misses}')
if __name__ == '__main__':
playgame()
I have included the additional feature to enter the entire word, and also refactored your code. If the user entered the entire word correctly, I'd assign current_guess with the correct word and break the while loop. Please have a look
import random
WORDS = ['apple', 'kiwi', 'banana']
MAX_WRONG = 3
def game_play():
word = random.choice(WORDS).upper()
current_guess = '-' * len(word) #hidden answer
wrong_guesses = 0
used_letters = []
while wrong_guesses < MAX_WRONG and current_guess != word:
print ('\nRemaining tries:', MAX_WRONG - wrong_guesses)
print ('So far, the secret word is: ', current_guess)
print ('You have used the following letters: ', used_letters)
guess = input('Enter your letter guess:').upper()
if guess == word:
current_guess = word
break #exit the while-loop
while guess in used_letters: #check for duplicate input
print ('You have guessed "' + guess + '" already!')
guess = input ('Enter your letter guess: ').upper()
used_letters.append(guess) #append guess to used_letters
if guess in word:
print ('You have guessed correctly!')
new_current_guess = ''
for idx in range(len(word)): #update hidden answer
if guess == word[idx]:
new_current_guess += guess
else:
new_current_guess += current_guess[idx]
current_guess = new_current_guess
else:
print ('Sorry that was incorrect')
wrong_guesses += 1
if wrong_guesses == MAX_WRONG:
print ('\nYou have been hanged!')
print ('The correct word is', word)
elif current_guess == word:
print ('\nYou have won!! The word is:', word)
game_play()
Output:
Remaining tries: 3
So far, the secret word is: ----
You have used the following letters: []
Enter your letter guess: i
You have guessed correctly!
Remaining tries: 3
So far, the secret word is: -I-I
You have used the following letters: ['I']
Enter your letter guess: kiwi
You have won!! The word is: KIWI
So i was making a program for hangman and this is it so far,
word = input("Enter a word: ").upper()
blanks = (len(word)*"_")
print(blanks)
chances = 5
while blanks.count("_") > 0:
letter = input("Enter a letter: ").upper()
if len(letter) > 1:
print("Please enter one letter only")
if letter in list(word):
blanks = blanks[:word.index(letter)] + letter + blanks[word.index(letter)+1:]
print(blanks)
continue
else:
chances -= 1
if chances > 0:
print("That letter isn't in the word, you have", chances, "chance(s) left")
if chances == 0:
print("You lost. The word was", word.lower())
exit()
print("You win! The word was", word.lower())
I was just trying the code out so I would give the word to guess myself, but if I ever gave a word with a letter repeated , like "doggo".
If i gave the letter as "o", it would give out "_ O _ _ _ " instead of " _ O _ _ O" even if i guess "o" again.
Is there anyway I can fix this?
This worked for me:
word = input("Enter a word: ").upper()
blanks = (len(word) * "_")
print(blanks)
chances = 5
while blanks.count("_") > 0:
letter = input("Enter a letter: ").upper()
if len(letter) > 1:
print("Please enter one letter only")
if letter in list(word):
for count, character in enumerate(word):
if letter == character:
blanks = blanks[:count] + letter + blanks[count + 1:]
print(blanks)
else:
chances -= 1
if chances > 0:
print("That letter isn't in the word, you have",
chances, "chance(s) left")
if chances == 0:
print("You lost. The word was", word.lower())
exit()
print("You win! The word was", word.lower())
The difference is that instead of making one replacement we iterate over the word to find all the coincidences and make all the necessary replacements of the same letter.
One solution is to use zip and join in a list compression. zip combines two strings pairwise. The list comprehension steps through the pairs of letters from blanks and word and compares them to the letter. join combines the result - a list of letters - back into a string.
word = "hello"
letter = 'o'
blanks = ''.join([(l if l == letter else b) for b, l in zip(blanks, word)])
#'__ll_'
You can use bytearray and memoryview or list:
# bytearray and memoryview
blank = '_' * 5
print(blank)
fill = 'abcde'
ctr = 0
ba = bytearray(blank, 'utf-8')
mv = memoryview(ba)
while ba.count(b'_') > 0:
mv[ctr] = ord(fill[ctr])
ctr += 1
blank = ba.decode()
print(blank)
Output:
_____
abcde
Second approach, list:
blank = '_____'
print(blank)
blank_list = list(blank)
fill = 'abcde'
while blank_list.count('_') > 0:
blank_list[ctr] = fill[ctr]
ctr += 1
blank = ''.join(blank_list)
print(blank)
Output:
_____
abcde
I'm still a noob when it comes to coding and I'm trying to create my own hangman game. I ran into some difficulties when it comes to guessing characters of a word which occur more than once in a word.
Here's a snippet of my code:
def random_word():
#word generator
randomized = random.randint(0,(len(content_words)-1))
word_to_guess = content_words[randomized].lower()
splitted = []
word_progress = []
for character in word_to_guess:
splitted.append(character.lower())
word_progress.append("?")
counter = 0
while counter <= 5:
print(word_to_guess)
print(splitted)
print(word_progress)
#Start of the game
options = str(input("Do you want to guess the word or the characters?: ").lower())
#word
if options == "word":
guess_word = input("Please your guess of the word: ").lower()
if guess_word == word_to_guess:
print("Correct! The word was " + word_to_guess + " you only needed " + str(counter) + " tries!")
break
elif guess_word != word_to_guess:
counter += 3
print("You have entered the wrong word ! You now have " + str(5-counter) + " tries left!")
continue
#characters
elif options == "characters":
guess_character = input("Please enter the character you would like to enter!: ")
if guess_character in splitted and len(guess_character) == 1:
print("Correct! The character " + guess_character.upper() + " is in the word were looking for!" )
for char in word_to_guess:
if char == guess_character:
word_progress[word_to_guess.index(char)] = word_to_guess[word_to_guess.index(char)]
continue
....so basically in the character section only the first occurrence of the guessed character gets implemented into the word_to_guess list. What is the best way to handle this problem?
By the way this is the first question I've ever asked regarding to coding and on this platform, please excuse me if I didn't really formulate my problem in the most efficient way.
index will only return the index of the first occurence of your character.
You should use enumerate to iterate on the characters and indices at the same time:
for index, char in enumerate(word_to_guess):
if char == guess_character:
word_progress[index] = guess_character
I'm making a hangman game and I need to update the table showing the correct letters. So far the program prints this
Enter a word: hello
[-----] You have 6 guesses left, enter a letter: h
Correct!
[H----] You have 6 guesses left, enter a letter: e
Correct!
[-E---] You have 6 guesses left, enter a letter: l
Correct!
[--LL-] You have 6 guesses left, enter a letter: o
Correct!
[----O] You have 6 guesses left, enter a letter:
What I need the program to do is combine the strings for example [H----] --> [HE---] and so on. How would I do this? As well as end the game when there are no more dashes left.
An example of what I want the program to look like is
[H----]
[HE---]
the program also has to work in a random order for example...
[----O]
[-E--O]
[HE--O]
[HELLO]
This is my code so far
Just loop through the string to be guessed and show either the letter, if that letter was already guessed or '_' in case it hasn't.
In [127]: s = "Apple"
In [128]: already_guessed = ['p', 'e']
In [129]: '[' + ''.join([letter if letter in already_guessed else '_' for letter in s]) + ']'
Out[129]: '[_pp_e]'
Instead of recomputing display_string with "-", use the previous value of display_string. Note: You need to offset the index of display_string because of your brackets.
display_string = "[" + "".join([x if x == letter else display_string[i + 1] for i, x in enumerate(word)]) + "]"
Here's my attempt at an answer, wrote this up before you put up your code, so it may not be what you're looking for, but it works.
def hangman():
answer = raw_input('Enter a word: ') # getting the word
guesses = 6 # number of starting guesses
word = '[' + '-'*len(answer) + ']' # this is the string of interest to be printed
while True:
print word, 'You have %d guesses left' % guesses,
if guesses == 0 or '-' not in word: break
# game finishes if word is guessed, or guesses run out
letter = raw_input(', enter a letter: ') # guess a letter
guesses -= 1 # decrease number of guesses by 1 each time
for index, char in enumerate(answer): # iterate through all letters in answer
if letter == char: # check if guessed letter is in the answer
wordlist = list(word) # representing the word as a list to allow mutation
wordlist[index+1] = letter # mutate the correctly guessed letter
word = ''.join(wordlist) # recombining the list into a string
lets say I have the word: "Pizza"
sAnswer = "Pizza"
sReveal = len(sAnswer)* "_ "
Above I've built a string that'd display "_ _ _ _ _ "
Like any other Hangman game it would contain underscores my problem is: How do I strip the sReveal of spaces, find the index of the letter guessed (example: 'z') and then replace the underscores with z's where necessary and then rebuild the spaces in between, therefore it would become: "_ _ z z _ "
I've tried something like this to no avail:
if sLetterGuessed in list(sAnswer):
for character in list(sAnswer):
index = sAnswer.find(sLetterGuessed)
sReveal = sReveal.replace(" ", "")
list(sReveal)[index] = "z"
print sReveal
for char in sReveal:
sReveal = sReveal.strip(" ")
sReveal = sReveal.replace("_", char)
print sReveal
print HangingMan[iErrors]
## The code is just consideration of the route I'm taking with this; the horrible route.
An easy way to update sReveal is use a list comp and str.join:
sAnswer = "Pizza"
sReveal = len(sAnswer)* "_ "
letter_guessed = "z"
# if letter_guessed == current letter in word, add that letter else add a _
sReveal = " ".join([x if x==letter_guessed else "_" for x in sAnswer ])
print(sReveal)
_ _ z z _
An old hangman game I had to do for a course might be useful:
def hangman(secret_word):
from string import ascii_lowercase
print ("Welcome to Hangman!")
print ("I am thinking of a word that is {} letters long\n-----------".format(len(secret_word)))
guesses = 8
letters_guessed = []
missed_l = ''
correct_l = ''
secret_word = secret_word.lower()
while True:
# if all the letters in secret_word are in correct_l , the user has won
if all(x in correct_l for x in secret_word):
print ("Congratulations, you won!")
break
# if len missed letters is 8, user has used up all guesses so break/end teh game
elif len(missed_l) == 8:
print ("Sorry, you ran out of guesses. The word was {}.".format(secret_word))
break
print ("You have {} guesses left".format(guesses))
print ("Available Letters: {}".format(" ".join([x for x in ascii_lowercase if x not in letters_guessed])))
guess = raw_input("Please guess a letter: ").lower()
# if guess in letters_guessed user has already guessed that letter
if guess in letters_guessed:
print ("Sorry You've already guessed that letter: {}\n-----------".format(guess))
# else if it is in the word, add guess to correct_l and to letters guessed
elif guess in secret_word:
letters_guessed.append(guess)
correct_l += guess
print("Good guess: {}\n-----------".format(" ".join([x if x in letters_guessed else "_" for x in secret_word])))
# if users guess is not in the word, minus a life/guess
elif guess not in secret_word:
letters_guessed.append(guess)
guesses -= 1
print (" That letter is not in my word: {}\n-----------".format(" ".join([x if x in letters_guessed else "_" for x in secret_word])))
missed_l += guess
You're converting sReveal to a list, but you're not saving the list, so it has no effect after all.
Try this:
aReveal = list(sReveal)
index = sAnswer.find(sLetterGuessed)
while index >= 0:
aReveal[index] = sLetterGuessed
index = sAnswer.find(sLetterGuessed, index + 1)
sReveal = ''.join(aReveal)
print sReveal