Cool Stuff

The Game of Hangman in Python

June 6, 2013

Computer games and python are like a perfect match, it just works. Python is simple enough and powerful to provide game designer and programers a common ground for them to meet up and create awesome stuff. In fact, Python has the PyGame library that is dedicated to creating games. There are many games for Python, buy I thought it would be beneficial to start off with a simple version of Hangman. As before, we will be using Python 2.7 for our examples.

Before we take off with it, let us agree to the rules of the game:

  • The computer will randomly chose a secret word.
  • For each user guess, all occurrences of the same letter in the word will be revealed to the player.
  • The computer will draw the “hangman digram” as outlined bellow for each turn.
  • The user may guess letters at each turn until the word is completed or the “hangman digram” is complete.
  • We can assume that all user input and word letters are lowercase alpha numeric without errors.

The last one is made to simplify the code and the constrains for the problem. In reality we should always account for errors, but I am going to et this one slide. For now. Let us first look and the “hangman digram”. Some people think this is the hardest thing, but it is actually the easiest. Here are the 7 possibilities of the board in ASCII art form.

  +---+
  |   |
      |
      |
      |
      |
=========

  +---+
  |   |
  0   |
  |   |
      |
      |
=========

  +---+
  |   |
  0   |
 /|   |
      |
      |
=========

  +---+
  |   |
  0   |
 /|\  |
      |
      |
=========

  +---+
  |   |
  0   |
 /|\  |
 /    |
      |
=========

  +---+
  |   |
  0   |
 /|\  |
 / \  |
      |
=========

This was generated by this short Python code:


board = [
'  +---+   \n  |   |   \n      |   \n      |   \n      |   \n      |   \n========= \n',
'  +---+   \n  |   |   \n  0   |   \n      |   \n      |   \n      |   \n========= \n',
'  +---+   \n  |   |   \n  0   |   \n  |   |   \n      |   \n      |   \n========= \n',
'  +---+   \n  |   |   \n  0   |   \n /|   |   \n      |   \n      |   \n========= \n',
'  +---+   \n  |   |   \n  0   |   \n /|\\  |   \n      |   \n      |   \n========= \n',
'  +---+   \n  |   |   \n  0   |   \n /|\\  |   \n /    |   \n      |   \n========= \n',
'  +---+   \n  |   |   \n  0   |   \n /|\\  |   \n / \\  |   \n      |   \n========= \n'
]

for i in range(len(borad)):
	print board[i]

This will take care of any of the board configurations. All we need to worry about is how many letters the user has got wrong and we can immediately print out the corresponding “hangman diagram”. Let us make it a little more nice and wrap it in a class. Classes are objects in Python, very similar to Objects in Java. We can encapsulate the board configuration, word to be guessed, missed letters and guessed letters in 1 object. Lets take a look:


board = [
'  +---+   \n  |   |   \n      |   \n      |   \n      |   \n      |   \n========= \n',
'  +---+   \n  |   |   \n  0   |   \n      |   \n      |   \n      |   \n========= \n',
'  +---+   \n  |   |   \n  0   |   \n  |   |   \n      |   \n      |   \n========= \n',
'  +---+   \n  |   |   \n  0   |   \n /|   |   \n      |   \n      |   \n========= \n',
'  +---+   \n  |   |   \n  0   |   \n /|\\  |   \n      |   \n      |   \n========= \n',
'  +---+   \n  |   |   \n  0   |   \n /|\\  |   \n /    |   \n      |   \n========= \n',
'  +---+   \n  |   |   \n  0   |   \n /|\\  |   \n / \\  |   \n      |   \n========= \n'
]

class Hangman:
	def __init__(self,word):
		self.word = word
		self.missed_letters = []
		self.guessed_letters = []

Sweet. Let us move on and create a print function. Print functions are useful for debugging and will take care of our user interface. When we want to print our Hangman object, we really want to know all the information, how the board looks like (or how much of the diagram is complete), the letter we missed, the blank splits for the words and letters we already found. Let us take a look:


def print_game_status(self):
		print board[len(self.missed_letters)]
		print 'Word: ' + self.hide_word()
		print 'Letters Missed: ',
		for letter in self.missed_letters:
			print letter,
		print
		print 'Letters Guessed: ',
		for letter in self.guessed_letters:
			print letter,
		print

