From 053242dc0bcf1d277a7a3b04870a7a26a65efa4b Mon Sep 17 00:00:00 2001 From: Lynn Date: Sat, 1 Jan 2022 19:14:50 +0100 Subject: [PATCH] win/lose feedback, mobile kb style --- src/App.css | 28 +++++++++++++++++++++++++--- src/App.tsx | 14 +++++++++----- src/Game.tsx | 38 ++++++++++++++++++++++++++++---------- src/Keyboard.tsx | 5 ++++- 4 files changed, 66 insertions(+), 19 deletions(-) diff --git a/src/App.css b/src/App.css index e440348..2999903 100644 --- a/src/App.css +++ b/src/App.css @@ -25,6 +25,19 @@ body { font-weight: bold; } +.App { + display: flex; + flex-direction: column; + max-width: 500px; + margin: 0 auto; + justify-content: center; +} + +.Game { + display: flex; + flex-direction: column; +} + .Game-keyboard { display: flex; flex-direction: column; @@ -33,22 +46,31 @@ body { .Game-keyboard-row { display: flex; flex-direction: row; - justify-content: center; + justify-content: stretch; } .Game-keyboard-button { margin: 2px; background-color: #cdcdcd; - padding: 4px; + padding: 2px; text-transform: capitalize; border-radius: 4px; - min-width: 25px; + min-height: 40px; + display: flex; + flex: 1; + align-items: center; + justify-content: center; + font-size: 20px; color: inherit; text-decoration: inherit; border: inherit; cursor: pointer; } +.Game-keyboard-button-wide { + flex: 2; +} + .Game-keyboard-button:focus { outline: none; } diff --git a/src/App.tsx b/src/App.tsx index 1b3619b..5eed5d8 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -26,20 +26,24 @@ function App() {

hello wordl

{ - setTarget(randomTarget(Number(e.target.value))); - setWordLength(Number(e.target.value)); + const length = Number(e.target.value); + setTarget(randomTarget(length)); + setWordLength(length); }} >
{ + setTarget(randomTarget(wordLength)); + }} />
diff --git a/src/Game.tsx b/src/Game.tsx index 7f6e42e..11f294a 100644 --- a/src/Game.tsx +++ b/src/Game.tsx @@ -6,23 +6,31 @@ import { Keyboard } from "./Keyboard"; enum GameState { Playing, - Over, + Won, + Lost, } interface GameProps { target: string; wordLength: number; maxGuesses: number; + restart: () => void; } function Game(props: GameProps) { const [gameState, setGameState] = useState(GameState.Playing); const [guesses, setGuesses] = useState([]); const [currentGuess, setCurrentGuess] = useState(""); + const [hint, setHint] = useState(`${props.wordLength} letters`); const onKey = (key: string) => { console.log(key); - if (gameState !== GameState.Playing) return; + if (gameState !== GameState.Playing) { + if (key === "Enter") { + props.restart(); + } + return; + } if (guesses.length === props.maxGuesses) return; if (/^[a-z]$/.test(key)) { setCurrentGuess((guess) => (guess + key).slice(0, props.wordLength)); @@ -30,15 +38,26 @@ function Game(props: GameProps) { setCurrentGuess((guess) => guess.slice(0, -1)); } else if (key === "Enter") { if (currentGuess.length !== props.wordLength) { - // TODO show a helpful message + setHint("Too short"); return; } if (!dictionary.includes(currentGuess)) { - // TODO show a helpful message + setHint("Not a valid word"); return; } setGuesses((guesses) => guesses.concat([currentGuess])); setCurrentGuess((guess) => ""); + if (currentGuess === props.target) { + setHint("You won! (Enter to play again)"); + setGameState(GameState.Won); + } else if (guesses.length + 1 === props.maxGuesses) { + setHint( + `You lost! The answer was ${props.target.toUpperCase()}. (Enter to play again)` + ); + setGameState(GameState.Lost); + } else { + setHint(""); + } } }; @@ -46,14 +65,11 @@ function Game(props: GameProps) { const onKeyDown = (e: KeyboardEvent) => { onKey(e.key); }; - document.addEventListener("keydown", onKeyDown); - return () => { document.removeEventListener("keydown", onKeyDown); }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [currentGuess]); + }, [currentGuess, gameState]); let letterInfo = new Map(); const rowDivs = Array(props.maxGuesses) @@ -61,7 +77,8 @@ function Game(props: GameProps) { .map((_, i) => { const guess = [...guesses, currentGuess][i] ?? ""; const cluedLetters = clue(guess, props.target); - if (i < guesses.length) { + const lockedIn = i < guesses.length; + if (lockedIn) { for (const { clue, letter } of cluedLetters) { if (clue === undefined) break; const old = letterInfo.get(letter); @@ -74,7 +91,7 @@ function Game(props: GameProps) { ); @@ -83,6 +100,7 @@ function Game(props: GameProps) { return (
{rowDivs} +

{hint || `\u00a0`}

); diff --git a/src/Keyboard.tsx b/src/Keyboard.tsx index 50b27d8..ceb1c24 100644 --- a/src/Keyboard.tsx +++ b/src/Keyboard.tsx @@ -22,6 +22,9 @@ export function Keyboard(props: KeyboardProps) { if (clue !== undefined) { className += " " + clueClass(clue); } + if (label.length > 1) { + className += " Game-keyboard-button-wide"; + } return (
- {label} + {label.replace("Backspace", "⌫")}
); })}