One way to clear each phase. Compare the approach with your own, then try the patterns yourself.
"""Phase 1: Validator must accept both upper- and lowercase letters
because the game is case-insensitive."""
class Validator:
"""Enforces input rules for the Word Reveal game."""
def is_valid(self, guess: str) -> bool:
"""A guess is valid if it is exactly one alphabetic character.
Both 'A' and 'a' are acceptable."""
if not isinstance(guess, str):
return False
if len(guess) != 1:
return False
# Bug fix: accept upper- AND lowercase. The original `'a' <= guess <= 'z'`
# rejected every uppercase guess in a "case-insensitive" game.
return ('a' <= guess <= 'z') or ('A' <= guess <= 'Z')
"""Phase 1: case-insensitive secret matching + corrected `is_complete`."""
from typing import List
class RevealState:
"""Hidden-word state, Hangman-style."""
def __init__(self, secret: str):
if not secret:
raise ValueError("secret must be non-empty")
self._secret = secret
self._revealed: List[str] = ['_' for _ in secret]
def apply(self, letter: str) -> int:
"""Reveal every position of `letter` in the secret.
Returns the number of newly-revealed positions. Case-insensitive."""
letter = letter.lower()
count = 0
for i, ch in enumerate(self._secret):
# Bug fix: compare the secret in lowercase so uppercase
# secrets ("APPLE") match lowercase guesses ("p").
if ch.lower() == letter and self._revealed[i] == '_':
self._revealed[i] = letter
count += 1
return count
def display(self) -> str:
"""Visible state: revealed letters with underscores for unknown."""
return ' '.join(self._revealed)
def is_complete(self) -> bool:
"""True iff every position has been revealed."""
# Bug fix: the original `'_' in self._revealed` returned True
# exactly when the word still had blanks. Logic was inverted.
return '_' not in self._revealed
def secret(self) -> str:
return self._secret
Sign in to join the discussion