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: 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)* 1. Picking a random word and checking answers
2. Replacing blanks with guesses 2. Replacing blanks with guesses *(this step)*
3. Checking if the player has won 3. Checking if the player has won
4. Keeping track of the player's lives 4. Keeping track of the player's lives
5. Improving the user experience 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 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 ## 📋 Requirements
- Python 3.13 or newer - Python 3.13 or newer
+2
View File
@@ -3,6 +3,8 @@
@brief Constants shared across the Hangman game. @brief Constants shared across the Hangman game.
""" """
## Character shown for a letter that has not been guessed yet.
BLANK = "_"
## Words the computer picks from. ## Words the computer picks from.
WORD_LIST = [ WORD_LIST = [
"aardvark", "aardvark",
+34 -1
View File
@@ -5,7 +5,7 @@
import random import random
from hangman.constants import WORD_LIST from hangman.constants import BLANK, WORD_LIST
def choose_word(words: list[str] | None = None) -> str: 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 True if @p letter is in @p word.
""" """
return letter.lower() in word.lower() 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. @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: 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() game = Game(choose_word())
guess = input("Guess a letter: ").strip() say(game.display())
if is_in_word(word, guess): letter = input("Guess a letter: ").strip()
print(f"Right, '{guess.lower()}' is in the word.") if game.guess(letter):
say(f"Right, '{letter.lower()}' is in the word.")
else: 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__": if __name__ == "__main__":
+17 -1
View File
@@ -1,5 +1,5 @@
from hangman.constants import WORD_LIST 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(): def test_choose_word_from_list():
@@ -14,3 +14,19 @@ def test_letter_in_word():
def test_letter_not_in_word(): def test_letter_not_in_word():
assert not is_in_word("camel", "z") 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 return capsys.readouterr().out
def test_right_guess(monkeypatch, capsys): def test_right_guess_fills_blanks(monkeypatch, capsys):
assert "Right" in run(monkeypatch, capsys, "camel", "a") out = run(monkeypatch, capsys, "camel", "a")
assert out.splitlines() == [
"_ _ _ _ _",
"Right, 'a' is in the word.",
"_ a _ _ _",
]
def test_wrong_guess(monkeypatch, capsys): def test_wrong_guess_keeps_blanks(monkeypatch, capsys):
assert "Wrong" in run(monkeypatch, capsys, "camel", "z") out = run(monkeypatch, capsys, "camel", "z")
assert "Wrong" in out
assert out.splitlines()[-1] == "_ _ _ _ _"