Replacing blanks with guesses
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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] == "_ _ _ _ _"
|
||||||
|
|||||||
Reference in New Issue
Block a user