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:

Hangman game in python game play

 

How to Make Hangman Game in Python

The hangman game is divided into three modules to simplify the program:

  1. words.py: Defines the class WordCache that helps to load the words from a text file, and then allows the game to request a random word.
  2. game.py: Defines the Game class. The Game class controls the actual gameplay.
  3. 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 parameter max_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

  1. 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.
  2. The hangman text-images: The class attributes STAGE0, STAGE1, STAGE2, STAGE3, STAGE4, STAGE5, and STAGE6, store the images for the different values of lives, or attempts left.
  3. 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_lengthrespectively) 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.
  4. 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.
  5. 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

  1. __initial_state(): It returns a tuple, (random word, max attempts), to the play() method to help initialize the hangman gameplay.
  2. display_hangman(): This method simply accesses the Game.status dictionary using the current lives (or, remaining attempts) as the key. It then returns the corresponding hangman text image.
  3. 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:
  4. 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, 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.

Like this article? Follow us on Facebook and LinkedIn.