Step 2
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 5s

Replacing blanks with guesses
This commit is contained in:
2026-10-04 12:37:41 +08:00
parent f07c34a5fa
commit 15d5f7134d
6 changed files with 108 additions and 38 deletions
+4 -2
View File
@@ -16,14 +16,16 @@ A beginner-friendly Python program that lets you play Hangman in the terminal ag
Day 7 of Udemy's *100 Days of Code™: The Complete Python Pro Bootcamp*. The game is built in five steps that follow the course:
1. Picking a random word and checking answers *(this step)*
2. Replacing blanks with guesses
1. Picking a random word and checking answers
2. Replacing blanks with guesses *(this step)*
3. Checking if the player has won
4. Keeping track of the player's lives
5. Improving the user experience
**Step 1:** the program picks a random word, asks for one letter and tells you whether the letter is in the word.
**Step 2:** the word is shown as blanks (`_ _ _ _ _`). After your guess every matching blank is replaced by the letter.
## 📋 Requirements
- Python 3.13 or newer
+25 -23
View File
@@ -1,23 +1,25 @@
"""!
@file constants.py
@brief Constants shared across the Hangman game.
"""
## Words the computer picks from.
WORD_LIST = [
"aardvark",
"baboon",
"camel",
"dolphin",
"elephant",
"flamingo",
"giraffe",
"hedgehog",
"iguana",
"kangaroo",
"leopard",
"octopus",
"penguin",
"squirrel",
"tortoise",
]
"""!
@file constants.py
@brief Constants shared across the Hangman game.
"""
## Character shown for a letter that has not been guessed yet.
BLANK = "_"
## Words the computer picks from.
WORD_LIST = [
"aardvark",
"baboon",
"camel",
"dolphin",
"elephant",
"flamingo",
"giraffe",
"hedgehog",
"iguana",
"kangaroo",
"leopard",
"octopus",
"penguin",
"squirrel",
"tortoise",
]
+34 -1
View File
@@ -5,7 +5,7 @@
import random
from hangman.constants import WORD_LIST
from hangman.constants import BLANK, WORD_LIST
def choose_word(words: list[str] | None = None) -> str:
@@ -25,3 +25,36 @@ def is_in_word(word: str, letter: str) -> bool:
@return True if @p letter is in @p word.
"""
return letter.lower() in word.lower()
class Game:
"""!
@brief State of one Hangman game.
"""
def __init__(self, word: str) -> None:
"""!
@brief Start a new game.
@param word The secret word.
"""
## The secret word.
self.word = word.lower()
## Letters guessed so far.
self.guesses: set[str] = set()
def guess(self, letter: str) -> bool:
"""!
@brief Process a guess and reveal the letter if it is in the word.
@param letter A single letter.
@return True if the letter is in the word.
"""
letter = letter.lower()
self.guesses.add(letter)
return is_in_word(self.word, letter)
def display(self) -> str:
"""!
@brief The word with unguessed letters replaced by blanks.
@return For example `"p _ n g _ i n"`.
"""
return " ".join(c if c in self.guesses else BLANK for c in self.word)
+17 -7
View File
@@ -3,19 +3,29 @@
@brief Command-line interface for Hangman.
"""
from hangman.game import choose_word, is_in_word
from hangman.game import Game, choose_word
def say(message: str = "") -> None:
"""!
@brief Show a message to the player; all output goes through here.
@param message The text to show.
"""
print(message)
def main() -> None:
"""!
@brief Entry point: pick a random word and check one guessed letter.
@brief Entry point: show the blanks, take one guess and show the result.
"""
word = choose_word()
guess = input("Guess a letter: ").strip()
if is_in_word(word, guess):
print(f"Right, '{guess.lower()}' is in the word.")
game = Game(choose_word())
say(game.display())
letter = input("Guess a letter: ").strip()
if game.guess(letter):
say(f"Right, '{letter.lower()}' is in the word.")
else:
print(f"Wrong, '{guess.lower()}' is not in the word.")
say(f"Wrong, '{letter.lower()}' is not in the word.")
say(game.display())
if __name__ == "__main__":
+17 -1
View File
@@ -1,5 +1,5 @@
from hangman.constants import WORD_LIST
from hangman.game import choose_word, is_in_word
from hangman.game import Game, choose_word, is_in_word
def test_choose_word_from_list():
@@ -14,3 +14,19 @@ def test_letter_in_word():
def test_letter_not_in_word():
assert not is_in_word("camel", "z")
def test_display_starts_blank():
assert Game("cat").display() == "_ _ _"
def test_correct_guess_reveals_letters():
g = Game("banana")
assert g.guess("a") is True
assert g.display() == "_ a _ a _ a"
def test_wrong_guess_keeps_blanks():
g = Game("cat")
assert g.guess("z") is False
assert g.display() == "_ _ _"
+11 -4
View File
@@ -8,9 +8,16 @@ def run(monkeypatch, capsys, word, letter):
return capsys.readouterr().out
def test_right_guess(monkeypatch, capsys):
assert "Right" in run(monkeypatch, capsys, "camel", "a")
def test_right_guess_fills_blanks(monkeypatch, capsys):
out = run(monkeypatch, capsys, "camel", "a")
assert out.splitlines() == [
"_ _ _ _ _",
"Right, 'a' is in the word.",
"_ a _ _ _",
]
def test_wrong_guess(monkeypatch, capsys):
assert "Wrong" in run(monkeypatch, capsys, "camel", "z")
def test_wrong_guess_keeps_blanks(monkeypatch, capsys):
out = run(monkeypatch, capsys, "camel", "z")
assert "Wrong" in out
assert out.splitlines()[-1] == "_ _ _ _ _"