当前位置: 首页 > 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.dtcms.com/a/290051.html

相关文章:

  • 子网划分核心原理 (网络原理1)
  • 配置 Nginx 反向代理
  • 微信小程序服务端快速对接指南(java版)
  • 本地生活服务 app 同城信息发布系统搭建
  • 文件的写出操作|文件的追加写入操作|文件操作的综合案例
  • BERT 的“池化策略”
  • 基于SpringBoot和leaflet-timeline-slider的历史叙事GIS展示-以哪吒2的海外国家上映安排为例
  • 技能学习PostgreSQL中级专家
  • 云原生安全工具:数字基础设施的免疫长城
  • 解码视觉体验:视频分辨率、屏幕尺寸、屏幕分辨率与观看距离的科学关系
  • 【Linux庖丁解牛】— 线程控制!
  • iOS 加固工具有哪些?快速发布团队的实战方案
  • 个人中心产品设计指南:从信息展示到用户体验的细节把控
  • SQLite以及Room框架的学习:用SQLite给新闻app加上更完善的登录注册功能
  • Lua:小巧而强大的脚本语言,游戏与嵌入式的秘密武器
  • 遇到偶现Bug(难以复现)怎么处理?
  • uni-app 开发小程序项目中实现前端图片压缩,实现方式
  • taro+pinia+小程序存储配置持久化
  • 健身管理小程序|基于微信开发健身管理小程序的系统设计与实现(源码+数据库+文档)
  • 【Unity基础】Unity中2D和3D项目开发流程对比
  • uni-app开发小程序,根据图片提取主题色值
  • 跑腿小程序|基于微信小程序的跑腿平台小程序设计与实现(源码+数据库+文档)
  • 表单属性总结
  • 常见算法——查找与排序
  • LeafletJS 主题与样式:打造个性化地图
  • 【高精度 带权并集查找 唯一分解定理】 P4079 [SDOI2016] 齿轮|省选-
  • 在血研所(SIH)恢复重建誓师大会上的讲话(by血研所创始所长王振义院士)
  • Stream流-Java
  • 用Dify构建气象智能体:从0到1搭建AI工作流实战指南
  • Redis学习-06渐进式遍历