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

React井字棋游戏官方示例

在本篇技术博客中,我们将介绍一个React官方示例:井字棋游戏。我们将逐步讲解代码实现,包括游戏的组件结构、状态管理、胜者判定以及历史记录功能。让我们一起开始吧!

项目概览

在这个井字棋游戏中,我们有以下组件:

  1. Square组件:表示游戏棋盘上的每一个方格。
  2. Board组件:表示游戏的棋盘,包含了多个Square组件。
  3. Game组件:表示整个游戏的容器,包含了游戏状态的管理和历史记录功能。

Square组件

Square组件表示游戏棋盘上的每一个方格。代码如下:

function Square({ value, onSquareClick }) {return (<button className="square" onClick={onSquareClick}>{value}</button>);
}

Square组件接收两个props:valueonSquareClickvalue表示当前方格的取值('X'、'O'或null),onSquareClick是一个点击事件处理函数。当方格被点击时,onSquareClick将会被触发。

Board组件

Board组件表示整个游戏的棋盘,包含了多个Square组件。代码如下:

function Board({ xIsNext, squares, onPlay }) {function handleClick(i) {if (calculateWinner(squares) || squares[i]) {return;}const nextSquares = squares.slice();if (xIsNext) {nextSquares[i] = 'X';} else {nextSquares[i] = 'O';}onPlay(nextSquares);}const winner = calculateWinner(squares);let status;if (winner) {status = 'Winner: ' + winner;} else {status = 'Next player: ' + (xIsNext ? 'X' : 'O');}return (<><div className="status">{status}</div><div className="board-row"><Square value={squares[0]} onSquareClick={() => handleClick(0)} /><Square value={squares[1]} onSquareClick={() => handleClick(1)} /><Square value={squares[2]} onSquareClick={() => handleClick(2)} /></div><div className="board-row"><Square value={squares[3]} onSquareClick={() => handleClick(3)} /><Square value={squares[4]} onSquareClick={() => handleClick(4)} /><Square value={squares[5]} onSquareClick={() => handleClick(5)} /></div><div className="board-row"><Square value={squares[6]} onSquareClick={() => handleClick(6)} /><Square value={squares[7]} onSquareClick={() => handleClick(7)} /><Square value={squares[8]} onSquareClick={() => handleClick(8)} /></div></>);
}

Board组件接收三个props:xIsNextsquaresonPlayxIsNext表示当前轮到哪个玩家下棋('X'或'O'),squares是一个数组,表示游戏的棋盘状态,每个元素为方格的取值。onPlay是一个函数,用于更新游戏的棋盘状态。

Board组件内部定义了handleClick函数,用于处理方格的点击事件。若游戏已经有胜者或方格已经被占用,则不进行任何操作。否则,根据当前的玩家('X'或'O'),更新方格的取值,然后调用onPlay函数更新游戏状态。

Board组件还根据当前的棋盘状态判断游戏的状态,并将其显示在页面上。

Game组件

Game组件是整个游戏的容器,它负责管理游戏的状态和历史记录。代码如下:

export default function Game() {const [history, setHistory] = useState([Array(9).fill(null)]);const [currentMove, setCurrentMove] = useState(0);const xIsNext = currentMove % 2 === 0;const currentSquares = history[currentMove];function handlePlay(nextSquares) {const nextHistory = [...history.slice(0, currentMove + 1), nextSquares];setHistory(nextHistory);setCurrentMove(nextHistory.length - 1);}function jumpTo(nextMove) {setCurrentMove(nextMove);}const moves = history.map((squares, move) => {let description;if (move > 0) {description = 'Go to move #' + move;} else {description = 'Go to game start';}return (<li key={move}><button onClick={() => jumpTo(move)}>{description}</button></li>);});return (<div className="game"><div className="game-board"><Board xIsNext={xIsNext} squares={currentSquares} onPlay={handlePlay} /></div><div className="game-info"><ol>{moves}</ol></div></div>);
}

Game组件使用了useState钩子来管理游戏的状态。history是一个数组,用于保存游戏的历史记录,每个元素是一个表示棋盘状态的数组。currentMove表示当前的步数,xIsNext表示当前轮到哪个玩家下棋('X'或'O'),currentSquares是当前步数对应的棋盘状态。

handlePlay函数用于处理玩家的下棋操作。它会将下一个棋盘状态添加到history中,并更新当前的步数。

jumpTo函数用于跳转到历史记录中的特定步数。

