mirror of
https://github.com/sigmasternchen/x86-64-wordle
synced 2025-03-15 08:09:01 +00:00
refactor: Move Game logic to new component
This commit is contained in:
parent
641e476ad6
commit
749057040f
2 changed files with 115 additions and 94 deletions
|
@ -1,111 +1,30 @@
|
||||||
import React, {useState} from "react";
|
import React from "react";
|
||||||
import {Field} from "./Field";
|
|
||||||
import {calculateDifference} from "../logic/game-logic";
|
|
||||||
import {id, objectMap, zip} from "../utils";
|
|
||||||
import {Keyboard} from "./Keyboard";
|
|
||||||
import {CellState, sortCellStates} from "../model/CellState";
|
|
||||||
import {Toast} from "./Toast";
|
|
||||||
import dictionary from "../data/dictionary.json"
|
import dictionary from "../data/dictionary.json"
|
||||||
import {newSFC32} from "../random/sfc32";
|
import {newSFC32} from "../random/sfc32";
|
||||||
import {GameState} from "../model/GameState";
|
import {Game} from "./Game";
|
||||||
|
|
||||||
const validWordsRegex = /[A-Z]+/;
|
const validWordsRegex = /[A-Z]+/;
|
||||||
|
|
||||||
export const App = () => {
|
export const App = () => {
|
||||||
const [gameState, setGameState] = useState(GameState.Active);
|
|
||||||
const [pastGuesses, setPastGuesses] = useState([]);
|
|
||||||
const [currentGuess, setCurrentGuess] = useState("");
|
|
||||||
|
|
||||||
const [message, setMessage] = useState("");
|
|
||||||
|
|
||||||
const wordLength = 5;
|
const wordLength = 5;
|
||||||
const numberOfGuesses = 6;
|
const numberOfGuesses = 6;
|
||||||
const availableWords = dictionary
|
|
||||||
.filter(word => validWordsRegex.test(word))
|
|
||||||
.filter(word => word.length === wordLength);
|
|
||||||
|
|
||||||
const today = Date.now() / 1000 / 60 / 60 / 24;
|
const today = Date.now() / 1000 / 60 / 60 / 24;
|
||||||
const random = newSFC32(today);
|
const random = newSFC32(today);
|
||||||
|
|
||||||
|
|
||||||
|
const availableWords = dictionary
|
||||||
|
.filter(word => validWordsRegex.test(word))
|
||||||
|
.filter(word => word.length === wordLength);
|
||||||
|
|
||||||
const correct = availableWords[Math.floor(random() * availableWords.length)];
|
const correct = availableWords[Math.floor(random() * availableWords.length)];
|
||||||
|
|
||||||
console.log(correct)
|
console.log(correct)
|
||||||
|
|
||||||
const fieldDataForPastGuesses = pastGuesses
|
return <Game
|
||||||
.map(guess => guess.toUpperCase())
|
wordLength={wordLength}
|
||||||
.map(guess => [
|
numberOfGuesses={numberOfGuesses}
|
||||||
guess.split(""),
|
availableWords={availableWords}
|
||||||
calculateDifference(correct.toUpperCase(), guess)
|
correctWord={correct}
|
||||||
])
|
/>
|
||||||
.map(([guess, difference]) => zip(guess, difference))
|
|
||||||
.map(guessWithDifference => guessWithDifference
|
|
||||||
.map(([content, state]) => ({
|
|
||||||
state: state,
|
|
||||||
content: content,
|
|
||||||
}))
|
|
||||||
);
|
|
||||||
|
|
||||||
const usedWithState = objectMap(
|
|
||||||
Object.groupBy(
|
|
||||||
fieldDataForPastGuesses
|
|
||||||
.flatMap(id)
|
|
||||||
.flatMap(id),
|
|
||||||
cell => cell.content
|
|
||||||
),
|
|
||||||
states => states
|
|
||||||
.map(state => state.state)
|
|
||||||
.toSorted(sortCellStates)
|
|
||||||
.at(-1)
|
|
||||||
);
|
|
||||||
|
|
||||||
const inputHandler = key => {
|
|
||||||
if (key === "ENTER") {
|
|
||||||
if (currentGuess.length === wordLength) {
|
|
||||||
if (availableWords.indexOf(currentGuess) === -1) {
|
|
||||||
setMessage("Not in word list.");
|
|
||||||
} else {
|
|
||||||
setPastGuesses(pastGuesses.concat([currentGuess]));
|
|
||||||
setCurrentGuess("");
|
|
||||||
|
|
||||||
if (currentGuess.toUpperCase() === correct.toUpperCase()) {
|
|
||||||
setGameState(GameState.Won);
|
|
||||||
} else {
|
|
||||||
if (pastGuesses.length === numberOfGuesses - 1) {
|
|
||||||
setGameState(GameState.Lost);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setMessage("Not enough letters.");
|
|
||||||
}
|
|
||||||
} else if (key === "BACK") {
|
|
||||||
if (currentGuess.length > 0) {
|
|
||||||
setCurrentGuess(currentGuess.substring(0, currentGuess.length - 1));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (currentGuess.length < wordLength) {
|
|
||||||
setCurrentGuess(currentGuess + key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const fieldData = fieldDataForPastGuesses
|
|
||||||
.concat([currentGuess
|
|
||||||
.split("")
|
|
||||||
.map(char => ({
|
|
||||||
state: CellState.Unknown,
|
|
||||||
content: char,
|
|
||||||
}))
|
|
||||||
])
|
|
||||||
|
|
||||||
return <div>
|
|
||||||
<Field
|
|
||||||
size={[wordLength, numberOfGuesses]}
|
|
||||||
fieldData={fieldData}
|
|
||||||
/>
|
|
||||||
<Keyboard enabled={gameState === GameState.Active} used={usedWithState} onKey={inputHandler}/>
|
|
||||||
<Toast message={message}/>
|
|
||||||
<div className={"result won " + (gameState === GameState.Won ? "show" : "")}>You won!</div>
|
|
||||||
<div className={"result lost " + (gameState === GameState.Lost ? "show" : "")}>You lost!</div>
|
|
||||||
</div>
|
|
||||||
};
|
};
|
102
src/components/Game.jsx
Normal file
102
src/components/Game.jsx
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
import React, {useState} from "react";
|
||||||
|
import {GameState} from "../model/GameState";
|
||||||
|
import {calculateDifference} from "../logic/game-logic";
|
||||||
|
import {id, objectMap, zip} from "../utils";
|
||||||
|
import {CellState, sortCellStates} from "../model/CellState";
|
||||||
|
import {Field} from "./Field";
|
||||||
|
import {Keyboard} from "./Keyboard";
|
||||||
|
import {Toast} from "./Toast";
|
||||||
|
|
||||||
|
export const Game = ({wordLength, numberOfGuesses, correctWord, availableWords, reset}) => {
|
||||||
|
const [gameState, setGameState] = useState(GameState.Active);
|
||||||
|
const [pastGuesses, setPastGuesses] = useState([]);
|
||||||
|
const [currentGuess, setCurrentGuess] = useState("");
|
||||||
|
|
||||||
|
const [message, setMessage] = useState("");
|
||||||
|
|
||||||
|
const fieldDataForPastGuesses = pastGuesses
|
||||||
|
.map(guess => guess.toUpperCase())
|
||||||
|
.map(guess => [
|
||||||
|
guess.split(""),
|
||||||
|
calculateDifference(correctWord.toUpperCase(), guess)
|
||||||
|
])
|
||||||
|
.map(([guess, difference]) => zip(guess, difference))
|
||||||
|
.map(guessWithDifference => guessWithDifference
|
||||||
|
.map(([content, state]) => ({
|
||||||
|
state: state,
|
||||||
|
content: content,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
const usedWithState = objectMap(
|
||||||
|
Object.groupBy(
|
||||||
|
fieldDataForPastGuesses
|
||||||
|
.flatMap(id)
|
||||||
|
.flatMap(id),
|
||||||
|
cell => cell.content
|
||||||
|
),
|
||||||
|
states => states
|
||||||
|
.map(state => state.state)
|
||||||
|
.toSorted(sortCellStates)
|
||||||
|
.at(-1)
|
||||||
|
);
|
||||||
|
|
||||||
|
const inputHandler = key => {
|
||||||
|
if (key === "ENTER") {
|
||||||
|
if (currentGuess.length === wordLength) {
|
||||||
|
if (availableWords.indexOf(currentGuess) === -1) {
|
||||||
|
setMessage("Not in word list.");
|
||||||
|
} else {
|
||||||
|
setPastGuesses(pastGuesses.concat([currentGuess]));
|
||||||
|
setCurrentGuess("");
|
||||||
|
|
||||||
|
if (currentGuess.toUpperCase() === correctWord.toUpperCase()) {
|
||||||
|
setGameState(GameState.Won);
|
||||||
|
} else {
|
||||||
|
if (pastGuesses.length === numberOfGuesses - 1) {
|
||||||
|
setGameState(GameState.Lost);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setMessage("Not enough letters.");
|
||||||
|
}
|
||||||
|
} else if (key === "BACK") {
|
||||||
|
if (currentGuess.length > 0) {
|
||||||
|
setCurrentGuess(currentGuess.substring(0, currentGuess.length - 1));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (currentGuess.length < wordLength) {
|
||||||
|
setCurrentGuess(currentGuess + key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetHandler = () => {
|
||||||
|
setGameState(GameState.Active);
|
||||||
|
setPastGuesses([]);
|
||||||
|
setCurrentGuess("")
|
||||||
|
|
||||||
|
reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
const fieldData = fieldDataForPastGuesses
|
||||||
|
.concat([currentGuess
|
||||||
|
.split("")
|
||||||
|
.map(char => ({
|
||||||
|
state: CellState.Unknown,
|
||||||
|
content: char,
|
||||||
|
}))
|
||||||
|
])
|
||||||
|
|
||||||
|
return <div>
|
||||||
|
<Field
|
||||||
|
size={[wordLength, numberOfGuesses]}
|
||||||
|
fieldData={fieldData}
|
||||||
|
/>
|
||||||
|
<Keyboard enabled={gameState === GameState.Active} used={usedWithState} onKey={inputHandler}/>
|
||||||
|
<Toast message={message}/>
|
||||||
|
<div className={"result won " + (gameState === GameState.Won ? "show" : "")}>You won!</div>
|
||||||
|
<div className={"result lost " + (gameState === GameState.Lost ? "show" : "")}>You lost!</div>
|
||||||
|
</div>
|
||||||
|
}
|
Loading…
Reference in a new issue