当前位置: 首页 > news >正文

wordle game(猜词游戏)小demo【react + ts】

wordle game(猜词游戏)小demo。

绿色代表字母对位置对,黄色代表字母对位置错,灰色是都错。

源码地址

play~

preview

#1 - init

#2 - using json-server

创建db.json文件,录入需要mock的json数据。

npm install json-server
json-server ./data/db.json [--port 3001]

#3 - Making a Wordle Hook

import { useState } from 'react'type LetterColor = 'green' | 'yellow' | 'grey'type LetterObject = {key: stringcolor: LetterColor
}type UseWordleReturn = {turn: numbercurrentGuess: stringguesses: LetterObject[][]isCorrect: booleanhandleKeyup: (event: KeyboardEvent) => void
}const useWordle = (solution: string): UseWordleReturn => {const [turn, setTurn] = useState<number>(0)const [currentGuess, setCurrentGuess] = useState<string>('')const [guesses, setGuesses] = useState<LetterObject[][]>([])const [history, setHistory] = useState<string[]>([])const [isCorrect, setIsCorrect] = useState<boolean>(false)// format a guess into an array of letter objects // e.g. [{key: 'a', color: 'yellow'}]const formatGuess = (): LetterObject[] => {// TODO: 实现格式化逻辑return []}// add a new guess to the guesses state// update the isCorrect state if the guess is correct// add one to the turn stateconst addNewGuess = () => {// TODO: 实现添加新猜测逻辑}// handle keyup event & track current guess// if user presses enter, add the new guessconst handleKeyup = ({key} : KeyboardEvent) => {// todo:处理按键响应}return { turn, currentGuess, guesses, isCorrect, handleKeyup }
}export default useWordle

#4 - Tracking the Current Guess

  // handle keyup event & track current guess// if user presses enter, add the new guessconst handleKeyup = ({key} : KeyboardEvent) => {console.log('key pressed - ' + key)if (key === 'Backspace') {setCurrentGuess((prev) => prev.slice(0, -1))return}if (/^[A-Za-z]$/.test(key)) {// 如果按下的是字母键,则添加到currentGuessif (currentGuess.length < 5) {setCurrentGuess((prev) => prev + key.toLowerCase())}}}

#5 - Submitting Guesses

