React 实现五子棋

简介

         本文将会基于React 实现五子棋小游戏,游戏规则为先让5颗棋子连成1线的一方获胜。

实现效果

技术实现

页面布局

<div><table style={{border: '1px solid #000', borderCollapse: 'collapse', backgroundColor: 'lightgray'}}><tbody>{squares.map((row, rowIndex) => {return <tr key={rowIndex}>{row.map((col, colIndex) => {return <td key={colIndex}style={{border: '1px solid #000', width: '30px', height: '30px'}}onClick={(event) => {const clickedElement = event.target as HTMLTableCellElement;const rect = clickedElement.getBoundingClientRect();const x = event.clientX - rect.left;const y = event.clientY - rect.top;const width = clickedElement.getBoundingClientRect().width;const height = clickedElement.getBoundingClientRect().height;const left = x / width;const top = y / height;if (left < 0.5 && top < 0.5){ // 左上if (rowIndex > 0){rowIndex--;}if (colIndex > 0){colIndex--;}}if (left < 0.5 && top > 0.5){ // 左下if (colIndex > 0){colIndex--;}}if (left > 0.5 && top < 0.5){ // 右上if (rowIndex > 0){rowIndex--;}}let item = squares[rowIndex][colIndex];if (item !== '') {return;}if (times % 2 === 0) {item = 'black';} else {item = 'white';}const newSquares = [...squares];newSquares[rowIndex][colIndex] = item;setTimes(times + 1);setSquares(newSquares);}}>{col === 'white' ?<divstyle={{width: '100%',height: '100%',backgroundColor: 'white',borderRadius: '50%',position: "relative",right: "-50%",bottom: "-50%"}}></div>: (col === 'black' ?<divstyle={{width: '100%',height: '100%',backgroundColor: 'black',borderRadius: '50%',position: "relative",right: "-50%",bottom: "-50%"}}></div> : col)}</td>})}</tr>})}</tbody></table></div>

        本文用table实现游戏布局,棋盘大小为15 * 15,背景色为浅灰,棋子为白色或黑色。

        由于棋子是位于交叉点上,需要将table cell 定位到右下角, right - 50%, bottom -50%,

下棋逻辑

onClick={(event) => {const clickedElement = event.target as HTMLTableCellElement;const rect = clickedElement.getBoundingClientRect();const x = event.clientX - rect.left;const y = event.clientY - rect.top;const width = clickedElement.getBoundingClientRect().width;const height = clickedElement.getBoundingClientRect().height;const left = x / width;const top = y / height;if (left < 0.5 && top < 0.5) { // 左上if (rowIndex > 0) {rowIndex--;}if (colIndex > 0) {colIndex--;}}if (left < 0.5 && top > 0.5) { // 左下if (colIndex > 0) {colIndex--;}}if (left > 0.5 && top < 0.5) { // 右上if (rowIndex > 0) {rowIndex--;}}let item = squares[rowIndex][colIndex];if (item !== '') {return;}if (times % 2 === 0) {item = 'black';} else {item = 'white';}const newSquares = [...squares];newSquares[rowIndex][colIndex] = item;setTimes(times + 1);setSquares(newSquares);
}
}

        基于times控制是白方还是黑方,然后更新squares状态,棋盘会根据squares状态进行显示。

        对于每个交叉点,棋子是以交叉点为右下角的table cell。

        计算点击位置位于table cell的哪个区域,然后计算交叉点对应的table cell。

        左上 -> r-- c--

        右上 -> r-- c

        左下 -> r c--

        右下 -> r ,c

获胜逻辑判断

    useEffect(()=>{// 计算dp的值for (let i = 0; i < 15; i++) {for (let j = 0; j < 15; j++) {if (squares[i][j] === '') {continue;}// 判断左边if (j >= 5){let num = 1;for (let k = 1; k < 5; k++) {if (squares[i][j - k] === squares[i][j]) {num++;} else {break;}}if (num >= 5) {alert(squares[i][j] +'win');setSquares(initSquares)setTimes(0);return;}}// 判断上边if (i >= 5){let num = 1;for (let k = 1; k < 5; k++) {if (squares[i - k][j] === squares[i][j]) {num++;} else {break;}}if (num >= 5) {alert(squares[i][j] +'win');setSquares(initSquares)setTimes(0);return;}}// 判断右边if (j <= 10){let num = 1;for (let k = 1; k < 5; k++) {if (squares[i][j + k] === squares[i][j]) {num++;} else {break;}}if (num >= 5) {alert(squares[i][j] +'win');setSquares(initSquares)setTimes(0);return;}}// 判断下边if (i <= 10){let num = 1;for (let k = 1; k < 5; k++){if (squares[i + k][j] === squares[i][j]) {num++;} else {break;}}console.log(i + ',' + j + ':'+ num)if (num >= 5) {alert(squares[i][j] +'win');setSquares(initSquares)setTimes(0);return;}}// 判断左上if (i >= 5 && j >= 5){let num = 1;for (let k = 1; k < 5; k++) {if (squares[i - k][j - k] === squares[i][j]) {num++;} else {break;}}if (num >= 5) {alert(squares[i][j] +'win');setSquares(initSquares)setTimes(0);return;}}// 判断右上if (i <= 10 && j >= 5){let num = 1;for (let k = 1; k < 5; k++) {if (squares[i + k][j - k] === squares[i][j]) {num++;} else {break;}}if (num >= 5) {alert(squares[i][j] +'win');setSquares(initSquares)setTimes(0);return;}}// 判断左下if (i >= 5 && j <= 10){let num = 1;for (let k = 1; k < 5; k++) {if (squares[i - k][j + k] === squares[i][j]) {num++;} else {break;}}if (num >= 5) {alert(squares[i][j] +'win');setSquares(initSquares)setTimes(0);return;}}// 判断右下if (i <= 10 && j <= 10){let num = 1;for (let k = 1; k < 5; k++){if (squares[i + k][j + k] === squares[i][j]) {num++;} else {break;}}if (num >= 5) {alert(squares[i][j] +'win');setSquares(initSquares)setTimes(0);return;}}}}}, [squares])

         判断每个棋子上下左右,左上,右上,左下,右下是否有连续5个棋子。

整体代码

const Board = () => {/*** 创建一个 15 * 15  的棋盘*/const initSquares = Array.from({length: 15},() => new Array(15).fill(''));const [squares, setSquares] = useState(initSquares);const [times, setTimes] = useState(0);useEffect(() => {// 计算dp的值for (let i = 0; i < 15; i++) {for (let j = 0; j < 15; j++) {if (squares[i][j] === '') {continue;}// 判断左边if (j >= 5) {let num = 1;for (let k = 1; k < 5; k++) {if (squares[i][j - k] === squares[i][j]) {num++;} else {break;}}if (num >= 5) {alert(squares[i][j] + '----' + 'win');setSquares(initSquares)setTimes(0);return;}}// 判断上边if (i >= 5) {let num = 1;for (let k = 1; k < 5; k++) {if (squares[i - k][j] === squares[i][j]) {num++;} else {break;}}if (num >= 5) {alert(squares[i][j] + '----' + 'win');setSquares(initSquares)setTimes(0);return;}}// 判断右边if (j <= 10) {let num = 1;for (let k = 1; k < 5; k++) {if (squares[i][j + k] === squares[i][j]) {num++;} else {break;}}if (num >= 5) {alert(squares[i][j] + '----' + 'win');setSquares(initSquares)setTimes(0);return;}}// 判断下边if (i <= 10) {let num = 1;for (let k = 1; k < 5; k++) {if (squares[i + k][j] === squares[i][j]) {num++;} else {break;}}if (num >= 5) {alert(squares[i][j] + '----' + 'win');setSquares(initSquares)setTimes(0);return;}}// 判断左上if (i >= 5 && j >= 5) {let num = 1;for (let k = 1; k < 5; k++) {if (squares[i - k][j - k] === squares[i][j]) {num++;} else {break;}}if (num >= 5) {alert(squares[i][j] + '----' + 'win');setSquares(initSquares)setTimes(0);return;}}// 判断右上if (i <= 10 && j >= 5) {let num = 1;for (let k = 1; k < 5; k++) {if (squares[i + k][j - k] === squares[i][j]) {num++;} else {break;}}if (num >= 5) {alert(squares[i][j] + '----' + 'win');setSquares(initSquares)setTimes(0);return;}}// 判断左下if (i >= 5 && j <= 10) {let num = 1;for (let k = 1; k < 5; k++) {if (squares[i - k][j + k] === squares[i][j]) {num++;} else {break;}}if (num >= 5) {alert(squares[i][j] + '----' + 'win');setSquares(initSquares)setTimes(0);return;}}// 判断右下if (i <= 10 && j <= 10) {let num = 1;for (let k = 1; k < 5; k++) {if (squares[i + k][j + k] === squares[i][j]) {num++;} else {break;}}if (num >= 5) {alert(squares[i][j] + '----' + 'win');setSquares(initSquares)setTimes(0);return;}}}}}, [squares])return <div><table style={{border: '1px solid #000', borderCollapse: 'collapse', backgroundColor: 'lightgray'}}><tbody>{squares.map((row, rowIndex) => {return <tr key={rowIndex}>{row.map((col, colIndex) => {return <td key={colIndex}style={{border: '1px solid #000', width: '30px', height: '30px'}}onClick={(event) => {const clickedElement = event.target as HTMLTableCellElement;const rect = clickedElement.getBoundingClientRect();const x = event.clientX - rect.left;const y = event.clientY - rect.top;const width = clickedElement.getBoundingClientRect().width;const height = clickedElement.getBoundingClientRect().height;const left = x / width;const top = y / height;if (left < 0.5 && top < 0.5) { // 左上if (rowIndex > 0) {rowIndex--;}if (colIndex > 0) {colIndex--;}}if (left < 0.5 && top > 0.5) { // 左下if (colIndex > 0) {colIndex--;}}if (left > 0.5 && top < 0.5) { // 右上if (rowIndex > 0) {rowIndex--;}}let item = squares[rowIndex][colIndex];if (item !== '') {return;}if (times % 2 === 0) {item = 'black';} else {item = 'white';}const newSquares = [...squares];newSquares[rowIndex][colIndex] = item;setTimes(times + 1);setSquares(newSquares);}}>{col === 'white' ?<divstyle={{width: '100%',height: '100%',backgroundColor: 'white',borderRadius: '50%',position: "relative",right: "-50%",bottom: "-50%"}}></div>: (col === 'black' ?<divstyle={{width: '100%',height: '100%',backgroundColor: 'black',borderRadius: '50%',position: "relative",right: "-50%",bottom: "-50%"}}></div> : col)}</td>})}</tr>})}</tbody></table></div>
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/46546.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

普中51单片机:定时器与计数器详解及应用(七)

文章目录 引言定时器工作原理TMOD定时器/计数器工作模式寄存器定时器工作模式模式0(13位定时器/计数器)模式1(16位定时器/计数器)模式2(8位自动重装模式)模式3(两个8位计数器) 定时器配置流程代码演示——LED1间隔1秒闪烁代码演示——按键1控制LED流水灯状态代码演示——LCD160…

GaussDB DWS 详解

文章目录 GaussDB DWS 详解一、简介二、DWS的分布式架构架构概述关键组件 三、分布式查询数据查询流程SQL执行的示例 批注&#xff1a;本文引鉴了Forlogen博主的一些内容&#xff0c;并加以补充&#xff0c;以供学习了解。 GaussDB DWS 详解 一、简介 DWS(Data Warehouse Ser…

免费分享一套SpringBoot+Vue农产品在线销售(在线商城)管理系统【论文+源码+SQL脚本】,帅呆了~~

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringBootVue农产品在线销售(在线商城)管理系统&#xff0c;分享下哈。 项目介绍 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发…

alike-cpp 编译

1. 源码链接&#xff1a; https://github.com/Shiaoming/ALIKE-cpp 2.已经安装好显卡驱动&#xff0c;cuda&#xff0c;cudnn,没安装的参考&#xff1a; 切记装cuda-11.x的版本&#xff0c;最好cuda11.3的版本 ubuntu重装系统后&#xff0c;安装cuda,cudnn-CSDN博客 3.安装…

C++客户端Qt开发——信号和槽

三、信号和槽 1.信号和槽概述 在Qt中&#xff0c;用户和控件的每次交互过程称为一个事件。比如"用户点击按钮”是一个事件&#xff0c;"用户关闭窗口”也是一个事件。每个事件都会发出一个信号&#xff0c;例如用户点击按钮会发出"按钮被点击"的信号&…

在互联网供应链系统可能是永远不会过时的系统

一、前言 在互联网在到人工智能&#xff0c;从基本的门户网站&#xff0c;社交网站&#xff0c;到移动互联网&#xff0c;视频网站&#xff0c;再到现在比较火爆短视频直播和人工智能AI&#xff0c;大模型。互联网的迭代&#xff0c;出现了无数的系统。但是有些系统一直久经不…

剪画小程序:做自媒体要做哪些准备!

在这个数字化的时代&#xff0c;自媒体成为了许多人展现自我、实现价值的舞台。如果你是一个自媒体小白&#xff0c;怀揣着梦想和热情准备踏上这条充满挑战与机遇的道路&#xff0c;那么在出发之前&#xff0c;有一些关键的准备工作可不能忽视。 一、明确自身定位 首先要思考的…

婚恋交友语音交友小程序APP系统开发

在数字化时代&#xff0c;婚恋交友的方式也日益多样化。传统的相亲、朋友介绍等方式已经无法满足现代人快节毒的生活需求&#xff0c;更多的人开始选择通过线上平台寻找自己的另-婚恋交友语音交友小程序APP应运而生&#xff0c;为单身男女提供了个便捷、高效的交友平台。本文将…

指针!!C语言(第一篇)

指针1 指针变量和地址1.取地址操作符(&)2.指针变量和解引用操作符(*) 指针变量的大小和类型指针的运算特殊指针1.viod*指针2.const修饰指针3.野指针 assert断言指针的使用和传址调用1.strlen的模拟实现2.传值调用和传址调用 指针变量和地址 在认识指针之前&#xff0c;我们…

Iceberg概念和特性

1. 快照 Iceberg会随着时间的推进,跟踪表生命周期中的所有数据集变化,并使用快照(Snapshots)来表示每一次变化后的数据集合,每一次数据操作的事务提交均会产生一个快照,并将其记录在元数据文件(Metadata)中。 基于快照的概念,Iceberg有以下特性: 事务性:写入快照成…

26.6 Django模型层

1. 模型层 1.1 模型层的作用 模型层(Model Layer)是MVC或MTV架构中的一个核心组成部分, 它主要负责定义和管理应用程序中的数据结构及其行为. 具体职责包括: * 1. 封装数据: 模型层封装了应用程序所需的所有数据, 这些数据以结构化的形式存在, 如数据库表, 对象等. * 2. 数据…

昇思25天学习打卡营第7天 | MindNLP ChatGLM-6B StreamChat

本案例基于MindNLP和ChatGLM-6B实现一个聊天应用。 1 环境配置 %%capture captured_output # 实验环境已经预装了mindspore2.2.14&#xff0c;如需更换mindspore版本&#xff0c;可更改下面mindspore的版本号 !pip uninstall mindspore -y !pip install -i https://pypi.mi…

前端:Vue学习-1

前端:Vue学习-1 1. 指令1. 指令修饰符2. v-bind对样式控制的增强3. v-model应用于其他表单元素 2. 计算属性3. watch侦听器&#xff08;监视器&#xff09; 1. 指令 就是带有v-前缀的特殊属性&#xff0c;不同属性对应不同的功能 v-html&#xff1a;动态设置页面的html标签内容…

超时导致SparkContext构造失败的问题探究

文章目录 1.前言2. 基于事故现场对问题进行分析2.1 日志分析2.2 单独测试Topology代码试图重现问题 3. 源码解析3.1 Client模式和Cluster模式下客户端的提交和启动过程客户端提交时在两种模式下的处理逻辑ApplicationMaster启动时在两种模式下的处理逻辑 3.2 两种模式下的下层角…

08-8.4.1 简单选择排序+8.4.2 堆排序

&#x1f44b; Hi, I’m Beast Cheng &#x1f440; I’m interested in photography, hiking, landscape… &#x1f331; I’m currently learning python, javascript, kotlin… &#x1f4eb; How to reach me --> 458290771qq.com 喜欢《数据结构》部分笔记的小伙伴可以…

Adminer-CVE-2021-21311

在其4.0.0到4.7.9版本之间&#xff0c;连接 ElasticSearch 和 ClickHouse 数据库时存在一处服务端请求伪造漏洞&#xff08;SSRF&#xff09;。 VPS开启HTTP服务 VPS 开启HTTP 再同时跑POC 确保能访问poc里的链接文件 第一是目标地址 第二个是跳转地址 第三个是监听地址 如果…

为什么大学讲授 C 语言比讲授 C++ 的更多?

大学更倾向于讲授C语言而不是C的几个原因可能包括。我收集归类了一份嵌入式学习包&#xff0c;对于新手而言简直不要太棒&#xff0c;里面包括了新手各个时期的学习方向编程教学、问题视频讲解、毕设800套和语言类教学&#xff0c;敲个22就可以免费获得。 基础性质&#xff1a;…

【Linux】进程程序替换 + 模拟实现简易shell

前言 上一节我们介绍了 **进程终止**和 **进程等待**等一系列问题&#xff0c;并做了相应的验证&#xff0c;本章将继续对进程控制进行介绍&#xff0c;重点学习进程程序替换&#xff0c;并进行相应验证&#xff0c;在此基础上&#xff0c;自己模拟实现一个shell&#xff0c;该…

Redis分布式锁-Redisson可重入锁原理的个人见解。

记录Redisson可重入锁的个人见解。 文章目录 前言一、什么叫做锁的重入&#xff1f;二、Redisson可重入锁原理 前言 ⁣⁣⁣⁣ ⁣⁣⁣⁣ 之前在写项目的时候&#xff0c;注意到Redisson可重入锁的一个问题&#xff0c;随即在网上搜索其对应的资料&#xff0c;下面就记录一下个…

昇思25天学习打卡营第14天 | ShuffleNet图像分类

昇思25天学习打卡营第14天 | ShuffleNet图像分类 文章目录 昇思25天学习打卡营第14天 | ShuffleNet图像分类ShuffleNetPointwise Group ConvolutionChannel ShuffleShuffleNet模块网络构建 模型训练与评估数据集训练模型评估模型预测 总结打卡 ShuffleNet ShuffleNetV1是旷世科…