Python hangman module returns unexpected results - python

I'm a newbie writing hangman and have hit a bug in one of my modules. My intent in this module is to check the user input and verify it is a single character that is a letter and not a number. The error checking works in that it won't exit the module until a single letter ( or special, haven't figured a way around that yet) is entered but the return value is always the first user input entered not the last and correct entry. Any suggestions would be appreciated.
def get_guess():
guess = str(raw_input('Please enter your guess letter: '))
if len(guess) == 1:
try:
float(guess)
is_int = True
except ValueError:
is_int = False
if is_int:
print "You have entered a number not a letter."
get_guess()
else:
print "Please enter a single letter."
get_guess()
return guess

You are using recursion to get repeated inputs, but are not returning the recursive call results. You do need to return whatever the recursive call produced to pass it back up the stack:
return get_guess()
You'll need to do this in both locations you are calling get_guess() recursively.
Using recursion to get a response is not a good idea however; never underestimate the determination of idiots to get it wrong and instead hit your recursion limit. Use a loop instead:
def get_guess():
while True:
guess = raw_input('Please enter your guess letter: ')
if len(guess) == 1:
if guess.isdigit():
print "You have entered a number not a letter."
else:
return guess
else:
print "Please enter a single letter."
Here the function keeps looping endlessly until you return the one valid character guess. Note that you probably want to test for str.isalpha() instead if only letters are permitted. Your code and my version allow for anything that is not a digit, so spaces and punctuation are allowed too.
You may also want to study Asking the user for input until they give a valid response

Related

How to check if a certain char is in a list/tuple in Python?

Beginner here. I am making a simple hangman game that can take up to 6 wrong guesses from the player. As long as they guess right, they can continue playing as many turns as necessary. There is no end behavior, I am just working on getting the input and having the program respond to it properly. My code below:
word_list = ["apple", "hello", "world", "computer"]
def choose_word():
return (random.choice(word_list))
def get_guess():
input("Give me a letter: ")
word = choose_word()
letters_used = list(word)
guess = get_guess()
counter = 0
while counter < 5:
if guess in letters_used:
print("Correct.")
get_guess()
else:
print("wrong")
counter += 1
get_guess()
My train of thought was that by taking the word the computer chose and making it into a list the program could then look at each item in said list and compare it to the input the user gave.
When I run it, it gets input, but it always says wrong, so I am guessing the problem must be in the if statement nested in the while loop.
I have looked at several other hangman games, but I don't see anything similar to what I'm trying to do, or maybe the code is similar but I'm not advanced enough to understand it.
My question is: is there a way to get Python to look at each item inside a list, compare it to a given input, and return a response (be it True/False, etc)?
in is the correct solution, you were just never giving it valid data to check for. You didn't return from get_guess, so it always returns None (thus, guess was always None and None was never in the list). Similarly, you didn't assign to guess on subsequent calls, so even if you had returned a value, guess wouldn't change (it would ask for more guesses, but the input would be discarded and it would always perform the test with the original value). Change the code to (lines with meaningful changes commented):
word_list = ["apple", "hello", "world", "computer"]
def choose_word():
return random.choice(word_list)
def get_guess():
return input("Give me a letter: ") # Must return new guess to caller
word = choose_word()
letters_used = list(word)
guess = get_guess()
counter = 0
while counter < 5:
if guess in letters_used:
print("Correct.")
guess = get_guess() # Must store new guess
else:
print("wrong")
counter += 1
guess = get_guess() # Must store new guess

[Random String Generator]Getting stuck in a loop on else condition

So (as you will probably see from my code) I am a beginner at Python (version 3.8.3) and enjoying it very much so far, and I have challenged myself on several different beginner projects. I am currently making a random string generator (i.e. a password generator, hence the use of the secrets module).
# Password Generator
import secrets, string
print("Welcome to the generator. Please specify your requirements")
print("A. All Characters;\nB. No Numbers;\nC. No Punctuation\nPlease choose the appropriate letter for your needs.")
userInput = input()
def userWelcome():
if userInput.lower() == "a":
generatePass = string.ascii_letters + string.digits + string.punctuation
print("How long do you want your string to be?")
stringRange = int(input())
print( "".join(secrets.choice(generatePass) for _ in range(stringRange)) )
elif userInput.lower() == "b":
generatePass = string.ascii_letters + string.punctuation
print("How long do you want your string to be?")
stringRange = int(input())
print("".join(secrets.choice(generatePass) for _ in range(stringRange)))
elif userInput.lower() == "c":
generatePass = string.ascii_letters + string.digits
print("How long do you want your string to be?")
stringRange = int(input())
print("".join(secrets.choice(generatePass) for _ in range(stringRange)))
else:
print("Not an option! Let's try again.")
userWelcome()
userWelcome()
However, my problem is what to do if the user inputs an incorrect option. As you can see, with the else statement I assume what they filled in does not match any of the earlier options - and so I want to try to rerun the generator again (so I try to call userWelcome again in the else statement).
However, when I type in for example 12 as input, my shell starts to output my string (Not an option Let's try again) literally a thousand times like it is stuck in a loop. I am wondering what I am doing wrong exactly.
What I have tried:
(1) So I have tried to solve this input problem first with try and except, running the except when there is a ValueError but that only works for numbers and I did not manage to rerun userWelcome()
(2) I have tried to create a elif statement in which I check the input for integers, however that also gets stuck in a loop. Code:
elif userInput.isalpha() == False:
print("Not an option! Let's try again.")
userWelcome()
Anyway, I hope that explains it well. I have been busy with this for a few hours now and I thought I'd ask this. Maybe it's a very stupid question but for me it's hard :)
TL;DR: Want to check for proper user input by running my function again, get stuck in weird loop
Thank you for your time and effort!
The code calls userWelcome() recursively, without changing the global variable userInput. The same bad string is processed again, causing the same result, which again calls userWelcome() - for ever (at least until max call depth).
You should read a new string at the beginning of userWelcome, instead of using a global variable. Also, recursion here is an overkill that confuses you. Better use a simple while loop:
while True:
userInput = ....
if ....
do something
return
elif ...
do something else
return # exit the function - breaking out of the loop
else:
print(error message)
# No return here, means the loop will continue to loop
If you want to call the function instead of loop inside, you can instead make the function return success (True) vs. failure (False), and loop that in the caller:
while not userWelcome(inputString):
inputString = read the string
def userWelcome(inputString):
if inputString == ....:
something
return True # To mark OK
elif inputString == .....:
something else
return True # To mark OK
else:
print an error
return False # To mark failure
Just avoid global variables, it is a bad practice. Pass the value through parameters, as in the code above.

Why isn't my program noticing the equivalency between letters?

I am working on making a simple game of Hangman in Python 2. The code I have so far is the ground work I have for it, but it doesn't seem to be working. If I could have a simple wake-up call as to what about what code I made isn't working I would appreciate it.
Code:
secret_word = 'tracy'
secret_word_list = []
for letter in secret_word:
secret_word_list += letter
print secret_word_list
def get_guess(guess = input("Guess: ")):
while len(guess) != 1:
print "Your guess must be exactly one character!"
guess = input("Guess: ")
while guess.isalpha() == False:
print "Your guess must be a lowercase letter!"
guess = input("Guess: ")
while guess.islower == False:
print "Your guess must be a lowercase letter!"
guess = input("Guess: ")
else:
return guess
while True:
if str(get_guess) in secret_word_list:
print "That letter is in the secret word!"
else:
print "That letter is not in the secret word!"
get_guess(guess = input("Guess: "))
Output:
Output of the Code
You've got several problems here, but the big one is that you're not calling functions, so you compare the function itself to the secret.
Code with fixes:
secret_word = 'tracy' # Don't make secret_word_list, there's no point; just use the str itself since you only test len 1 strings against it anyway
print secret_word
def get_guess(guess): # Don't make the default call input, that'll prompt once for an input and store it as the permanent default
while True:
# Test each condition and break loop only if all past; original code would never
# recheck length if new value entered after testing isalpha
if len(guess) != 1:
print "Your guess must be exactly one character!"
elif not guess.islower(): # Add missing call parens on islower; use not, never compare to False; islower implicitly verifies isalpha, so avoid testing isalpha
print "Your guess must be a lowercase letter!"
else:
break # Passed all tests, break loop
# Get new guess if any test failed
guess = raw_input("Guess: ") # Use raw_input on Python 2, never input (which eval's the result of raw_input)
# Removed else (loop always ends by breaking, using else nonsensical but harmless in original code too
return guess
while True:
# Move guess getting to if, because having it in else case never actually checked it
if get_guess(raw_input("Guess: ")) in secret_word:
print "That letter is in the secret word!"
else:
print "That letter is not in the secret word!"
Try it online!
Note: I kept the kinda odd behavior of having get_guess take an argument, but then reprompt for guesses on failure. A saner solution would be to remove the guess argument entirely, and move the guess = raw_input("Guess: ") to the top of the while loop (removing the else block at the end).
get_guess is a function, you need to put () after it to call the function.
You shouldn't put the call to input() as a default argument. The default value is evaluated once, when the function is defined, not every time the function is called. You should assign guess inside the function.
You should test for all the invalid inputs in a single loop.
def get_guess():
while True:
guess = input("Guess:")
if len(guess) != 1:
print "Your guess must be exactly one character!"
continue
if not guess.isalpha() or not guess.islower():
print "Your guess must be a lowercase letter!"
continue
break
return guess
while True:
guess = get_guess()
if guess in secret_word_list:
print "That letter is in the secret word!"
else:
print "That letter is not in the secret word!"

How can I fix the problem of an extra output line after I input my 3rd letter? I can't use while loops or range in the program

When I run the code, the 3rd guess gives me an output of High/Low. On the 3rd try, I don't need it to tell me if I'm high or low. How can I fix the problem with out using "while" loops or "range." We haven't covered these two keywords yet.
python
print("You have 3 tries to guess the letter.")
letter = "F"
tries = 0
# [ ] create letter_guess() function, call the function to test
def letter_guess(tries):
if not tries == 3:
guess = input("Guess a letter: ")
tries = tries + 1
check = check_guess (guess,letter)
if check == True:
print('Winner')
else:
letter_guess(tries)
else:
print ("GAME OVER!")
pass
# def check_guess(guess,letter)
def check_guess (guess, letter):
#if else to see if correct letter
if letter == guess.upper():
print ("correct")
return True
elif letter < guess.upper():
print ("You are wrong, guess lower.")
return False
elif letter > guess.upper():
print ("You are wrong, guess higher.")
return False
else:
print("Invalid response!")
return False
letter_guess(tries)
One way to get result similar to a loop is to use recursion. But if you have not done loops yet, you almost certainly have not done recursion. So just use straightforward code.
The tricky part is that you need to ask for a guess, input the guess, and check for a correct guess three times, once for each guess. However, you need to give feedback on whether the guess is high or low only two times. Therefore, you cannot put those actions in the same function. Just split them into separate functions, and handle each guess in your main routine. No need to count guesses--the position in the main routine makes that clear.
"""Guess-a-letter game."""
def get_guess(letter):
"""Get a guess an note if it is correct. If correct, return None.
Otherwise, return the guess."""
guess = input("Guess a letter: ").upper()
if guess == letter:
print("Correct: You win!")
return None
else:
return guess
def give_feedback(guess, letter):
"""Give feedback on a wrong guess."""
if letter < guess:
print("You are wrong, guess lower.")
else:
print("You are wrong, guess higher.")
def letter_guess():
# Store the letter for the user to guess.
letter = "F"
# Introduce the game.
print("You have 3 tries to guess the letter.")
# Handle the first guess.
guess = get_guess(letter)
if guess is None:
return # Success!
give_feedback(guess, letter)
# Handle the second guess.
guess = get_guess(letter)
if guess is None:
return # Success!
give_feedback(guess, letter)
# Handle the third and last guess.
guess = get_guess(letter)
if guess is None:
return # Success!
print("You were wrong three times. GAME OVER!")
letter_guess()

PYTHON Why is my if statement always returning false

I am new to python and trying to write a program that requires the user to guess a number, 1 - 6 and then they are told if they guessed right or not. However, even when the user guesses right the else statement is still returned.
I apologise for the beginner question, although this really has me stuck because the 'guess' variable is being assigned correctly, I tested this by moving the print("Your guess was: ",guess) outside of the function and executed after the function was called which always returned with the same value that the user inputs.
#Function to take guess
def userGuess (guess):
guess = input("Take a guess.\n")
print("Your guess was: ",guess)
return guess
#Define Variables
diceNum = random.randint(1,6)
guess = 0
#Call Function
guess = userGuess(guess)
#Check answer
if guess == diceNum:
print("You guessed right!, the number was: ",diceNum)
else:
print("You did not guess it right, the number was: ",diceNum)
You need to convert the user input to an integer prior to comparing:
guess = int(input("Take a guess.\n"))
If you want an explanation as to why your if statement returned false for a comparison between an integer and a string, take a look at this question.

Categories

Resources