Hangman and Guillotine

Tags: large, game, puzzle, word

This classic word game has the player guess the letters to a secret word. For each incorrect letter, another part of the hangman is drawn. Try to guess the complete word before the hangman completes. The secret words in this version are all animals like RABBIT and PIGEON, but you can replace these with your own set of words.

The HANGMAN_PICS variable contains ASCII-art strings of each step of the hangman’s noose:

 +--+     +--+     +--+     +--+     +--+     +--+     +--+
 |  |     |  |     |  |     |  |     |  |     |  |     |  |
    |     O  |     O  |     O  |     O  |     O  |     O  |
    |        |     |  |    /|  |    /|\ |    /|\ |    /|\ |
    |        |        |        |        |    /   |    / \ |
    |        |        |        |        |        |        |
=====    =====    =====    =====    =====    =====    =====

For a French twist on the game, you can replace the strings in the HANGMAN_PICS variable with the following strings depicting a guillotine:

|        |   |    |===|    |===|    |===|    |===|    |===|
|        |   |    |   |    |   |    |   |    || /|    || /|
|        |   |    |   |    |   |    |   |    ||/ |    ||/ |
|        |   |    |   |    |   |    |   |    |   |    |   |
|        |   |    |   |    |   |    |   |    |   |    |   |
|        |   |    |   |    |   |    |/-\|    |/-\|    |/-\|
|        |   |    |   |    |\ /|    |\ /|    |\ /|    |\O/|
|===     |===|    |===|    |===|    |===|    |===|    |===|
hangman_and_guillotine.py
  1"""Hangman, by Al Sweigart al@inventwithpython.com
  2Guess the letters to a secret word before the hangman is drawn.
  3This code is available at https://nostarch.com/big-book-small-python-programming
  4Tags: large, game, word, puzzle"""
  5
  6# A version of this game is featured in the book "Invent Your Own
  7# Computer Games with Python" https://nostarch.com/inventwithpython
  8
  9import random, sys
 10
 11# Set up the constants:
 12# (!) Try adding or changing the strings in HANGMAN_PICS to make a
 13# guillotine instead of a gallows.
 14HANGMAN_PICS = [r"""
 15 +--+
 16 |  |
 17    |
 18    |
 19    |
 20    |
 21=====""",
 22r"""
 23 +--+
 24 |  |
 25 O  |
 26    |
 27    |
 28    |
 29=====""",
 30r"""
 31 +--+
 32 |  |
 33 O  |
 34 |  |
 35    |
 36    |
 37=====""",
 38r"""
 39 +--+
 40 |  |
 41 O  |
 42/|  |
 43    |
 44    |
 45=====""",
 46r"""
 47 +--+
 48 |  |
 49 O  |
 50/|\ |
 51    |
 52    |
 53=====""",
 54r"""
 55 +--+
 56 |  |
 57 O  |
 58/|\ |
 59/   |
 60    |
 61=====""",
 62r"""
 63 +--+
 64 |  |
 65 O  |
 66/|\ |
 67/ \ |
 68    |
 69====="""]
 70
 71# (!) Try replacing CATEGORY and WORDS with new strings.
 72CATEGORY = 'Animals'
 73WORDS = 'ANT BABOON BADGER BAT BEAR BEAVER CAMEL CAT CLAM COBRA COUGAR COYOTE CROW DEER DOG DONKEY DUCK EAGLE FERRET FOX FROG GOAT GOOSE HAWK LION LIZARD LLAMA MOLE MONKEY MOOSE MOUSE MULE NEWT OTTER OWL PANDA PARROT PIGEON PYTHON RABBIT RAM RAT RAVEN RHINO SALMON SEAL SHARK SHEEP SKUNK SLOTH SNAKE SPIDER STORK SWAN TIGER TOAD TROUT TURKEY TURTLE WEASEL WHALE WOLF WOMBAT ZEBRA'.split()
 74
 75
 76def main():
 77    print('Hangman, by Al Sweigart al@inventwithpython.com')
 78
 79    # Setup variables for a new game:
 80    missedLetters = []  # List of incorrect letter guesses.
 81    correctLetters = []  # List of correct letter guesses.
 82    secretWord = random.choice(WORDS)  # The word the player must guess.
 83
 84    while True:  # Main game loop.
 85        drawHangman(missedLetters, correctLetters, secretWord)
 86
 87        # Let the player enter their letter guess:
 88        guess = getPlayerGuess(missedLetters + correctLetters)
 89
 90        if guess in secretWord:
 91            # Add the correct guess to correctLetters:
 92            correctLetters.append(guess)
 93
 94            # Check if the player has won:
 95            foundAllLetters = True  # Start off assuming they've won.
 96            for secretWordLetter in secretWord:
 97                if secretWordLetter not in correctLetters:
 98                    # There's a letter in the secret word that isn't
 99                    # yet in correctLetters, so the player hasn't won:
100                    foundAllLetters = False
101                    break
102            if foundAllLetters:
103                print('Yes! The secret word is:', secretWord)
104                print('You have won!')
105                break  # Break out of the main game loop.
106        else:
107            # The player has guessed incorrectly:
108            missedLetters.append(guess)
109
110            # Check if player has guessed too many times and lost. (The
111            # "- 1" is because we don't count the empty gallows in
112            # HANGMAN_PICS.)
113            if len(missedLetters) == len(HANGMAN_PICS) - 1:
114                drawHangman(missedLetters, correctLetters, secretWord)
115                print('You have run out of guesses!')
116                print('The word was "{}"'.format(secretWord))
117                break
118
119
120def drawHangman(missedLetters, correctLetters, secretWord):
121    """Draw the current state of the hangman, along with the missed and
122    correctly-guessed letters of the secret word."""
123    print(HANGMAN_PICS[len(missedLetters)])
124    print('The category is:', CATEGORY)
125    print()
126
127    # Show the incorrectly guessed letters:
128    print('Missed letters: ', end='')
129    for letter in missedLetters:
130        print(letter, end=' ')
131    if len(missedLetters) == 0:
132        print('No missed letters yet.')
133    print()
134
135    # Display the blanks for the secret word (one blank per letter):
136    blanks = ['_'] * len(secretWord)
137
138    # Replace blanks with correctly guessed letters:
139    for i in range(len(secretWord)):
140        if secretWord[i] in correctLetters:
141            blanks[i] = secretWord[i]
142
143    # Show the secret word with spaces in between each letter:
144    print(' '.join(blanks))
145
146
147def getPlayerGuess(alreadyGuessed):
148    """Returns the letter the player entered. This function makes sure
149    the player entered a single letter they haven't guessed before."""
150    while True:  # Keep asking until the player enters a valid letter.
151        print('Guess a letter.')
152        guess = input('> ').upper()
153        if len(guess) != 1:
154            print('Please enter a single letter.')
155        elif guess in alreadyGuessed:
156            print('You have already guessed that letter. Choose again.')
157        elif not guess.isalpha():
158            print('Please enter a LETTER.')
159        else:
160            return guess
161
162
163# If this program was run (instead of imported), run the game:
164if __name__ == '__main__':
165    try:
166        main()
167    except KeyboardInterrupt:
168        sys.exit()  # When Ctrl-C is pressed, end the program.

https://inventwithpython.com/bigbookpython/project34.html