Hangman

Game rules:

Hangman is a popular word guessing game where the player attempts to build a missing word by guessing one letter at a time.

  • The program randomly generates a secret word and indicates its length with according number of underscores
  • The player guesses one letter at a time
  • After 6 incorrect guesses the player loses and the game ends
  • The game also ends if the player correctly identifies all the letters of the secret word
  • Player is not penalized for guessing a letter they already tried
  • Regardless of the final result player can choose to start a new game or finish & exit
Game in action:

Why don't you have a go and play the game yourself in the console embedded below? :)

Program flow:

The following flow chart has been created and used as a basis for designing the program logic.

program flow diagram
Sample run:

Here is what the user sees when they run the Hangman program. The following example game run results in player losing the game:



        Welcome to Hangman! Guess the word before your man gets hung!
        _______________
          | /       |
          |/        |
          |
          |
          |
          |
          |
          |
        =====
        This is your secret word:
        _ _ _ _ _ _ _ _
        Guess a letter: e
        _ _ E _ _ _ _ _
        Guess a letter: a
        _______________
          | /       |
          |/        |
          |         O
          |
          |
          |
          |
          |
        =====
        No such letter! Try a different one.
        Guess a letter: n
        _ _ E _ _ _ N _
        Guess a letter: o
        _______________
          | /       |
          |/        |
          |         O
          |         |
          |         |
          |
          |
          |
        =====
        No such letter! Try a different one.
        Guess a letter: l
        _ _ E L _ _ N _
        Guess a letter: m
        _______________
          | /       |
          |/        |
          |         O
          |       __|
          |         |
          |
          |
          |
        =====
        No such letter! Try a different one.
        Guess a letter: r
        _______________
          | /       |
          |/        |
          |         O
          |       __|__
          |         |
          |
          |
          |
        =====
        No such letter! Try a different one.
        Guess a letter: a
        You've tried this letter before and it's not there just trust me.
        Guess a letter: t
        _______________
          | /       |
          |/        |
          |         O
          |       __|__
          |         |
          |        /
          |
          |
        =====
        No such letter! Try a different one.
        Guess a letter: c
        C _ E L _ _ N _
        Guess a letter: h
        C H E L _ _ N _
        Guess a letter: s
        _______________
          | /       |
          |/        |
          |         O
          |       __|__
          |         |
          |        / \
          |
          |
        =====
        No such letter! Try a different one.
        Guess a letter: i
        C H E L _ I N _
        Guess a letter: u
        _______________
          | /       |
          |/        |
          |         X
          |       __|__
          |         |
          |        / \
          |
          |
        =====
        You lost! You have reached the maximum number of incorrect guesses.
        The secret word was --> CHELPING <--
        Why don't you try again? :)
        To play press '1', to exit press '2': 2
        See you soon!

                    
Source code:

