PEP-8
First off, as mentioned by GregOliveira in the comments, by PEP-8 you don't need the entire program indented (and indeed, it won't run as written). You do, however, need spaces before/after operators, after commas, etc. Getting a linter such as pylint or flake8 will highlight these and make writing good code easier.
Also, your variable names are not terribly clear get_word
(sounds more like a verb) might be target_word
for example.
Handling input
Because we're taking input from the user, we want to make sure we're handling it appropriately. Currently you are testing the bare input and merely checking whether it is 1 character. We need to consider carefully about what we consider valid input and not, for example, punish the player for entering an upper-case letter, entering the same guess multiple times, entering a character which isn't a letter at all.
Instead of:
guess = input("Enter a letter: ")
if len(guess) == 1:
We could do:
from string import ascii_lowercase # Or we could define our own set of valid characters
[...]
while True:
guess = input("Enter a letter:")
guess = guess.lower() # Handle capital letters by downcasing all of them
if len(guess) != 1:
print(f"Invalid guess '{guess}', must be a single character")
elif guess not in ascii_lowercase:
print(f"Invalid guess '{guess}', must be one of {', '.join(ascii_lowercase)}")
elif guess in missed or guess in result:
print(f"Invalid guess '{guess}', already guessed.")
else:
break
N.B. This is also a good opportunity to use a function.
Python Functions
The Python module random
contains the random.choice
function (try running the help(random)
function in the Python shell to see what functions things have). This function selects one element from a sequence (i.e. your list), so:
get_word = random.randint(0, len(word_list)-1)
get_word = word_list[get_word]
Becomes
get_word = random.choice(word_list)
You also have what appears to be some remnants of old code floating around. E.g.
x = "_" * len(get_word)
print(x)
Where later, you use the more Pythonic:
print("".join(result),"\nMissed letters are: ", missed , "\t")
^
"".join(result)
The input
function takes a prompt
argument:
input(prompt=None, /)
Read a string from standard input. The trailing newline is stripped.
The prompt string, if given, is printed to standard output without a
trailing newline before reading input.
If the user hits EOF (*nix: Ctrl-D, Windows: Ctrl-Z+Return), raise EOFError.
On *nix systems, readline is used if available.
Instead of:
print("Enter a letter: ")
guess = input()
We can simply use
guess = input("Enter a letter: ")
Functionality
In this part:
for index,value in enumerate(get_word):
if guess == value:
result[index] = value
print("You guessed right")
else:
You align the else
with the for
which is probably not what you intend. else
on the for
is executed if the for
loop exits naturally rather than through a break
statement. Which in your case it always does. What you probably intend is:
if guess in get_word:
print("You guessed right") # This also allows us to avoid printing this multiple times for each time the character appears in the word
for index,value in enumerate(get_word):
if guess == value:
result[index] = value
else:
attempts -= 1
missed.append(guess)
print("Sorry the letter ", guess , "is not in the word." ,"Now you have" , attempts , "attempts")
if attempts == 0:
print("You didn't guess the word.The word was" , get_word)
However, we can use this to test whether we have used up all our attempts (since we break on success):
while attempts > 0:
[...]
<if correct>:
break
else:
print("You didn't guess the word. The word was" , get_word)
Cleaning up
We also don't really need to check whether _
is in our result before testing its validity, we can just straight up test whether we have the right answer.
We can also use f-strings to clean up some of the print
statements.
print("Sorry the letter ", guess, "is not in the word.", "Now you have", attempts, "attempts")
Becomes:
print(f"Sorry the letter {guess} is not in the word. You have {attempts} attempts remaining.")
Putting it all together
If we put all these things together, we end up with something that looks like:
"""
Play a simple hangman game
"""
import sys
import random
from string import ascii_lowercase
WORD_LIST = ['sleep', 'window']
def get_user_guess() -> str:
while True:
guess = input("Enter a letter:").lower()
if len(guess) != 1:
print(f"Invalid guess '{guess}', must be a single character")
elif guess not in ascii_lowercase:
print(f"Invalid guess '{guess}', must be one of {', '.join(ascii_lowercase)}")
elif guess in missed or guess in result:
print(f"Invalid guess '{guess}', already guessed.")
elif not guess: # Handle user giving up
to_quit = input("Giving up? [y/N]")
if to_quit.lower() == "y":
sys.exit()
else:
break
return guess
target_word = random.choice(WORD_LIST)
result = ["_"] * len(target_word)
print("".join(result))
attempts = 5
guessed = []
missed = []
while attempts > 0:
guess = get_user_guess()
if guess in target_word:
print("You guessed right")
for index, value in enumerate(target_word):
if guess == value:
result[index] = value
else:
attempts -= 1
missed.append(guess)
print(f"Sorry the letter {guess} is not in the word."
f"You have {attempts} attempts remaining.")
print("".join(result))
if "".join(result) == target_word:
print("Congratulations! You guessed all the letters")
break
print(f"Missed letters are: {', '.join(missed)}.")
else:
print(f"You didn't guess the word. The word was {target_word}.")