This tutorial is about creating a Hangman game in Python. The Hangman game is a word-guessing game played between the computer and a human player. The gameplay goes as follows:
- The computer generates a secret word
- There is a limited number of failed attempts that the computer needs to keep track of
- The human player tries to guess a letter in the secret word
- If the guess is wrong, the number of available tries is reduced, and more pieces of the hanged man picture are revealed
- The player continues to try until either the number of available tries is reduced to zero, or the letters in the word are all correctly guessed.
- Once the number of tries is zero, the complete picture of the hangman is displayed, and the human player loses.
The screenshots below show sample gameplay:
How to Make Hangman Game in Python
The hangman game is divided into three modules to simplify the program:
words.py
: Defines the classWordCache
that helps to load the words from a text file, and then allows the game to request a random word.game.py
: Defines theGame
class. TheGame
class controls the actual gameplay.main_module.py
: The driver module controlling the game object. It restarts the game when the player decides to play the game again.
Each of these modules’ functionality is discussed in detail below, along with screenshots of the hangman game code in python.
The Words module of Python Hangman game: words.py
The WordCache
class defined in this module helps to load words from the words.txt
file, store them in memory, and provide words on request.
The __load_file()
method loads the words.txt
file into the __words
list attribute. However:
- If the word contains an open parenthesis, a closing parenthesis, or a hyphen, it is filtered out
- If the number of letters in the word is less than the parameter
min_word_length
, or greater than the parametermax_word_length
, it is also filtered out.
The get_random_word()
method provides words from the store whenever it is requested. The method simply calls the random.choice()
method from the random
module to randomly select words from the __words
attribute.
The source code below shows the contents of the words.py
module.
import random
class WordCache:
# Represents a store of words
def __init__(self, min_word_length, max_word_length):
self.__words = []
# load the words from file
self.__load_file(min_word_length, max_word_length)
def __load_file(self, min_word_length, max_word_length):
WORD_LIST = 'wordlist.txt'
OPEN_PAR = '('
CLOSE_PAR = ')'
HYPHEN = '-'
with open(WORD_LIST, 'r') as f:
for word in f:
# remove all leading and trailing spaces
# from the word
word = word.strip().lower()
# check word that either have parenthesis or hyphens
# or, smaller than min_word_length
if (OPEN_PAR in word) or (CLOSE_PAR in word) or (HYPHEN in word):
continue # Skip words containing parentheses.
elif (len(word) < min_word_length) or (len(word) > max_word_length):
continue # Skip the word because it is too short or too long.
else:
self.__words.append(word)
def get_random_word(self):
# Get a random word from the wordlist
return random.choice(self.__words)
The Game module in python Hangman program: game.py
class Game
defined in this module contains the main functionality of the hangman game. However, it needs to import words.py
so that it can fetch the secret words needed for each gameplay. The complete source code of this module is shown below.
from words import WordCache
import string
class Game:
STAGE0 = [" ___ ",
"| |",
"| O",
"| /|\\",
"| |",
"| / \\",
"| ",
"| "]
STAGE1 = [" ___ ",
"| |",
"| O",
"| /|\\",
"| |",
"| / ",
"| ",
"| "]
STAGE2 = [" ___ ",
"| |",
"| O",
"| /|\\",
"| |",
"| ",
"| ",
"| "]
STAGE3 = [" ___ ",
"| |",
"| O",
"| /| ",
"| |",
"| ",
"| ",
"| "]
STAGE4 = [" ___ ",
"| |",
"| O",
"| | ",
"| |",
"| ",
"| ",
"| "]
STAGE5 = [" ___ ",
"| |",
"| O",
"| ",
"| ",
"| ",
"| ",
"| "]
STAGE6 = [" ___ ",
"| |",
"| ",
"| ",
"| ",
"| ",
"| ",
"| "]
# the display stages of hangman. will be implemented
# as a dictionary
stages = None
def __init__(self):
self.__min_word_length = 5
self.__max_word_length = 6
# the maximum number of attempts, usually 6
self.__max_attempts = 6
# create the word cache to store the words later
self.__cache = WordCache(self.__min_word_length, self.__max_word_length)
# all letters of the alphabet in lowercase
# helps restrict the possible inputs from user
self.__alphabet = set(string.ascii_lowercase)
# initiialize the display stages
Game.stages = {
6: Game.STAGE6, 5: Game.STAGE5, 4: Game.STAGE4,
3: Game.STAGE3, 2: Game.STAGE2, 1: Game.STAGE1,
0: Game.STAGE0
}
def __initial_state(self):
return self.__cache.get_random_word(), self.__max_attempts
def display_hangman(self, lives):
return "\n".join(Game.stages[lives])
def display_status(self, lives, guessed_letters, secret_word):
# display the hangman
print(self.display_hangman(lives))
# inform user of the letters already used
print("You have", lives, "lives left and you have used these letters: ", ' '.join(guessed_letters))
# display guess status, that is, the guessed word along
# with underscores in place of unguessed words in the letter
word_guess_status = [letter if letter in guessed_letters else '_' for letter in secret_word]
print("Current progress: ", ' '.join(word_guess_status))
def play(self):
# main loop of game
secret_word, attempts = self.__initial_state()
# stores letters available in the word
# a way to keep track of letters that have been
# guessed in the current word.
letters_in_word = set(secret_word)
# keep track of what user has guessed
guessed_letters = set()
# display the status
self.display_status(attempts, guessed_letters, secret_word)
# repeat this loop while letters remaining in
# the word's character set is > 0 and lives left > 0
while len(letters_in_word) > 0 and attempts > 0:
# get the user's input
user_guess = input("Guess a letter: ").lower()
# check if it is a valid letter not yet guessed
unused_letters = self.__alphabet - guessed_letters
if user_guess in unused_letters:
# user input has not yet been guessed
# add the user's guess to the guessed letters set
guessed_letters.add(user_guess)
# remove the letter from letters not yet guessed in secret word
# if the guess is correct, Do this every
# time a correct guess is made. If a wrong guess
# is made, reduce the lives by 1
if user_guess in letters_in_word:
letters_in_word.remove(user_guess)
else:
attempts -= 1
elif user_guess in guessed_letters:
# user made this guess before.
print("You have already guessed this letter! Try again.")
else:
# user entered an invalid character
print("You have entered an invalid character! Try again.")
# display status
self.display_status(attempts, guessed_letters, secret_word)
# display the end message
if attempts == 0:
print("\nYou died! The word was '{}'".format(secret_word))
else:
print("\nYou won!!!")
The Game
class consists of the following definitions:
Attributes
- The dictionary of hangman images: The class attribute
stages
is a dictionary that stores each stage of the hangman image as a different image. The keys of the dictionary represent the lives/attempts remaining, while the values of the dictionary are the text-based images that will be displayed for each life. - The hangman text-images: The class attributes
STAGE0
,STAGE1
,STAGE2
,STAGE3
,STAGE4
,STAGE5
, andSTAGE6
, store the images for the different values of lives, or attempts left. - The word length range and the word cache: Each instance of the hangman
Game
class stores default values for the minimum and maximum length of words (in the attributes__min_word_length
and__max_word_length
respectively) that will be loaded from the text file. The value for the minimum is set to 5, and the maximum word length is set to 6. - The maximum number of attempts allowed: The
__max_attempts
instance attribute. This attribute stores the maximum number of attempts allowed before the game is lost. This attribute is set to a value of 6 and does not change throughout the gameplay. - The alphabet: The purpose of the attribute
__alphabet
is to provide a way to restrict the kind of characters the player can enter while guessing the letters of the secret word. The attribute stores the 26 letters of the alphabet in lowercase as a set of characters.
Methods
__initial_state()
: It returns a tuple,(random word, max attempts)
, to theplay()
method to help initialize the hangman gameplay.display_hangman()
: This method simply accesses theGame.status
dictionary using the current lives (or, remaining attempts) as the key. It then returns the corresponding hangman text image.display_status()
: This updates the display with the hangman text-image, the lives/attempts left and the already guessed letters in the secret word. An example of the display will look as follows:play()
: This method is where the hangman game loop is controlled.
The while-loop
first gets the player’s guess, then it checks for one of the following situations:
- player’s guess is part of the letters of the alphabet not yet guessed by the player. Then, the player’s guess is added to the set of guessed letters. If the player’s guess is part of the unguessed letters in the secret word, it is removed from the unguessed letters in the secret word, otherwise, the remaining attempts are reduced by one.
- player’s guess is part of the letters of the alphabet already guessed by the player. Then, it informs the player that his guess is already made.
- player’s guess is not part of the letters of the alphabet. This situation is the else part of the if statement and implies that the player either entered a whitespace character, an uppercase letter, or a special character. The player is then informed that his guess is an invalid character
After the while loop is exited, a message is displayed to the player based on whether all the letters of the secret message were correctly guessed, or all the attempts were exhausted.
The Main Module or driver module of the Hangman game: main_module.py
main_module.py
is the entry point of the game. It allows the player to replay the game as many times as he wants.
from game import Game
g = Game()
# ask if user wants to play again
user_input = "yes"
while user_input == "yes":
# enter game play loop
g.play()
# ask if user wants to play again
print("To play again, enter 'yes', but enter any other input to exit")
user_input = input("Play again? ").lower()
Each time the user agrees to replay the game (by entering ‘yes’). The game loop is repeated, and then the user is asked again if he/she wants to replay. Only when the player enters any other input does the loop, and the program, exit.
Conclusion
That’s it for our game of hangman. You could think of other ways this simple hangman game could be extended. For example
- Allow the player to also enter the full word, not just a letter in the word
- Allow the player to specify difficulty. For example, the lesser allowed attempts, the more difficult the game. Also, a bigger value of minimum word length means a more difficult game of hangman
- Print a welcome message, maybe also asking the player for a name, then using that name throughout the game
- Create a GUI/graphics version of the game
I hope you had fun while learning how to create a hangman in python. Thank you for reading to the end, and don’t forget to continue building your skills by creating more fun projects!
Want to get python help for more such awesome python projects? Feel free to contact us.