Hangman Game
Abstract
Section titled “Abstract”Hangman is the perfect “second game” project. It is more complex than Rock-Paper-Scissors but still fits in one file. You learn file I/O (loading a word list), random selection, sets (tracking guessed letters), string assembly (showing the partially-revealed word), and game-state management (win, lose, keep going). In this tutorial you will build the classic version with a word list, then layer in ASCII-art gallows, input validation, category selection, score tracking, hints, and a replay loop.
You will learn:
- Why
setis the right structure for “letters already guessed”. - How to reveal a word letter-by-letter from a hidden secret.
- How to draw step-by-step ASCII art from a list of stages.
- How to organize game state into clean functions.
- How to extend a beginner game with categories, hints, and persistence.
The Rules
Section titled “The Rules”- The computer picks a secret word.
- The player sees blanks:
_ _ _ _ _ _ _. - Player guesses one letter at a time.
- Correct letters fill in their positions.
- Wrong letters cost one “limb” of the hanged figure.
- Player wins by completing the word; loses if the figure is fully drawn first.
Prerequisites
Section titled “Prerequisites”- Python 3.6 or above.
- A code editor or IDE.
- A text file of words (we will make one).
- Comfort with
whileloops,if/else, and basic file reading.
Getting Started
Section titled “Getting Started”Create the project
Section titled “Create the project”- Create a folder named
hangman-game. - Inside it, create
hangman.py. - Create
words.txtnext to it. Suggested starter contents:words.txt python programming computer science technology development software coding algorithm function variable recursion compiler interpreter
Write the code
Section titled “Write the code”Hangman
pch.viewSource# Hangman game
# -----------------------------------
# Importing the random module
import random
import time
# Inputting the name of the user
name = input("What is your name? ")
print("Good Luck ! ", name)
time.sleep(1)
print("The game is about to start !")
print("Let's play Hangman")
time.sleep(1)
open_file = open("words.txt", "r")
words = open_file.readlines()
# Function will choose one random
# word from this list of words
word = random.choice(words)
word = word.lower().strip().replace("\n", "").replace("\r", "").replace(" ", "").replace("-", "")
print("Guess the characters")
guesses = ''
turns = len(word) * 2
# Checks if the turns are more than zero
while turns > 0:
failed = 0
# for every character in secret_word
for char in word:
# see if the character is in the players guess
if char in guesses:
print(char, end="")
else:
print("_", end="")
# and increase the failed counter with one
failed += 1
if failed == 0:
print("\nYou Win")
# this print the correct word
print("The word is: ", word)
break
# if failed equals to zero
# then you will get this message
if turns == 1:
print("\nYou have", turns, 'more guess')
else:
print("\nYou have", turns, 'more guesses')
guess = input("guess a character: ")
# every input character will be stored in guesses
guesses += guess
# check input with the character in word
if guess not in word:
turns -= 1
# if the character doesn’t match the word
# then “Wrong” will be given as output
print("Wrong")
# this will print the number of
# turns left for the user
if turns == 1:
print("\nYou have", turns, 'more guess')
else:
print("\nYou have", turns, 'more guesses')
if turns == 0:
print("\nYou Loose")
print("\nThe word is: ", word)
break Run it
Section titled “Run it”C:\Users\Your Name\hangman-game> python hangman.py
What is your name? John
Good luck, John! Let's play Hangman.
Word: _ _ _ _ _ _ _
Guesses left: 6
Guess a letter: p
Word: p _ _ _ _ _ _
Guess a letter: ...Step-by-Step Explanation
Section titled “Step-by-Step Explanation”1. Imports
Section titled “1. Imports”import random
import timerandom.choice picks the word. time.sleep adds drama.
2. Load and pick a word
Section titled “2. Load and pick a word”with open("words.txt", encoding="utf-8") as f:
words = [line.strip().lower() for line in f if line.strip()]
word = random.choice(words)Reading inside a with block ensures the file is closed automatically. The list comprehension strips trailing newlines and skips empty lines.
3. Game state
Section titled “3. Game state”guessed_letters = set()
wrong = 0
max_wrong = 6Why a set for guessed_letters?
letter in guessed_lettersis O(1).- Adding a duplicate is harmless.
- It mirrors the natural language of the rules — “have I guessed this letter already?”
4. Reveal the secret partially
Section titled “4. Reveal the secret partially”def display(word: str, guessed: set[str]) -> str:
return " ".join(c if c in guessed else "_" for c in word)A list/generator comprehension over the secret word: keep characters the player has guessed, otherwise show _. " ".join(...) spaces them out for readability.
5. The main loop
Section titled “5. The main loop”while wrong < max_wrong:
print(f"\n{display(word, guessed_letters)}")
print(f"Guesses left: {max_wrong - wrong}")
guess = input("Guess a letter: ").lower().strip()
if len(guess) != 1 or not guess.isalpha():
print("Enter a single letter.")
continue
if guess in guessed_letters:
print("Already guessed.")
continue
guessed_letters.add(guess)
if guess in word:
if all(c in guessed_letters for c in word):
print(f"\n🎉 You win! The word was '{word}'.")
break
else:
wrong += 1
print("Wrong!")
else:
print(f"\nYou lost. The word was '{word}'.")Several patterns in play:
- Input validation rejects multi-char or non-alphabetic input.
- Duplicate detection uses the set.
- Win check asks “are every letter of the word now in
guessed?” —all(...)is the right tool. elseclause on awhileruns only if the loop ended normally (the player ran out of guesses). It is a lesser-known but elegant feature of Python.
ASCII-Art Gallows
Section titled “ASCII-Art Gallows”A 7-frame gallows that draws progressively as the player loses:
STAGES = [
r"""
-----
| |
|
|
|
|
=========""",
r"""
-----
| |
O |
|
|
|
=========""",
r"""
-----
| |
O |
| |
|
|
=========""",
r"""
-----
| |
O |
/| |
|
|
=========""",
r"""
-----
| |
O |
/|\ |
|
|
=========""",
r"""
-----
| |
O |
/|\ |
/ |
|
=========""",
r"""
-----
| |
O |
/|\ |
/ \ |
|
=========""",
]
print(STAGES[wrong]) # in the main loopSix wrong guesses → seven stages (0 wrong = empty gallows, 6 wrong = full hangman). The r"""...""" is a raw triple-quoted string — backslashes inside stay literal.
Common Mistakes
Section titled “Common Mistakes”| Problem | Cause | Fix |
|---|---|---|
| Word contains a newline character | Forgot .strip() after readlines() | Use the list-comp above |
| Capital letters never match | Mixed cases | Lowercase both the word and the guess |
| Pressing Enter empty crashes the game | No length check | Validate len(guess) == 1 |
| Counting wrong letters when a duplicate is pressed | No duplicate check | Skip already-guessed letters |
| Win never triggers | Used == instead of all(... in ...) | Use all(c in guessed_letters for c in word) |
Variations to Try
Section titled “Variations to Try”1. Categories
Section titled “1. Categories”Store one word list per category:
fruits.txt
animals.txt
programming.txtAsk the user to pick a category. Each .txt becomes a Path:
from pathlib import Path
cats = {p.stem: p for p in Path("words").glob("*.txt")}
choice = input(f"Pick: {', '.join(cats)}\n> ")
words = cats[choice].read_text().splitlines()2. Difficulty levels
Section titled “2. Difficulty levels”- Easy: 4–6 letter words, 8 guesses.
- Medium: 7–9 letter words, 6 guesses.
- Hard: 10+ letter words, 5 guesses, only common letters give hints.
3. Hints
Section titled “3. Hints”Give a hint after N wrong guesses — reveal one letter automatically:
if wrong == 4:
for c in word:
if c not in guessed_letters:
print(f"Hint: contains '{c}'")
guessed_letters.add(c)
break4. Score tracking
Section titled “4. Score tracking”A win earns (letters - wrong) * 10 points. Persist between sessions in a JSON file. See Personal Diary for the same persistence pattern.
5. Replay loop
Section titled “5. Replay loop”while True:
play_round()
if input("Play again? (y/n): ").lower() != "y":
break6. Two-player mode
Section titled “6. Two-player mode”Player 1 enters the word secretly (getpass.getpass hides it from the terminal); Player 2 guesses.
7. GUI version
Section titled “7. GUI version”Tkinter with a letter-grid of buttons and an image-based gallows. See Basic Music Player for the GUI pattern.
8. Web version
Section titled “8. Web version”Flask plus a single HTML page. The state lives in the user’s session. See Basic Web Server.
9. Word source from an API
Section titled “9. Word source from an API”Pull a random English word from a dictionary API instead of words.txt:
import requests
word = requests.get("https://random-word-api.herokuapp.com/word").json()[0]10. Definition reveal
Section titled “10. Definition reveal”After the round, look up the word’s definition using pip install nltk + the WordNet corpus, and show it to teach vocabulary.
Refactoring with a Class
Section titled “Refactoring with a Class”For a serious version, wrap state in a class:
class Hangman:
def __init__(self, word: str, max_wrong: int = 6):
self.word = word.lower()
self.guessed: set[str] = set()
self.wrong = 0
self.max_wrong = max_wrong
def guess(self, letter: str) -> str:
letter = letter.lower()
if letter in self.guessed:
return "duplicate"
self.guessed.add(letter)
if letter not in self.word:
self.wrong += 1
return "miss"
return "hit"
@property
def display(self) -> str:
return " ".join(c if c in self.guessed else "_" for c in self.word)
@property
def is_won(self) -> bool:
return all(c in self.guessed for c in self.word)
@property
def is_lost(self) -> bool:
return self.wrong >= self.max_wrongNow the game logic is testable without input() — perfect for unit tests.
Real-World Applications
Section titled “Real-World Applications”- Vocabulary teaching — a hangman with curated word lists works in language learning apps.
- CAPTCHA-style verification in a friendly form.
- Conference / classroom icebreaker — group hangman on a projector.
- Onboarding gamification — turn product terminology into a guessing game.
Educational Value
Section titled “Educational Value”This project teaches:
- File I/O — reading lists from text files.
- Sets — O(1) membership tests and natural-language semantics.
- String manipulation — partial reveal, comparison, validation.
- Game-state management — wrong count, guessed letters, win/lose conditions.
- Refactoring — moving from a script to a class for testability.
Next Steps
Section titled “Next Steps”- Build the ASCII-art version with the
STAGESlist above. - Add categories and difficulty levels.
- Wrap state in a
Hangmanclass and add unit tests withpytest. - Build a GUI or web version.
- Use a real word API so the dictionary never runs out.
Conclusion
Section titled “Conclusion”You built a complete Hangman game from a 50-line script: file loading, secret picking, partial reveal, input validation, win/lose conditions, and ASCII-art gallows. The same patterns power dozens of guessing games and quiz apps. Full source on GitHub. Explore more games on Python Central Hub.
pch.coffeeTagline
pch.coffeeCtapch.feedbackHeading
pch.feedbackSubheading