Hangman game. How to slice strings to change original value - python

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

Related

Is it possible to store inputted values in a while loop?

I'm trying to store the guesses so that I can make code for if you have already guessed that letter and also to make code for when they get all of the letters correct. I may be stuck on that part, too, since I don't know how to check if the letters correspond to the letters in the wordname list, especially when it isn't even ordered.
So, I am looking for some code that would store the guesses and also something that can check if all of the correct letters have been guessed. I am thinking it may have something to do with the enumerate() function, but I am not sure since I have never used it before and have only just heard about it.
Also, for your information, the game is hangman if that helps.
wordname = word_choosing()
wordnamelength = len(wordname)
wordnamelist = list(wordname)
def letter_guess1():
sleep(1)
tries = 5
print(f"{oppositeplayer}, the word is {wordnamelength} letters long")
while tries > 0:
guess1 = input("Make your guess: ")
if guess1 in wordnamelist:
print("Congrats, that is correct")
letternum = wordnamelist.index(guess1)
letternum += 1
print(f"This letter is number {letternum}")
elif guess1 not in wordnamelist:
tries -= 1
print(f"You have {tries} left")
if guess1 == "quit".lower():
exit()
return tries
tries = letter_guess1()
I think set is very suitable in this situation. Keep the letters of the word being guessed as a set and add the guess to another set. Then, you can check if the word was guessed correctly by using the intersection of both sets.
Something like that:
wordname = word_choosing()
wordnamelength = len(wordname)
wordnamelist = list(wordname)
def letter_guess1():
sleep(1)
tries = 5
print(f"{oppositeplayer}, the word is {wordnamelength} letters long")
word_set = set(wordname)
guessed_letters = set()
while tries > 0:
guess = input("Make your guess: ")
if guess in guessed_letters:
print("You already guessed this letter")
continue
guessed_letters.add(guess)
if guess in word_set:
print("Congrats, that is correct")
letternum = wordnamelist.index(guess)
letternum += 1
print(f"This letter is number {letternum}")
elif guess not in word_set:
tries -= 1
print(f"You have {tries} left")
if word_set.intersection(guessed_letters) == word_set:
print("You have won!")
if guess == "quit".lower():
exit()
return tries
tries = letter_guess1()

why does the index of "list_of_letters" not update for every while loop with "guessed_letter_string"? The problem occurs in the Try: section

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 am trying to make a guess the word game but I get a logical error when it picks a random word that has two or more of the same letter

