Hangman Game in Python

The Hangman is a classic game where a player needs to guess a word where all the letters are masked. The player has a certain number of attempts and needs to select a letter: if the selected letter is part of the word all the locations with the selected letter are unmasked, on the other hand if the selected letter is not contained in the word then the number of attempts of the player decreases by one. The player wins if finds the word within the number of attempts and loses otherwise.

This game can be written in Python by using less than 100 code lines and Figure 1 shows and example of the end result: the letters of the word are masked by '*', the letter 'a' is contained in the word so all the locations of letter 'a' are unmasked and the number of health points (i.e. attempts) stays the same.

Figure 1: Hangman Game Example
Figure 1: Hangman Game Example

The code will only require 2 libraries which are string and numpy: the first is used to get all the alphabet letters (it is optional given that it is possible to manually write a list with all the letters) while the second is used to generate random numbers. The code below shows how to import these libraries.

import string
import numpy as np

The code will use a file with a list of countries, one of these will be randomly selected and the letters masked with '*', then the health is set to its maximum value and a loop will start and continue until game is over (i.e. the player wins or loses). In the loop, the current discovered letters and the masked letters are shown to the user and then the user will be asked to select a letter from the list of letters available, once selected the word is modified if the letter is part of the word or the health is reduced if this is not the case, finally the game over condition is checked in order to go out of the loop. All these checks and updates are done within functions, if needed, the buttons below are tutorials on how to create functions, use files and handle errors in Python.

The first function is called load_file and loads the list of words from a file. The file in this case is quite simple, it is a .csv file with a single column with the list of countries. The code below shows that the function uses the file path to open the file and then adds the name of the countries, without the newline "\n", in a list and returns this list.

def load_file(file_path):
    name_countries=[]
    f = open(file_path, "r")
    for x in f:
      name_countries.append(x.strip("\n"))
    f.close()
    return name_countries

The file used in this example can be downloaded from the button below but another file with the same format can be used.

The second function is called mask_word and it replaces the letters with '*': it creates a new masked word which is initially empty and then if the character is a space it adds the space, otherwise it adds the '*' to the masked word.

def mask_word(word):
    masked_word=''
    for character in word:
        if(character!=' '):
            masked_word=masked_word+'*'
        else:
            masked_word=masked_word+' '
    return masked_word  

The third function, select_letter, allows the user to select a letter from a list of letters provided as input: this is repeated until the user has provided a valid letter which is part of the list. The output is the letter and its index in the list of letters.

def select_letter(letters):
    index=-1
    while(index==-1):
        l=input("Choose Letter: ")
        try:
            index=letters.index(l)
        except:
            print("Letter not in the list! Try again!")
    return [index,l]

The fourth function, update_mask, it uses the word, the masked word and the selected letter as input and then it creates a new masked word which, for each character, assumes the value of the word if the letter is found or the value of the masked word in case is not found. The function outputs the new masked word and also a variable 'found' which is 1 if the letter is found in the word or 0 otherwise.

def update_mask(masked_word,word,letter):
    found=0
    new_masked_word=''
    for i in range(len(word)):
        if(letter==word[i]):
            new_masked_word+=letter
            found=1
        else:
            new_masked_word+=masked_word[i]
    if(found==1):
        print("The selected letter is part of the word!")
    else:
        print("Wrong letter!")
    return [new_masked_word,found]

The fifth function, reduce_health, it uses a variable 'health' which is a number of remaining attempts and the variable 'found' obtained from the previous function. If the letter was not found then the health is reduced by 1.

def reduce_health(health,found):
    if(found==0):
        health-=1
    return health

The sixth function, print_letters, prints the available letters from the list of letters so that the user can choose one of them.

def print_letters(letters):
    print("Available Letters: ")
    s='|'
    for l in letters:
        s=s+l+"|"
    print(s)

The seventh function, print_info, prints the remaining health (using the hearts) and the masked word which initially is only made of '*' but then is gradually updated and in this way the user can try to understand which is the underlying word.

def print_info(masked_word,health):
    print("Health: "+"❤"*health)
    print("Word: "+masked_word)

The eigth function, check_game_over, checks if the game is finished. This can happen if there are no remaining attempts (the user loses) or if all the letters have been discovered (i.e. there are no '*' characters and the user wins).

def check_game_over(masked_word,health):
    game_over=0
    if(health==0 or masked_word.find("*")==-1):
        game_over=1
    return game_over 

Now all these functions need to be assembled together to create the game as shown in the commented code below.

#Load the file with your file_path and obtain the list of countries
file_path="Insert_file_path"  
name_countries=load_file(file_path)

#Use the string in-built function 'ascii_lowercase' which outputs all the letters from a to z.
letters=list(string.ascii_lowercase)
#Use the randint function within numpy to randomly select an index from the list of countries
index=np.random.randint(len(name_countries))
#Extract the word using the randomly selected index and user lower() so that uppercase letters are not considered.
word=name_countries[index].lower()
#Create the initial masked word formed by only '*'
masked_word=mask_word(word)
#Initialize the health to 5
health=5
#Initialize game_over to 0
game_over=0
#Repeat the loop while game_over is not 1
while(not game_over):
    #Print the information about the masked word and remaining health
    print_info(masked_word,health)
	#Print the available letters
    print_letters(letters)
	#Select a letter from the available letters
    [i,l]=select_letter(letters)
	#Remove the selected letter from the available letters
    letters.pop(i)
	#Update the masked_word using the selected letter
    [masked_word,found]=update_mask(masked_word,word,l)
	#Update the health if necessary
    health=reduce_health(health,found)
	#Check the game_over condition
    game_over=check_game_over(masked_word,health)
    print("----------")
#Once the game is finished print a Win message or Lose message based on the remaining health.
if(health>0):
    print("You Won!")
else:
    print("You Lost!")
print("The word was: ",word) 

The console below can be used to test parts of the code but the full code needs to be tested locally given that uses a file and requests inputs from a user. Overall, this version of Hangman Game is less than 100 code lines where the difficulty can be changed by modifying the initial health and also the available words can be easily changed by replacing the input file.