This section contains the source code of the game along with its comments.



        # ------------------------------------->     GAME     <-------------------------------------

        import random


        # hangman drawing function; depending on number of incorrect guesses user has made appropriate message is shown
        def draw_hangman(num_of_incr_guesses):
            options = {
                0: "_______________\n  | /       |  \n  |/        |\n  |\n  |\n  |\n  |\n  |\n  |\n=====",
                1: "_______________\n  | /       |  \n  |/        |\n  |         O\n  |\n  |\n  |\n  |\n  |\n=====",
                2: "_______________\n  | /       |  \n  |/        |\n  |         O\n  |         |\n  |         |\n  |\n  |\n  "
                   "|\n=====",
                3: "_______________\n  | /       |  \n  |/        |\n  |         O\n  |       __|\n  |         |\n  |\n  |\n  "
                   "|\n=====",
                4: "_______________\n  | /       |  \n  |/        |\n  |         O\n  |       __|__\n  |         |\n  |\n  "
                   "|\n  |\n=====",
                5: "_______________\n  | /       |  \n  |/        |\n  |         O\n  |       __|__\n  |         |\n  |      "
                   "  /\n  |\n  |\n=====",
                6: "_______________\n  | /       |  \n  |/        |\n  |         O\n  |       __|__\n  |         |\n  |      "
                   "  / \ \n  |\n  |\n=====",
                7: "_______________\n  | /       |  \n  |/        |\n  |         X\n  |       __|__\n  |         |\n  |      "
                   "  / \ \n  |\n  |\n=====",
            }

            print(options[num_of_incr_guesses])


        # function that picks a random word from a list of words from the SOWPODS dictionary
        def pick_random_word():
            with open('sowpods_dict.txt', 'r') as f:
                # read all words and save them in a list
                list_of_words = f.readlines()

            dict_size = len(list_of_words)
            # generate random number
            random_num = random.randint(0, dict_size + 1)
            # take the word and remove any whitespaces
            random_word = list_of_words[random_num].strip()

            return random_word


        # main function of the game
        def play_hangman():

            # generate random word and find it's length
            secret_word = pick_random_word()
            secret_word_length = len(secret_word)

            # for each letter in random word add a space (for better game visual effect and later comparison purposes)
            secret_word_with_ending_spaces = ""
            for letter in secret_word:
                secret_word_with_ending_spaces += letter + " "

            # variables initialization
            max_num_of_guesses = 6
            guesses_counter = 0
            user_word_list = []
            user_wrong_letters = []

            # first filling up of the user guessing list with underscores to indicate the length of the secret word
            for i in range(secret_word_length):
                user_word_list.append("_ ")

            # joining into string to remove square brackets
            user_word_str = "".join(user_word_list)

            # welcome into the game and introduce length of the unknown secret word
            print("Welcome to Hangman! Guess the word before your man gets hung!")
            draw_hangman(guesses_counter)
            print("This is your secret word:")
            print(user_word_str)

            # game logic - as long as user word isn't matching secret word and number of incorrect guesses has not be exceed
            # keep asking user for a letter
            while user_word_str != secret_word_with_ending_spaces and guesses_counter <= max_num_of_guesses:
                user_letter = input("Guess a letter: ").upper()

                # validating user input - only letters, if wrong input - ask again
                if not user_letter.isalpha():
                    print("Only letters please!")
                    continue

                # validating user input - only one letter at a time, if wrong input - ask again
                elif len(user_letter) > 1:
                    print("Only one letter at a time.")
                    continue

                # check if user guessed that letter already, if yes, ask again for a new one
                elif user_letter in user_word_str:
                    print("You've tried this letter already. Choose a different one.")
                    continue

                # check if the guessed letter is in secret word
                elif user_letter in secret_word:
                    # when it is - check it's all positions in secret word
                    letter_indices_in_sw = [i for i, letter in enumerate(secret_word) if letter == user_letter]

                    # overwriting the underscores with correctly guessed letters
                    for elem in letter_indices_in_sw:
                        user_word_list[elem] = user_letter + " "

                    # joining into string to remove square brackets and showing the updated word
                    user_word_str = "".join(user_word_list)
                    print(user_word_str)

                # check if user is trying to guess the incorrect letter again, if yes - ask for new letter
                elif user_letter in user_wrong_letters:
                    print("You've tried this letter before and it's not there just trust me.")
                    continue

                # at this point it is known that guessed letter is not in the secret word
                else:
                    # hence increase the incorrect guess counter and make a note of that letter
                    guesses_counter += 1
                    user_wrong_letters.append(user_letter)

                    # if the user still have moves print according message and draw a hangman
                    if guesses_counter <= max_num_of_guesses:
                        draw_hangman(guesses_counter)
                        print("No such letter! Try a different one.")

            # when user exceeds the amount of incorrect guesses he looses; an appropriate message is shown and a dead hangman
            # is drawn; finally ask if want to play again
            if guesses_counter > max_num_of_guesses:
                draw_hangman(guesses_counter)
                print("You lost! You have reached the maximum number of incorrect guesses.\nThe secret word was --> {} "
                      "<--\nWhy don't you try again? :)".format(secret_word))
            # otherwise he wins and so appropriate message is shown + ask if want to play again
            else:
                print("Congratulations, you won!\nFancy playing one more time?")

            # check if user want to play again
            play_again = ""
            # check for valid input, ask until valid
            while play_again not in ("1", "2"):
                play_again = input("To play press '1', to exit press '2': ")

            # if want to play - resume the game
            if play_again == "1":
                print("\n---------------------------->>>  NEW GAME <<<----------------------------\n")
                return play_hangman()
            # otherwise say goodbye and end the game
            else:
                print("See you soon!")


        if __name__ == '__main__':
            play_hangman()