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", "⌫")}
);
})}