In this tutorial, we will create the hangman game in Python. We will follow a step-by-step process and gradually build it.
To code the hangman game in Python you have to use the input() function to ask the user to guess a letter. Then you keep track of the maximum number of attempts allowed and if that’s reached before guessing the full word the user loses. To print the hangman stages you can use multi-line strings.
We will start by writing the code to guess a single letter…
Once this is done we will repeat this code over and over using a Python while loop.
Pick a Random Word for the Hangman in Python
Let’s start working on our hangman game by creating a Python function that returns a random word for our user to guess.
Import the random module and define a list of strings that contains 5 words.
import random
words = ["tiger", "tree", "underground", "giraffe", "chair"]
Then add a function called select_word()
that randomly selects one word from the list using the function random.choice()
.
The random.choice() function returns a random element from a sequence.
def select_word(words):
return random.choice(words)
Call the function and test the Python program several times to make sure you get back random words.
print(select_word(words))
Here is the output:
$ python hangman.py
tree
$ python hangman.py
underground
$ python hangman.py
chair
The function works fine.
Which Variables Do We Need for the Hangman Game?
For our hangman game we will need the following variables:
- remaining_attempts: this is an integer and represents the number of remaining attempts to guess the “secret” word. This value will be initially set to 6 (head + body + arms + legs).
- guessed_letters: a string that contains all the letters guessed by the user that are in the “secret” word.
Here is how we set these two variables:
remaining_attempts = 6
guessed_letters = ""
Somehow we also have to print the different stages of the hangman depending on how many mistakes the user makes.
In other words, the stage of the hangman we will print will depend on the value of the remaining_attempts variable.
Let me explain…
We will create a list of strings in which every element represents a stage of the hangman. For a string to “draw” the hangman, we will use multiline strings (delimited by triple quotes).
Create a separate file called hangman_stages.py where we can define a function that returns one of the multi-line strings in the list depending on the value of the variable remaining_attempts.
This is the content of the hangman_stages.py file:
def get_hangman_stage(remaining_attempts):
max_attempts = 6
stages = ["""
------
| |
|
|
|
|
|
------------
""", """
------
| |
| O
|
|
|
|
------------
""", """
------
| |
| O
| |
| |
|
|
------------
""", """
------
| |
| O
| |
| |
| /
|
------------
""", """
------
| |
| O
| |
| |
| / \\
|
------------
""", """
------
| |
| O
| --|
| |
| / \\
|
------------
""", """
------
| |
| O
| --|--
| |
| / \\
|
------------
"""]
return stages[max_attempts - remaining_attempts]
In the next sections, we will import this Python function to display the hangman.
How Do You Write the Code to See the Word to Guess?
Now it’s time to write the code to ask our user to guess a letter.
First of all, you have to print a sequence of underscores where the number of underscores is the number of letters in the word to guess.
Here is what I mean…
def print_secret_word(secret_word):
print(" _ " * len(secret_word))
print("Welcome to the Hangman Game! Let's see if you can guess this word!\n")
secret_word = select_word(words)
print_secret_word(secret_word)
Firstly we have defined a function called print_secret_word() that prints a sequence of underscores separated by spaces where the number of underscores is equal to the number of letters in the secret word.
Then we passed the secret_word variable to the print_secret_word() function after obtaining the secret_word from the select_word() function we have defined previously.
Notice that instead of writing our code one line after another we are already splitting it in functions.
This makes it a lot more readable!
As an exercise, at the end of this tutorial try to remove functions and see how bad the readability of the code becomes.
Below you can see the output of the previous code:
$ python hangman.py
Welcome to Hangman! Let's see if you can guess this word!
_ _ _ _ _
Nice! We are getting somewhere!
And what if we also want to print the initial hangman stage?
We have to import hangman_stages and call the function get_hangman_stage() from the hangman_stages.py file.
Update the import statement at the top of hangman.py:
import random, hangman_stages
And call hangman_stages.get_hangman_stage():
print("Welcome to Hangman! Let's see if you can guess this word!\n")
secret_word = select_word(words)
print(hangman_stages.get_hangman_stage(remaining_attempts))
print_secret_word(secret_word)
[output]
$ python hangman.py
Welcome to Hangman! Let's see if you can guess this word!
------
| |
|
|
|
|
|
------------
_ _ _ _
That’s cool!
How Do You Ask the User to Guess a Letter of the Secret Word?
The next step of our program is to ask the user to guess a letter.
In the logic of the program, we will make sure the user can only provide a single letter (no multiple letters, no numbers or other characters).
Let’s create a function called guess_letter() that does the following:
- Ask the user to guess a letter using the Python input function.
- Verify that the input is a single letter using an if statement. If that’s not the case stop the execution of the program.
- Convert the letter to lowercase before returning it to the function caller. We will work only with lowercase letters to make any comparisons in the program easier.
Here is the guess_letter() function:
def guess_letter():
guess = input("Guess a letter: ")
if len(guess) > 1 or not guess.isalpha():
print("Only single letters are allowed. Unable to continue...")
sys.exit()
return guess.lower()
Note: remember to import the sys module.
To verify that the user has provided a single character we use the len() function.
And we use the string isalpha() method to make sure the string returned by the input function is alphabetic.
As part of this tutorial, I also want to show you the thought process to go through when you write your code.
This is why I’m saying this…
While writing this code I decided to convert this function into a function that takes two arguments:
- letter guessed by the user
- secret word
This function will tell if a letter guessed by the user is part of the secret word.
Let’s make two changes to our code:
- take out the line that calls the input() function to get the guess from the user.
- rename the function from guess_letter() to is_guess_in_secret_word(). This function will return a boolean.
Here is how the function becomes:
def is_guess_in_secret_word(guess, secret_word):
if len(guess) > 1 or not guess.isalpha():
print("Only single letters are allowed. Unable to continue...")
sys.exit()
else:
if guess in secret_word:
return True
else:
return False
And how we can call this function in our main code:
print("Welcome to Hangman! Let's see if you can guess this word!\n")
secret_word = select_word(words)
guess = input("Guess a letter: ")
guess_in_secret_word = is_guess_in_secret_word(guess, secret_word)
At this point we can use the boolean variable guess_in_secret_word to update the hangman output we show to our user.
Update the User about the Hangman State Depending on a Correct or Incorrect Guess
It’s time to add the logic to handle a correct or incorrect guess from the user.
If the guess is correct we add the guessed letter (guess variable) to the guessed_letters variable (a string).
Alternatively, if the guess is incorrect we decrease the value of the remaining_attempts variable. Remember that this variable is then used to print the correct hangman stage.
In both cases we use the print() function to print a success or failure message for our user.
Add the following code after the code shown above, at the end of the previous section:
if guess_in_secret_word:
if guess in guessed_letters:
print("You have already guessed the letter {}".format(guess))
else:
print("Yes! The letter {} is part of the secret word".format(guess))
guessed_letters += guess
else:
print("No! The letter {} is not part of the secret word".format(guess))
remaining_attempts -= 1
print(hangman_stages.get_hangman_stage(remaining_attempts))
print_secret_word(secret_word)
As you can see…
In both print statements we have added we are using the string format method.
Let’s execute the code and see what happens in both scenarios, if a letter we guess doesn’t belong to the secret word or if it does.
Guessed letter doesn’t belong to the secret word
$ python hangman.py
Welcome to Hangman! Let's see if you can guess this word!
Guess a letter: t
No! The letter t is not part of the secret word
------
| |
| O
|
|
|
|
------------
_ _ _ _ _ _ _ _ _ _ _
The hangman drawing gets updated successfully.
Guessed letter belongs to the secret word
$ python hangman.py
Welcome to Hangman! Let's see if you can guess this word!
Guess a letter: a
Yes! The letter a is part of the secret word
------
| |
|
|
|
|
|
------------
_ _ _ _ _ _ _
The hangman drawing is correct but…
The guessed letter doesn’t get added to the string with underscores shown to the user.
And that’s because we haven’t updated the following function:
def print_secret_word(secret_word):
print(" _ " * len(secret_word))
Let’s do it now…
Showing the Letters of the Word that Have been Guessed by the User
To show our users the letters that have been guessed correctly we have to update the print_secret_word() function.
Let’s also pass the variable guessed_letters to it and replace any underscores with the letters that have been guessed by the user.
We will use a for loop that goes through each letter of the secret word:
- If a letter has been guessed we print that letter.
- If a letter has not been guessed we print an underscore.
Sounds simple!
Here is how our function looks like:
def print_secret_word(secret_word, guessed_letters):
for letter in secret_word:
if letter in guessed_letters:
print(" {} ".format(letter), end="")
else:
print(" _ ", end="")
print("\n")
Note: I have passed the end parameter to the print() function to print each character on the same line. In other words, we are telling the print() function not to print the newline character.
Also, remember to update the call to the print_secret_word() function by passing the additional parameter guessed_letters:
print_secret_word(secret_word, guessed_letters)
Let’s test this code by testing a scenario in which the user guesses the correct letter…
$ python hangman.py
Welcome to Hangman! Let's see if you can guess this word!
Guess a letter: a
Yes! The letter a is part of the secret word
------
| |
|
|
|
|
|
------------
_ _ _ a _ _ _
This time it’s working!
Using a While Loop to Keep Asking the User to Guess Letters
Now that we have written the code to ask the user to guess one letter we can repeat this code over and over using a while loop.
Two things can happen at this point:
- The user wins by guessing the word within the maximum number of attempts allowed (initial value of the variable remaining_attempts).
- The user doesn’t guess the word within the maximum number of attempts allowed and loses.
We will express this in the condition of the main while loop that has to be added before we ask the user to guess a letter.
Here is the while loop condition…
while remaining_attempts > 0 and len(guessed_letters) < len(get_unique_letters(secret_word)):
...
...
The condition after the and operator checks that the length of the guessed_letters string is less than the number of unique letters in the word the user is trying to guess.
We are checking if the user has guessed all the letters or not.
Here is how the get_unique_letters() function looks like.
def get_unique_letters(word):
return "".join(set(word))
We convert the secret word into a set first and then we use the string join method to create a string of unique letters.
Let’s see how this works in the Python shell to make sure it’s 100% clear.
>>> secret_word = "underground"
>>> set(secret_word)
{'r', 'e', 'g', 'n', 'd', 'o', 'u'}
>>> "".join(set(secret_word))
'regndou'
Converting the secret_word string into a Python set removes duplicates.
Then the string join method returns a string that only contains unique letters part of the secret word.
The previous code we have written to guess one letter becomes the body of the while loop.
while remaining_attempts > 0 and len(guessed_letters) < len(get_unique_letters(secret_word)):
guess = input("Guess a letter: ")
guess_in_secret_word = is_guess_in_secret_word(guess, secret_word)
if guess_in_secret_word:
if guess in guessed_letters:
print("You have already guessed the letter {}".format(guess))
else:
print("Yes! The letter {} is part of the secret word".format(guess))
guessed_letters += guess
else:
print("No! The letter {} is not part of the secret word".format(guess))
remaining_attempts -= 1
print(hangman_stages.get_hangman_stage(remaining_attempts))
print("\n{} attempts remaining\n".format(remaining_attempts))
print_secret_word(secret_word, guessed_letters)
print("\n\nNumber of letters guessed: {}\n".format(len(guessed_letters)))
Notice that I have added two extra print statements in the last four lines to show the number of attempts remaining and the number of letters guessed.
This code change improves the experience of the user while playing the game.
Testing the Hangman Python Code Created So Far
Our code should be almost complete…
The best way to confirm that is to run the code and start playing Hangman.
Here is the output of a successful game:
Guess a letter: g
Yes! The letter g is part of the secret word
------
| |
| O
| |
| |
|
|
------------
4 attempts remaining
t i g e r
Number of letters guessed: 5
It looks fine except for the fact that we are not printing a message when the user wins a game.
And the same applies to the scenario in which the user loses a game (see below).
Guess a letter: o
No! The letter o is not part of the secret word
------
| |
| O
| --|--
| |
| / \
|
------------
0 attempts remaining
t i _ e r
Number of letters guessed: 4
So, let’s complete our code by adding two print statements to handle a user winning or losing a game.
The print statements will end up being outside of the while loop considering that in both scenarios (user winning or losing) we exit from the while loop.
Let’s add an if statement after the while loop to verify if the user has won or lost and based on that let’s print the correct message.
if len(guessed_letters) == len(get_unique_letters(secret_word)):
print("+++ Well done, you have won this game! +++\n")
else:
print("--- Sorry, you have lost this game! ---\n")
A user has won if the length of the guessed_letters string is the same as the string that contains unique letters in the secret word.
Otherwise, the user has lost because it means not all the letters have been guessed.
Let’s confirm that the print statement works fine in both scenarios.
User wins
Guess a letter: o
Yes! The letter o is part of the secret word
------
| |
| O
| |
| |
|
|
------------
4 attempts remaining
u n d e r g r o u n d
Number of letters guessed: 7
+++ Well done, you have won this game! +++
User loses
Guess a letter: h
No! The letter h is not part of the secret word
------
| |
| O
| --|--
| |
| / \
|
------------
0 attempts remaining
_ _ _ _
Number of letters guessed: 0
--- Sorry, you have lost this game! ---
It’s working!
Go through the video below to recap all the steps we have followed to build this game:
Conclusion
We have completed the creation of the hangman game in Python.
There might be additional checks you could add to make the game more robust but the code we went through should give you a good enough idea of how to create this type of game in Python.
I hope it also helps to be able to see the thought process behind the creation of a program like this one instead of simply seeing the final version of the Python program without knowing how to get there.
If you have any questions feel free to email me at hello@codefather.tech.
Claudio Sabato is an IT expert with over 15 years of professional experience in Python programming, Linux Systems Administration, Bash programming, and IT Systems Design. He is a professional certified by the Linux Professional Institute.
With a Master’s degree in Computer Science, he has a strong foundation in Software Engineering and a passion for robotics with Raspberry Pi.