And the output for an empty board:

wpid-hangman_empty_board_python-2013-06-6-13-05.png

Upon close inspection, you will notice that there is another method I am calling name hide_word(). By the concatenation with the string before, you can assume the function is defined and returns a string. What we really need, is a function that can take a word and print out only the letters the user has already guessed. Let’s take a look:


def hide_word(self):
		rtn = ''
		for letter in self.word:
			if letter not in self.guessed_letters:
				rtn += '_'
			else:
				rtn += letter
		return rtn

That seems good enough. Before we can move on to the game play and logic, we need a method in the Hangman object to update a current guess. That is straight forward and looks like so:


def guess(self,letter):
		if letter in self.word and letter not in self.guessed_letters:
			self.guessed_letters.append(letter)
		elif letter not in self.word and letter not in self.missed_letters:
			self.missed_letters.append(letter)
		else:
			return False
		return True

So if the letter is in the word we are trying to guess and we haven’t tried to guess it before, we are going to mark it and return 1 for successful update or if the letter is not in our word, but has not been asked again. If either of these conditions is a failure, we have a repeat input we have already accounted for and we will return 0 to notify the game handler of a problem. The last method we are really missing is to check for win condition. Here is how we can check for hangman win condition in our case:


def hangman_won(self):
		if '_' not in self.hide_word():
			return True
		return False

Notice that we are reusing methods we already have, making things simple. Now our Hangman game object is complete. You will think that we are over, but there is one more method we are missing for the game to be complete. We have a method to check if the game has been won, but we do not have a method to check if the game is over. What happens when the “hangman digram” is complete? For this we will add just a one liner method:


def hangman_over(self):
		return self.hangman_won() or len(self.missed_letters) == 7

Sweet. Now all we need is a main driver and some helper function and we are all done. Our main method can look like this:


def main():

	game = Hangman(rand_word())
	while not game.hangman_over():
		game.print_game_status()
		user_input = raw_input('\nEnter a letter: ')
		game.guess(user_input)

	game.print_game_status()
	if game.hangman_won():
		print '\nCongratulations! You are the winner of Hangman!'
	else:
		print '\nSorry, you have lost in the game of Hangman...'
		print 'The word was ' + game.word

	print '\nGoodbye!\n'

You will be now notice that we are almost done, just 1 more function and we are clear, the rand_word() function. Now you can get very fancy with this, read from a file and randomly choose and such. However, I want to keep things simple, so I limited the word bank into a small list from which I randomly choose 1 word. Check it out:


def rand_word():

	bank = ['the','living','pearl','.com','captain','deadbones']
	return bank[random.randint(0,len(bank))]

That’s all folks. That is the simple way you can get a game started in python. Now you might think this is very complex. If you are looking for a more simple approach, there is a whole chapter about hangman in python I recommend you check out. The reason we set it up like this is so we can add some GUI events or make it more complex without a lot of hassle. You can download the Python code for Hangman or code it yourself. I hope this gave you some flavor to how games and python could work together. What game can you come up with?

Here are some output screen shots:

wpid-python_hangman_game_screen_1-2013-06-6-13-05.png

wpid-python_hangman_game_screen_2-2013-06-6-13-05.png

wpid-python_hangman_game_screen_3-2013-06-6-13-05.png
wpid-python_hangman_game_screen_4-2013-06-6-13-05.png

wpid-python_hangman_game_screen_6-2013-06-6-13-05.png

wpid-python_hangman_game_screen_5-2013-06-6-13-05.png

If you enjoyed this post, please consider leaving a comment or subscribing to the RSS feed to have future articles delivered to your feed reader.

You Might Also Like

  • Neftas

    Hey there! I read your script and ran it a few times, enjoyed it. I noticed that you can enter any amount of characters you want, so user_imput 'random amount of characters' also gets added to self.missed_letters. So I added a few lines of code to fix that.

    • CptDeadBones

      Thank you! I am glad you enjoyed my little game. I did not try to account for user error. You are correct in fixing it. I am happy you shared it. Thanks!