One iteration is being wasted, and not getting proper output. (Python) - python

I am beginner in python and trying to make a simple game in which the user has to guess the word/name by inputting characters of that word/name. The program will generate stars of the word length which the user has to guess.
When the user will input a character, the position of that character in stars will be changed to that character. For example, The word is my name "Vishwas", the program will generate 7 stars as the length of my name is 7, *******, when user will input i the output will be Correct *i***** like this.
Now the problem is my name has two 's' in it, the program is okay till 2 's' but when we input third 's' as input it just wastes that iteration, I want here output as "Incorrect" which I just don't know how to fix here otherwise all the code is okay.
Also, tell what function to use to let the program wait till the user inputs a character as C++ has getch function right now I have used time function.
import time
print("\t\t\t\t\t\t\tWelcome to name guessing game")
name = "shahzaib"
LengthOfWord = len(name)
stars = []
for x in range(LengthOfWord):
stars.append("*")
stars = ''.join(stars)
print(stars)
print("Enter a character")
chance = 2
y=0
LOW=LengthOfWord
while y < LOW:
if chance<0:
print("Game Over")
break
chr = input()
chr = chr.lower()
count = 0
for x in range(LengthOfWord):
if chr[0] == name[x]:
if stars[x] == name[x]:
continue
else:
stars = list(stars)
stars[x] = chr[0]
stars = ''.join(stars)
print("Correct\n",stars)
if stars == name:
print("Congratulations you won")
break
count+=1
if count == LengthOfWord:
print("Incorrect\n",chance,"Chance(s) left\n",stars)
chance -= 1
LOW=LOW+1
y+=1
time.sleep(3)
The program is pretty simple I think it should be easily understandable.

Your logic is too much complex, you don't have to use any time class to wait for user to input, in python we use input() simple. It will wait till infinity for user to input something.
This can be done simply like this:
name = 'shahzaib'
chances = 3
stars = ['*' for _ in name] # I kept it as a list so that we can replace * with char
print("\t\tWelcome to name guessing game")
# while there are chances and user hasn't guessed the whole name
while chances > 0 and '*' in stars:
user = input("\nEnter Character: ").lower()
# If correct
if user in name:
index = name.find(user) # find the first occurence of that char in name
name = name.replace(user, '.', 1) # now replace that char with some special character like '.'
stars[index] = user # replace the value in the stars list so that we can show it to the user
print("Correct\nName: " + ''.join(stars))
else:
chances -=1
print("Incorrect, {} chances left.".format(chances))
Your problem is when you have more than 1 occurrence of the same character in name. This problem arose because of your logic.
The solution as you can see is to replace the occurrence of the character with some special letter like . , :, ; etc, that will not be used in a name. This will also make the program more elegant as you will be guessing the character from left to right.
Ask me anything if you feel confused about the code.

Related

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.

Coding Hangman in Python

I'm having trouble with this hangman coding. When I run the code, it asks the question "Type in a letter a - z", but when I type in a letter, instead of it putting a letter, it just ask the same question from the beginning without letting me know if the letter is correct or not.
import random
possibleAnswers = ["page","computer","cookie","phishing","motherboard","freeware","bus","unix","document","hypertext","node","digital","worm","macro","binary","podcast","paste","virus","toolbar","browser"]
random.shuffle(possibleAnswers)
answers = list(possibleAnswers[1])
display = []
display.extend(answers)
for i in range(len(display)):
display[i] = "_"
print ' '.join(display)
print "\n\n\n\n"
count = 0
while count < len(answers):
guess = raw_input("Type in a letter a - z: ")
guess = guess.upper()
for i in range(len(answers)):
if answers[i] == guess:
display[i] = guess
count += 1
print ' '.join(display)
print "\n\n\n"
It does tell you, after a fashion. The problem is that your entire word list is lower-case, but you specifically change all of your input guesses to upper-case. Those cannot match, so there's never a "correct" guess. Change the word list to capitals, or change your conversion from upper to lower.

Python 3.2 Hangman String edit

This is my code for a school hangman project. I currently have some trouble with editing my correctguess string.
I have been told that strings in Python are immutable, but with that fact I now don't know how to add the correctly guessed letter to my guesses. I was originally thinking of using the find method, but now I feel like that won't work. If possible, I'd like a solution or a recommendation for creating a string that is editable, or a loop to create new strings. I'd like it so that every time I get a correct guess, (let's say A) my "HANGMAN" (which is my code word) would change from "XXXXXXX" to "XAXXXAX".
(Sorry that this is hard to explain, the code should be easier to understand, as I added a lot of comments as to what I want to do. I also commented out some code that gave me errors.)
Thanks in advance
import sys
message1=("hangman")
l=len(message1)
t = 10
c = 0
tries = str(t)
correct = str(0)
wrongguess=" "
print("Hello, you have 10 tries to achieve the answer.")
for i in range(0,l):
sys.stdout.write('x')
i=i+1
print("")
for x in range(0,l):
message2=input()
message3= message2.lower()
finder = message1.find(message3)
if(int(finder)==-1):
print("You Fail")
if(int(finder)!=-1):
correctguess[int(finder)]=message2
print(correctguess)
## find message 3 within message 1
## "Find" the input message within the original hangman word; Find the position
## of the "Found" letter within the original message, and replace the "correctguess"
## string's position of the Found letter; The found letter. If not, tries will -1,
## if tries = 0, terminate program
## Create an input loop that will save under a new string. If the input does not equal
## to anything within the original word, add the letter to the "wrongguess" string
##for x in range(0, l-1):
## message2=input()
## message3= message2.lower()
## if message3==message1[x]:
## correctguess[x]= message3
## print(correctguess)
## if message3!=message1[x]:
## t=t-1
## if t==0:
## print("You lose")
##
##if message1==message3:
## print("Correct! You had " + tries + " tries left, and had " + correct + " correct")
##
I just wrote up a hangman game right now to test, and what worked for me was this:
word was the word that the user had to guess.
I had a mask, which is a list with the same length as word. mask consists of only 1s and 0s. If an index of mask is 1, then show the user has guessed that letter. If it's 0, the user hasn't guessed it.
Example usage:
word = 'hangman'
mask = [0]*len(word)
# How to print the obfuscated word
# Print X if the user hasn't guessed the letter, otherwise print the letter.
print(''.join('X' if mask[i] == 0 else word[i] for i in range(len(mask))))
# How to get the guess
guess = input().strip().lower()[0]
# How to mark the guessed letter in the word
if guess in word:
mask = [1 if mask[i] == 1 or word[i] == guess else 0 for i in range(len(mask))]
Also, I see you iterate through the game with range(0,l) where l = len(word). Instead you should use a while loop, like so:
guessed = False
tries = 10
while (not guessed) and (tries > 0):
# Play game
That way, the game will end if the user guesses correctly, or if the user runs out of tries. After the game, whether the user won or not can be gotten simply by checking the value of guessed
Pseudocode:
Set the word
init the mask to the length of the word
set tries to the number of guesses the playe rhas
set guessed to False
while not guessed and tries > 0:
get guess from input
if guess in word:
update mask to mark the guessed letters
if the mask is full of 1s, (if the sum of mask is equal to the length):
guessed = True
else:
tries -= 1
if guessed:
The user has correctly guessed the word
else:
The user has failed.
if you want to edit a string, you could use a list in conjunction with the string.join method instead. The join method takes a list as an argument and returns a string which is separated by the original string. If you make it an empty string, you'll get the string you need.
my_word = ["H", "E", "L", "L", "O"]
''.join(my_word)
# 'HELLO'
my_word[1] = "H"
''.join(my_word)
# 'HHLLO'

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