Game组件还渲染了一个历史记录列表,用于显示每一步的操作。点击列表中的按钮可以跳转到对应的历史记录步数。

辅助函数 calculateWinner

最后,我们还有一个辅助函数 calculateWinner,用于判断游戏是否有胜者。代码如下:

function calculateWinner(squares) {const lines = [[0, 1, 2],[3, 4, 5],[6, 7, 8],[0, 3, 6],[1, 4, 7],[2, 5, 8],[0, 4, 8],[2, 4, 6],];for (let i = 0; i < lines.length; i++) {const [a, b, c] = lines[i];if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {return squares[a];}}return null;
}

calculateWinner函数接收一个squares数组,表示游戏的棋盘状态。它遍历一个包含所有获胜情况的数组lines,检查是否有任何一种情况下三个方格的取值相同,如果有则返回该取值('X'或'O'),否则返回null表示没有胜者。

 

总结

在这篇技术博客中,我们详细介绍了React官方示例井字棋游戏。我们了解了游戏的组件结构,实现了游戏状态的管理、胜者判定和历史记录功能。通过这个简单的井字棋游戏,我们学习了React组件之间的通信、状态管理以及如何处理用户交互。

相关文章:

React井字棋游戏官方示例

在本篇技术博客中&#xff0c;我们将介绍一个React官方示例&#xff1a;井字棋游戏。我们将逐步讲解代码实现&#xff0c;包括游戏的组件结构、状态管理、胜者判定以及历史记录功能。让我们一起开始吧&#xff01; 项目概览 在这个井字棋游戏中&#xff0c;我们有以下组件&am…...

七大经典比较排序算法

1. 插入排序 (⭐️⭐️) &#x1f31f; 思想&#xff1a; 直接插入排序是一种简单的插入排序法&#xff0c;思想是是把待排序的数据按照下标从小到大&#xff0c;依次插入到一个已经排好的序列中&#xff0c;直至全部插入&#xff0c;得到一个新的有序序列。例如&#xff1a;…...

【点云处理教程】03使用 Python 实现地面检测

一、说明 这是我的“点云处理”教程的第3篇文章。“点云处理”教程对初学者友好&#xff0c;我们将在其中简单地介绍从数据准备到数据分割和分类的点云处理管道。 在上一教程中&#xff0c;我们在不使用 Open3D 库的情况下从深度数据计算点云。在本教程中&#xff0c;我们将首先…...

Python 日志记录:6大日志记录库的比较

Python 日志记录&#xff1a;6大日志记录库的比较 文章目录 Python 日志记录&#xff1a;6大日志记录库的比较前言一些日志框架建议1. logging - 内置的标准日志模块默认日志记录器自定义日志记录器生成结构化日志 2. Loguru - 最流行的Python第三方日志框架默认日志记录器自定…...

最近遇到一些问题的解决方案

最近遇到一些问题的解决方案 SpringBoot前后端分离参数传递方式总结Java8版本特性讲解idea使用git更新代码 : update project removeAll引发得java.lang.UnsupportedOperationException异常Java的split()函数用多个不同符号分割 Aspect注解切面demo 抽取公共组件&#xff0c;使…...

封装hutool工具生成JWT token