I have made a word guessing game but when it picks a random word with repeating letters in it, it works fine and puts the correctly guessed letters into a list. But how do I make it so it acknowledge that the random word has repeating letters so accepts repeating letters? For example, if the chosen word is ball and you entered s it would display that s is not in the word. If I entered l, it would say l is in the word and add it to a list called correct. If I then entered l again as ball has two l's, it will display that I have already entered that letter and will not let me continue any further. I don't know how I can make it acknowledge that the word has repeating letters. Here is the code:
words = ["burger","chips","ketchup","cake","crisp","coke","fruit"]
correct = []
guessed = []
print("Weclome to guess the word. Aim of the game is to guess all the letters in the word and then type what word you think the word is. The subject is food. You have 15 guesses")
j = random.choice(words)
x = len(j)
count = x
guesses = 15
print("The word is:", x , "letters long.")
while guesses > 0:
guess1 = input("Enter a letter: ").lower()
k = len(guess1)
if k != 1:
print("Not a valid guess!")
if guess1 in j and guess1 in correct:
print("You have already guessed this letter! Your number of guesses left is:", guesses)
if guess1 in j and guess1 not in correct:
print(guess1,"is in the word. You have:", guesses , "guesses left.")
correct.append(guess1)
guesses = guesses-1
count = count-1
print("You have", count ,"of", x , "letters left to guess and you correctly given these letters:", *correct)
if guess1 not in j and guess1 not in guessed:
guessed.append(guess1)
print(guess1, "is not in the word. You have:", guesses , "guesses left and have given the following incorrect letters:", *guessed)
guesses = guesses-1
if guesses == 0:
print("You have ran out of guesses!")
break
if count == 0:
print("Well done! You have guessed all the letters. Now time to de-scramble them! You have unlimited guesses for the word.")
print("These are the following letters you need to de-scramble")
print(*correct)
descramble = input("Enter what you think the word is: ").lower()
if descramble == j:
print("You guessed the word! Well done!")
break
if descramble != j:
print(descramble,"is not the word.")```
You can try this,
import random
words = ["burger","chips","ketchup","cake","crisp","coke","fruit"]
correct = []
guessed = []
print("Weclome to guess the word. Aim of the game is to guess all the letters in the word and then type what word you think the word is. The subject is food. You have 15 guesses")
j = random.choice(words)
x = len(j)
count = x
guesses = 15
already_used_letters = list()
print("The word is:", x , "letters long.")
while guesses > 0:
guess1 = input("Enter a letter: ").lower()
k = len(guess1)
if guess1 in already_used_letters:
print("You already used this letter")
guesses = guesses - 1
already_used_letters.append(guess1)
if k != 1:
print("Not a valid guess!")
if guess1 in j and guess1 in correct:
print("You have already guessed this letter! Your number of guesses left is:", guesses)
if guess1 in j and guess1 not in correct:
print(guess1,"is in the word. You have:", guesses , "guesses left.")
correct.append(guess1)
guesses = guesses-1
count = count-1
print("You have", count ,"of", x , "letters left to guess and you correctly given these letters:", *correct)
if guess1 not in j and guess1 not in guessed:
guessed.append(guess1)
print(guess1, "is not in the word. You have:", guesses , "guesses left and have given the following incorrect letters:", *guessed)
guesses = guesses-1
if guesses == 0:
print("You have ran out of guesses!")
break
if count == 0:
print("Well done! You have guessed all the letters. Now time to de-scramble them! You have unlimited guesses for the word.")
print("These are the following letters you need to de-scramble")
print(*correct)
descramble = input("Enter what you think the word is: ").lower()
if descramble == j:
print("You guessed the word! Well done!")
break
if descramble != j:
print(descramble,"is not the word.")
Try this:
import random
words = ["burger", "chips", "ketchup", "cake", "crisp", "coke", "fruit"]
correctLetters = []
wronglyGuessed = []
print(
"Weclome to guess the word. Aim of the game is to guess all the letters in the word and then type what word you think the word is. The subject is food. You have 15 guesses")
word = random.choice(words)
# word = "aapplle"
lives = 15
while lives > 0:
if len(word) == len(correctLetters):
print(
"Well done! You have guessed all the letters. Now time to de-scramble them! You have unlimited guesses for the word.")
print("These are the following letters you need to de-scramble")
print(*correctLetters)
descramble = input("Enter what you think the word is: ").lower()
if descramble == word:
print("You guessed the word! Well done!")
break
else:
print(descramble, "is not the word.")
guess1 = input("Enter a letter: ").lower()
if len(guess1) > 1 or not guess1.isalpha():
print("Not a valid guess!")
lives -= 1
continue
if guess1 in word:
if word.count(guess1) > correctLetters.count(guess1):
correctLetters.append(guess1)
print("you found a letter")
else:
lives -= 1
print('You guessed all the occurances')
continue
if guess1 not in word:
lives -= 1
print(f'Wrong guess. You have {lives} tries left')
continue
if lives == 0:
print("You ran out of guesses")
Your problem comes from here:
if guess1 in j and guess1 in correct:
print("You have already guessed this letter! Your number of guesses left is:", guesses)
When you use in it will only find the first occurrence of said item and return true. In this case you are interested in also finding the case for duplicates and also keeping track of them. Thus, you need to take another approach: that of finding said duplicates and their number. I used a pre-built method count().
I'd say there are a few more issues with your code:
Use descriptive names for your variables. x, j, k, n can mean a lot of things whereas guestNames is pretty self explanatory
When a case inside one of your ifs was met and all following tests cannot evaluate true, just use a continue statement
Also, on a different note, i'd say that when a letter is guessed you assume all its occurances, but that's not programming related.

Python - Guess a word game

Here is my code:
import random
guesses = 0 #Number of tries to guess.
print ("Welcome to Guess Me!")
print ("\nYou have five guesses, choose letter and guess a word.")
print("\nAll of luck!")
def rand_word():
f = open('sowpods.txt', 'r').readlines() #Sowpods is library with some random words
return random.choice(f).strip()
word = rand_word()
print word #I printed a word just so i can test if is working.
correct = word
lenght = len(word) #I want to tell them how many letters a word contain
new_length = str(lenght)
guess = raw_input("The word is " + new_length + " letters long. Guess a letter: ")
while guesses < 5:
if guess not in word:
print("Sorry, this letter is not in word.")
else:
print("Correct, word contain this letter!")
guesses =+ 1
if guesses > 5:
final_answer = raw_input("You ran out of guesses, what is your answer?")
if final_answer == correct:
print("That's correct, congratulations you won!")
else:
print("Sorry, correct word is" + " " + word + " ,you can try again!")
Problem is when i run my code, and let's say i type letter "s", my sublime freeze and i get message "Sublime 3 is not responding.." and i have to turn it off. Maybe it's while loop? Infinite?
There are a few things.
guesses =+ 1 should be guesses += 1 and at the top of the while loop before any if statements
I think your guess = raw_input should be within the while loop before any of the if statements. So it will keep asking and counting for each guess until it reaches 5. The last if statement within the loop should be if guesses == 5 or guesses >= 5 instead of guesses > 5.
Mostly just reordering things all within the while loop. Everything under the code within the while loop will be ran for every guess.
I changed it according to the above and it works great for me:
while guesses < 5:
guesses += 1
guess = raw_input("The word is " + new_length + " letters long. Guess a letter: ")
if guess not in word:
print("Sorry, this letter is not in word.")
else:
print("Correct, word contain this letter!")
if guesses == 5:
final_answer = raw_input("You ran out of guesses, what is your answer?")
if final_answer == correct:
print("That's correct, congratulations you won!")
else:
print("Sorry, correct word is" + " " + word + " ,you can try again!")
Welcome to Guess Me!
You have five guesses, choose letter and guess a word.
All of luck!
word
The word is 4 letters long. Guess a letter: 1
Sorry, this letter is not in word.
The word is 4 letters long. Guess a letter: 2
Sorry, this letter is not in word.
The word is 4 letters long. Guess a letter: 3
Sorry, this letter is not in word.
The word is 4 letters long. Guess a letter: 4
Sorry, this letter is not in word.
The word is 4 letters long. Guess a letter: 5
Sorry, this letter is not in word.
You ran out of guesses, what is your answer?numbers
Sorry, correct word is word ,you can try again!
You have an infinite loop because your 'guesses' variable is not being inceremented in the while loop; move the 'guesses += 1' into the loop itself e.g.
while guesses < 5:
if guess not in word:
print("Sorry, this letter is not in word.")
else:
print("Correct, word contain this letter!")
guesses += 1

python letter guessing game

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

Categories

Resources