Problem statement
Design the object model and core APIs for a single-process word-guessing game engine (think a classic hangman round played in a terminal or as a test harness). A secret word is chosen, the player calls out one letter at a time, and each guess either reveals every matching position in the word or costs one of a fixed budget of wrong attempts. The engine owns the rules and the running state; whatever drives it merely feeds letters in and reads the masked word, the score, and the outcome back.
Operating context. One round at a time, one player, one thread, no clock and no network. At construction the engine is handed a word source (which supplies the secret word) and the number of wrong attempts allowed. A guess is a single letter and is case-insensitive. A letter already guessed (whether it hit or missed) is a repeat and must not cost a second attempt. A correct guess reveals the letter at every position it occurs; a wrong guess decrements the remaining attempts. The round ends in a win when every position is revealed, or in a loss when the remaining attempts reach zero. Scoring rewards efficient play: fewer wrong guesses and fewer total guesses score higher.
Out of scope. Any rendering or drawing of the gallows/figure, console or keyboard input parsing, multiplayer or networked play, persistence of scores or resume across rounds, and hint or reveal-a-letter power-ups. Design only the in-process rules engine and its object model.
What to produce. The class hierarchy (entities such as Game/Round and any value objects like a Letter, a Guess, or the masked-word view), the public API each class exposes, and the state transitions of the round (setup, in-progress, won, lost) and of a guess (hit, miss, repeat). Be explicit about: how the word source is abstracted so a test can force a known word; how the masked reveal is computed without leaking un-guessed letters; how repeats are detected so they never cost an attempt; how game-over (win vs loss) is decided after each guess; and how the scoring rule is kept swappable.
Functional requirements
- Accept a single-letter guess, normalize its case, and classify it as a hit, a miss, or a repeat of an earlier guess.
- On a hit, reveal the guessed letter at every position where it occurs in the secret word.
- On a miss, decrement the remaining wrong-attempt budget by exactly one.
- Track and ignore repeat guesses so that guessing an already-tried letter never changes the attempt budget or state.
- Detect game over after each guess: a win when the whole word is revealed, a loss when remaining attempts hit zero.
- Expose read-only queries for the masked word, the letters guessed so far, the attempts left, the score, and the outcome.
Non-functional requirements
- Applying one guess (classify, reveal, update state) is O(L) in the word length L, with repeat lookup O(1).
- The word source is an injected abstraction so a test can force a known secret word with no real randomness.
- The masked-word view never exposes an un-guessed letter, so a caller cannot read the answer before winning.
- A repeat guess is idempotent: re-guessing a tried letter leaves attempts, reveals, and status exactly unchanged.
- The scoring rule is pluggable behind a seam, so a new formula swaps in without touching guess handling.
- The engine is unit-testable with no wall clock, no console I/O, and no rendering layer — letters in, state out.
Topics
- System Design LLD
- Oop Solid
- Statemachine
- Patterns Strategy
- Testability Clock