private static final String KEY "abcdef";/*** 生成token** param payload 可以存放用户的一些信息&#xff0c;不要存放敏感字段* return*/public static String createToken(Map<String, Object> payload) {//十分重要&#xff0c;不禁用发布到生产环境无…...

【手机】三星手机刷机解决SecSetupWizard已停止

三星手机恢复出厂设置之后&#xff0c;出现SecSetupWizard已停止的解决方案 零、问题 我手上有一部同学给的三星 GT-S6812I&#xff0c;这几天搞了张新卡&#xff0c;多余出的卡就放到这个手机上玩去了。因为是获取了root权限的&#xff08;直接使用KingRoot就可以&#xff0…...

GDAL C++ API 学习之路 OGRGeometry 抽象曲线基类 OGRCurve

OGRCurve class "ogrsf_frmts.h" OGRCurve 是 OGR&#xff08;OpenGIS Simple Features Reference Implementation&#xff09;几何库中的一个基类&#xff0c;表示曲线几何对象。它是 OGRLineString 和 OGRCircularString 的抽象基类&#xff0c;用于表示曲…...

etcd底层支持的数据库有哪些

etcd底层的数据库可以更换。在当前版本的etcd中&#xff0c;它使用的是BoltDB作为默认的后端存储引擎。但是&#xff0c;etcd提供了接口允许您更换数据库后端&#xff0c;以便根据需要选择更合适的存储引擎。 以下是etcd支持的一些后端数据库选项&#xff1a; BoltDB&#xff…...

linux设备驱动的poll与fasync

什么是fasync 在 Linux 驱动程序中&#xff0c;fasync 是一种机制&#xff0c;用于在异步事件发生时通知进程。它允许进程在等待设备事件时&#xff0c;不必像传统的轮询方式那样持续地查询设备状态。 具体来说&#xff0c;当进程调用 fcntl(fd, F_SETFL, O_ASYNC) 函数时&am…...

TortoiseGit安装与配置

注&#xff1a;在安装TortoiseGit之前我已经安装了git工具。 二、Git的诞生及环境配置_tortoisegit安装包_朱嘉鼎的博客-CSDN博客 1、TortoiseGit简介 TortoiseGit是基于TortoiseSVN的Git版本的Windows Shell界面。它是开源的&#xff0c;可以完全免费使用。 TortoiseGit 支持…...

Java代码打印空心菱形(小练习)

回看基础 利用Java代码打印一个空心菱形 //5. 打印空心菱形 import java.util.Scanner; public class MulForExercise01 {//编写一个 main 方法public static void main(String[] args) {Scanner myScanner new Scanner(System.in);System.out.println("请输入正三角的行…...

【性能优化】MySQL百万数据深度分页优化思路分析

业务场景 一般在项目开发中会有很多的统计数据需要进行上报分析&#xff0c;一般在分析过后会在后台展示出来给运营和产品进行分页查看&#xff0c;最常见的一种就是根据日期进行筛选。这种统计数据随着时间的推移数据量会慢慢的变大&#xff0c;达到百万、千万条数据只是时间问…...

交叉编译工具链的安装、配置、使用

一、交叉编译的概念 交叉编译是在一个平台上生成另一个平台上的可执行代码。 编译&#xff1a;一个平台上生成在该平台上的可执行文件。 例如&#xff1a;我们的Windows上面编写的C51代码&#xff0c;并编译成可执行的代码&#xff0c;如xx.hex.在C51上面运行。 我们在Ubunt…...

【C++ 进阶】继承

一.继承的定义格式 基类又叫父类&#xff0c;派生类又叫子类&#xff1b; 二.继承方式 继承方式分为三种&#xff1a; 1.public继承 2.protected继承 3.private继承 基类成员与继承方式的关系共有9种&#xff0c;见下表&#xff1a; 虽然说是有9种&#xff0c;但其实最常用的还…...

Git使用详细教程

1. cmd面板的常用命令 clear&#xff1a;清屏cd 文件夹名称----进入文件夹cd … 进入上一级目录(两个点)dir 查看当前目录下的文件和文件夹(全拼:directory)Is 查看当前目录下的文件和文件夹touch 文件名----创建文件echo 内容 > 创建文件名----创建文件并写入内容rm 文件名…...

小程序 表单验证

使用 WxValidate.js 插件来校验表单数据 常用实例方法 名称返回类型描述checkForm(e)boolean验证所有字段的规则&#xff0c;返回验证是否通过。valid()boolean返回验证是否通过。size()number返回错误信息的个数。validationErrors()array返回所有错误信息。addMethod(name…...

本地仓库推送至远程仓库

1. 本地生成ssh密钥对 ssh-keygen -t rsa -C 邮箱2. 添加公钥到gitlab/github/gitee上 打开C:\Users\用户名\.ssh目录下生成的密钥文件id_rsa.pub&#xff0c;把内容复制到如下文本框中 删除Expiration date显示的日期&#xff0c;公钥有效期变成永久&#xff0c;之后点Add K…...

【Unity2D】角色动画的切换

动画状态转换 第一种方法是设置一个中间状态&#xff0c;从中间状态向其余各种状态切换&#xff0c;且各状态向其他状态需要设置参数 实现动作转移时右键点击Make Transition即可 实现动画转移需要设置条件 点击一种动画到另一种动画的线 &#xff0c;然后点击加号添加Condi…...

【MATLAB第62期】基于MATLAB的PSO-NN、BBO-NN、前馈神经网络NN回归预测对比

【MATLAB第62期】基于MATLAB的PSO-NN、BBO-NN、前馈神经网络NN回归预测对比 一、数据设置 1、7输入1输出 2、103行样本 3、80个训练样本&#xff0c;23个测试样本 二、效果展示 NN训练集数据的R2为&#xff1a;0.73013 NN测试集数据的R2为&#xff1a;0.23848 NN训练集数据的…...

新手学习Linux系统的11点建议

随着Linux应用的扩展许多朋友开始接触Linux&#xff0c;根据学习Windwos的经验往往有一些茫然的感觉&#xff1a;不知从何处开始学起。这里介绍学习Linux的一些建议。一、从基础开始&#xff1a;常常有些朋友在Linux论坛问一些问题&#xff0c;不过&#xff0c;其中大多数的问题…...

TikTok客户端关键字符串追踪与ttencrypt协议解析

1. 这不是“破解”&#xff0c;而是协议层的工程化还原很多人看到“TikTok算法逆向”第一反应是&#xff1a;这得用IDA Pro硬啃SO文件、在ARM汇编里找特征码、对着混淆后的Java层反复脱壳——其实大错特错。我过去三年深度参与过5个主流短视频App的客户端通信分析项目&#xff…...

GEO工具红黑榜:有的在“监测“,有的在“收智商税“

2026年&#xff0c;AI搜索已承接超过40%的传统搜索查询量&#xff0c;品牌面临的不再是"百度一下"的竞价排名&#xff0c;而是AI助手直接给出的"默认答案"。当用户问ChatGPT"推荐一款面霜"或向豆包询问"哪个在线教育平台更好"时&#…...

c#string字符串

//API 应用程序接口 内置函数 //字符串的属性 string a "abcd";//表示字符串中 字符的个数Console.WriteLine(a.Length);//字符串是可以通过 索引 取值的 因为string类内部顶一个一个索引器char c a[2];Console.WriteLine(c);string s1 "abc";st…...

渗透测试小白上手指南:系统化故障排查能力迁移手册

1. 别被“渗透测试”四个字吓住&#xff1a;它本质是系统化的故障排查能力很多人第一次听说“渗透测试”&#xff0c;脑子里立刻浮现出黑客电影里飞速滚动的代码、黑底绿字的终端、几秒钟攻破银行防火墙的炫酷场面。结果一搜学习资料&#xff0c;满屏都是“Kali Linux”“Metas…...

【紧急预警】2025年起Steam/Epic将强制要求AI生成内容标注——游戏公司AI Agent内容溯源方案已迫在眉睫

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;AI Agent游戏行业应用的监管变局与战略意义 近年来&#xff0c;AI Agent在游戏开发、智能NPC行为建模、动态剧情生成及玩家个性化体验优化等领域加速落地&#xff0c;引发全球监管机构高度关注。欧盟《…...

ComfyUI-Custom-Scripts自动完成终极指南:如何快速提升AI绘画提示词效率

ComfyUI-Custom-Scripts自动完成终极指南&#xff1a;如何快速提升AI绘画提示词效率 【免费下载链接】ComfyUI-Custom-Scripts Enhancements & experiments for ComfyUI, mostly focusing on UI features 项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI-Custom-Sc…...

深入解析CPU L1/L2缓存:原理、性能影响与编程优化实战

1. 项目概述&#xff1a;从“快”字说起做性能调优或者写高性能代码的朋友&#xff0c;对“缓存”这个词一定不陌生。我们总在说&#xff0c;把数据放进缓存里&#xff0c;访问就快了。但缓存本身&#xff0c;尤其是离CPU核心最近的一级缓存&#xff08;L1 Cache&#xff09;和…...

构建中文AI的未来:MNBVC超大规模语料库的深度解析与实践指南

构建中文AI的未来&#xff1a;MNBVC超大规模语料库的深度解析与实践指南 【免费下载链接】MNBVC MNBVC(Massive Never-ending BT Vast Chinese corpus)超大规模中文语料集。对标chatGPT训练的40T数据。MNBVC数据集不但包括主流文化&#xff0c;也包括各个小众文化甚至火星文的数…...

Python通达信数据接口深度解析:5大核心模块构建金融数据生态

Python通达信数据接口深度解析&#xff1a;5大核心模块构建金融数据生态 【免费下载链接】mootdx 通达信数据读取的一个简便使用封装 项目地址: https://gitcode.com/GitHub_Trending/mo/mootdx 在前100个字内&#xff0c;Python通达信数据接口为你提供了一个免费、高效…...