const handleKeyup = ({key} : KeyboardEvent) => {// console.log('key pressed - ' + key)if (key === 'Enter') {if (turn >= 6) {console.log('You have used all your guesses.')return}if (currentGuess.length !== 5) {console.log('Current guess must be 5 characters long.')return}if (history.includes(currentGuess)) {console.log('You have already guessed that word.')return}const formatted = formatGuess()console.log('formatted guess: ', formatted)}if (key === 'Backspace') {setCurrentGuess((prev) => prev.slice(0, -1))return}if (/^[A-Za-z]$/.test(key)) {// 如果按下的是字母键,则添加到currentGuessif (currentGuess.length < 5) {setCurrentGuess((prev) => prev + key.toLowerCase())}}}

#6 - Checking & Formatting Guesses

  const formatGuess = (): LetterObject[] => {// console.log('formatting guess for ' + currentGuess)let solutionArray : (string | null)[] = [...solution]const formattedGuess: LetterObject[] = currentGuess.split('').map((letter) => {return { key: letter, color: 'grey' }})// find all green lettersformattedGuess.forEach((letterObject, index) => {if (letterObject.key === solutionArray[index]) {letterObject.color = 'green'solutionArray[index] = null // remove from solutionArray so we don't match it again}})// find all yellow lettersformattedGuess.forEach((letterObject) => {if (letterObject.color === 'green') return // skip already matched lettersconst letterIndex = solutionArray.indexOf(letterObject.key)if (letterIndex > -1) {letterObject.color = 'yellow'solutionArray[letterIndex] = null // remove from solutionArray so we don't match it again}})return formattedGuess}

#7 - Adding New Guesses

  // add a new guess to the guesses state// update the isCorrect state if the guess is correct// add one to the turn stateconst addNewGuess = (formattedGuess: LetterObject[]) => {if (currentGuess === solution) {setIsCorrect(true)} // console.log('adding new guess: ', formattedGuess)setGuesses(prevGuesses => [...prevGuesses,formattedGuess])setHistory(prevHistory => [...prevHistory,currentGuess])setCurrentGuess('')setTurn(prevTurn => prevTurn + 1)}

#8 - Creating a Game Grid

import { Row } from "./Row"
import type { LetterObject } from "../hooks/useWordle" // Adjust the path if neededtype GridProps = {guesses: LetterObject[][]currentGuess: stringturn: number
}const Grid = ({guesses, currentGuess, turn} : GridProps) => {return (<div className="grid">{guesses.map((guess, index) => {return <Row key={index}></Row>})}</div>)
}export default Grid
export const Row = () => {return (<div className="row"><div></div><div></div><div></div><div></div><div></div><div></div></div>)
}

#9 - Showing Past Guesses

import type { LetterObject } from "../hooks/useWordle"type RowProps = {guess?: LetterObject[]
}export const Row = ({ guess }: RowProps) => {if (guess) {return (<div className="row">{guess.map((letter, index) => {return <div key={index} className={letter.color}>{letter.key}</div>})}</div>)}return (<div className="row"><div></div><div></div><div></div><div></div><div></div></div>)
}

#10 - Showing the Current Guess

import type { LetterObject } from "../hooks/useWordle"type RowProps = {guess?: LetterObject[]currentGuess?: string
}export const Row = ({ guess, currentGuess }: RowProps) => {...if (currentGuess) {let letters = currentGuess.split('')return (<div className="row current">{letters.map((letter, index) => {return <div key={index} className="current">{letter}</div>})}{/* Fill the rest of the row with empty divs */}{Array.from({ length: 5 - letters.length }).map((_, index) => (<div key={index}></div>))}</div>)}...
}

#11 - Animating Tiles

.row > div.green {--background: #5ac85a;--border-color: #5ac85a;animation: flip 0.5s ease forwards;
}
.row > div.grey {--background: #a1a1a1;--border-color: #a1a1a1;animation: flip 0.6s ease forwards;
}
.row > div.yellow {--background: #e2cc68;--border-color: #e2cc68;animation: flip 0.5s ease forwards;
}
.row > div:nth-child(2) {animation-delay: 0.2s;
}
.row > div:nth-child(3) {animation-delay: 0.4s;
}
.row > div:nth-child(4) {animation-delay: 0.6s;
}
.row > div:nth-child(5) {animation-delay: 0.8s;
}
.row.current > div.filled {animation: bounce 0.2s ease-in-out forwards;
}/* keyframe animations */
@keyframes flip {0% {transform: rotateX(0);background: #fff;border-color: #333;}45% {transform: rotateX(90deg);background: white;border-color: #333;}55% {transform: rotateX(90deg);background: var(--background);border-color: var(--border-color);}100% {transform: rotateX(0deg);background: var(--background);border-color: var(--border-color);color: #eee;}
}@keyframes bounce {0% { transform: scale(1);border-color: #ddd;}50% { transform: scale(1.2);}100% {transform: scale(1);border-color: #333;}
}

#12 - Making a Keypad

import { useEffect, useState } from "react";export const Keypad = () => {const [letters, setLetters] = useState<string[]>([]);useEffect(() => {const fetchLetters = async () => {const response = await fetch("/mock/db.json");const data = await response.json();setLetters(data.letters.map((letter: { key: string }) => letter.key));};fetchLetters();}, []);return (<div className="keypad">{letters &&letters.map((letter, index) => <div key={index}>{letter}</div>)}</div>);
};

#13 - Coloring Used Keys

import { useEffect, useState } from "react";
import type { LetterColor } from "../hooks/useWordle";type KeypadProps = {usedKeys: { [key: string]: LetterColor }; // to track used keys and their colors
};export const Keypad = ({ usedKeys }: KeypadProps) => {...return (<div className="keypad">{letters &&letters.map((letter, index) => {const color = usedKeys[letter];return (<div key={index} className={color}>{letter}</div>);})}</div>);
};

#14 - Ending A Game

...export default function Wordle({ solution }: { solution: string }) {const { currentGuess, handleKeyup, guesses, isCorrect, turn, usedKeys } =useWordle(solution);useEffect(() => {window.addEventListener("keyup", handleKeyup);if (isCorrect) {console.log("Congratulations! You've guessed the word!");window.removeEventListener("keyup", handleKeyup);}if (turn >= 6 && !isCorrect) {console.log("Game over! The correct word was: " + solution);window.removeEventListener("keyup", handleKeyup);}return () => {window.removeEventListener("keyup", handleKeyup);};}, [handleKeyup]);...
}

#15 - Making a Modal

import React from 'react'type ModalProps = {isCorrect: booleansolution: stringturn: number
}const Modal = ({ isCorrect, solution, turn }: ModalProps) => {return (<div className='modal'>{isCorrect ? (<div><h2>Congratulations!</h2><p>You guessed the word "{solution}" in {turn + 1} turns!</p></div>) : (<div><h2>Game Over</h2><p>The correct word was "{solution}". Better luck next time!</p></div>)}<button onClick={() => window.location.reload()}>Play Again</button></div>)
}export default Modal
http://www.lryc.cn/news/594563.html

相关文章:

  • 搭建种草商城框架指南
  • Protein FID:AI蛋白质结构生成模型评估新指标
  • MCP协议解析:如何通过Model Context Protocol 实现高效的AI客户端与服务端交互
  • 基础神经网络模型搭建
  • 【Linux】3. Shell语言
  • 双8无碳小车“cad【17张】三维图+设计说名书
  • XTTS实现语音克隆:精确控制音频格式与生成流程【TTS的实战指南】
  • XSS GAME靶场
  • 仙盟数据库应用-外贸标签打印系统 前端数据库-V8--毕业论文-—-—仙盟创梦IDE
  • Apache基础配置
  • ESMFold 安装教程
  • 深度相机的工作模式(以奥比中光深度相机为例)
  • 近期工作感想:职业规划篇
  • 【RAG Agent】Deep Searcher实现逻辑解析
  • 尚庭公寓--------登陆流程介绍以及功能代码
  • Linux:线程控制
  • API获取及调用(以豆包为例实现图像分析)
  • 《计算机网络》实验报告三 UDP协议分析
  • 单线程 Reactor 模式
  • 【PyTorch】图像二分类项目
  • SSE和WebSocket区别到底是什么
  • 渗透笔记(XSS跨站脚本攻击)
  • `MYSQL`、`MYSQL_RES` 和 `MYSQL_FIELD`的含义与使用案例
  • [硬件电路-59]:电源:电子存储的仓库,电能的发生地,电场的动力场所
  • 2025最新 PostgreSQL17 安装及配置(Windows原生版)
  • BST(二叉搜索树)的笔试大题(C语言)
  • 【web安全】SQL注入与认证绕过
  • 【算法300题】:双指针
  • c#转python第四天:生态系统与常用库
  • XSS的介绍