娱乐五子棋(附加源码)

一写在开头

上期代码主要实现瀑布流功能,本期就来实现五子棋小游戏,开发久了很多功能都是通过框架组件库来完成,但是如果组件满足不了开发需求,还需要开发人员手动封装组件,专门出这样一期文章,通过原生js实现一些特定功能,功能也比较简单,也是想借助这样一个简单的功能,然后来帮助大家了解我们JavaScript,在前端中的作用,另外也培养下我们的代码思维,那我们本次就通过由简单到复杂循序渐进,这份专栏中我们还会带领大家用前端实现读心术小游戏等等有趣的小功能,纯前端语言实现,都会陆续带给大家。

实现逻辑

1.棋盘的绘制
绘制棋盘,其实就是一个 14 行 x 14 列 的 table 表格。
每个 td 会记录当前的格子是第几行第几列,我们通过自定义属性来进行记录。
data-row 记录行,data-line 记录列。
2.确定落子的坐标
当用户在棋盘上点击鼠标时,我们需要落下一颗棋子,那么如何确定这颗棋子的坐标呢?首先,通过 e.target.dataset,能够获取到用户点击的是哪一个 td,通过 e.offsetX、e.offsetY,我们就可以获取到事件发生时鼠标相对于事件源元素的坐标,所谓事件源元素就是绑定事件的那个元素。首先计算出一个格子的宽高,然后用户点击的 e.offsetX 小于格子宽度的一半,e.offsetY 小于格子高度的一半,则是左上区域。 e.offsetX 小于格子宽度的一半但是 e.offsetY 大于格子高度的一半,则是左下,依此类推。
3.绘制棋子
4.胜负判定
5.游戏已经结束,需要询问是否要重新来一局

页面创建

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>五子棋小游戏2</title><link rel="stylesheet" href="../css/index.css">
</head>
<body><!-- 最外层的容器 --><div class="container"><!-- 棋盘 --><table class="chessboard"></table></div><script src="../js/index.js"></script>
</body>
</html>

样式编写

/* 整体容器的样式 */
.container{border: 1px solid rgb(207, 188, 188);width: 500px;height: 500px;margin: 50px auto;/* 是一个弹性盒子,我们这边的设置代表让里面的内容水平垂直居中 */display: flex;justify-content: center;align-items: center;background-color: rgb(247, 230, 183);
}/* 棋盘里面的格子的样式 */
.chessboard{width: 92%;height: 92%;/* 设置表格的行列之间没有间隙 */border-collapse: collapse;
}.chessboard td{border: 1px solid black;position: relative;
}/* 棋子的公共样式 */
.chess{border: 1px solid lightgrey;border-radius: 50%;position: absolute;left: -50%;top: -50%;width: 90%;height: 90%;color: lightgrey;font-size : 12px;font-weight: bold;/* 让文字居中 */display: flex;justify-content: center;align-items: center;
}/* 白色棋子 */
.white {background-color: #fff;
}/* 黑色棋子 */
.black {background-color: #000;
}/* 获胜棋子 */
.win{border : 1px solid red;box-shadow: 0 0 3px 2px red; /* 红色阴影 */
}

逻辑实现

// 首先还是封装两个 DOM 查询的方法
function $(selector){return document.querySelector(selector);
}function $$(selector){return document.querySelectorAll(selector);
}var chessboard = $('.chessboard'); // 获取棋盘的 table
var isGameOver = false; // 游戏是否结束
var whichOne = 'white'; // 一开始是白色的棋子
var chessArr = []; //  存储所有的棋子信息// 初始化棋盘的方法
function initChessboard(){// 我们要绘制一个 14x14 的棋盘格子,并且我们要把下标放入到每一个格子var tableContent = "";// 循环生成行for(var i=0;i<14;i++){var row = '<tr>';// 循环生成列for(var j=0;j<14;j++){row += `<td data-row='${i}' data-line='${j}'></td>`;}row += '</tr>';tableContent += row;}chessboard.innerHTML = tableContent;
}// 绑定点击事件
function bindEvent(){chessboard.onclick = function(e){// 我们可以很轻松的知道用户点击的是哪一个 tdif(!isGameOver){// 游戏没有结束,那么我们要做的事情就是落子var temp = Object.assign({}, e.target.dataset); // 获取到用户点击的 td 信息if(e.target.nodeName === 'TD'){// 我们首先计算出每个格子的边长var tdw = chessboard.clientWidth * 0.92 / 14;// 接下来我们就需要确认用户落子究竟是在四个角的哪一个角var positionX = e.offsetX > tdw / 2;var positionY = e.offsetY > tdw / 2;// 接下来我们来组装棋子的信息var chessPoint = {x : positionX ? parseInt(temp.line) + 1 : parseInt(temp.line),y : positionY ? parseInt(temp.row) + 1 : parseInt(temp.row),c : whichOne}// 绘制棋子chessMove(chessPoint);}} else {// 游戏已经结束,需要询问是否要重新来一局if(window.confirm('是否要重新开始一局?')){// 进行一些初始化操作chessArr = []; // 重置棋子的数组initChessboard(); // 重新绘制棋盘isGameOver = false;}}}
}// 绘制棋子,接收一个参数,就是棋子的信息的对象
function chessMove(chessPoint){// 我们在绘制之前,我们需要先判断一下,该位置有没有棋子,如果有棋子,那么就不需要再绘制if(exist(chessPoint) && !isGameOver){// 进入此 if,说明该位置能够绘制,并且没有游戏结束chessArr.push(chessPoint); // 将该棋子的信息推入到数组// 生成一个棋子,其实就是生成一个 div,然后将该 div 放入到对应的 td 里面var newChess = `<div class="chess ${chessPoint.c}" data-row="${chessPoint.y}" data-line="${chessPoint.x}"></div>`;// 接下来,我们需要根据不同的落子位置,调整棋子if(chessPoint.x < 14 && chessPoint.y < 14){var tdPos = $(`td[data-row='${chessPoint.y}'][data-line='${chessPoint.x}']`);tdPos.innerHTML += newChess;}// x 等于 14,说明是最右侧那条线if(chessPoint.x === 14 && chessPoint.y < 14){var tdPos = $(`td[data-row='${chessPoint.y}'][data-line='13']`);tdPos.innerHTML += newChess;tdPos.lastChild.style.left = '50%';}// y 等于 14,说明是最下侧那条线if(chessPoint.x < 14 && chessPoint.y === 14){var tdPos = $(`td[data-row='13'][data-line='${chessPoint.x}']`);tdPos.innerHTML += newChess;tdPos.lastChild.style.top = '50%';}// x 和 y 均等于 14,说明是最右下角的那个 tdif(chessPoint.x === 14 && chessPoint.y === 14){var tdPos = $(`td[data-row='13'][data-line='13']`);tdPos.innerHTML += newChess;tdPos.lastChild.style.top = '50%';tdPos.lastChild.style.left = '50%';}whichOne = whichOne === 'white' ? 'black' : 'white'; // 切换棋子的颜色}check(); // 核对游戏是否结束
}// 判断该棋子是否已经存在
function exist(chessPoint){var result = chessArr.find(function(item){return item.x === chessPoint.x && item.y === chessPoint.y;})return result === undefined ? true : false;
}// 检查游戏是否结束,检查是否有符合要求的棋子
function check(){// 其实就是遍历数组里面的每一个棋子// 这里分为 4 种情况:横着、竖着、斜着(2 种)for(var i=0; i< chessArr.length; i++){var curChess = chessArr[i];var chess2, chess3, chess4, chess5;// 检查有没有横着的 5 个颜色一样的棋子chess2 = chessArr.find(function(item){return curChess.x === item.x + 1 && curChess.y === item.y && curChess.c === item.c;})chess3 = chessArr.find(function(item){return curChess.x === item.x + 2 && curChess.y === item.y && curChess.c === item.c;})chess4 = chessArr.find(function(item){return curChess.x === item.x + 3 && curChess.y === item.y && curChess.c === item.c;})chess5 = chessArr.find(function(item){return curChess.x === item.x + 4 && curChess.y === item.y && curChess.c === item.c;})if(chess2 && chess3 && chess4 && chess5){// 进入此 if,说明游戏结束end(curChess, chess2, chess3, chess4, chess5);}// 检查有没有竖着的 5 个颜色一样的棋子chess2 = chessArr.find(function(item){return curChess.x === item.x && curChess.y === item.y + 1 && curChess.c === item.c;})chess3 = chessArr.find(function(item){return curChess.x === item.x && curChess.y === item.y + 2 && curChess.c === item.c;})chess4 = chessArr.find(function(item){return curChess.x === item.x && curChess.y === item.y + 3 && curChess.c === item.c;})chess5 = chessArr.find(function(item){return curChess.x === item.x && curChess.y === item.y + 4 && curChess.c === item.c;})if(chess2 && chess3 && chess4 && chess5){// 进入此 if,说明游戏结束end(curChess, chess2, chess3, chess4, chess5);}// 检查有没有斜着的 5 个颜色一样的棋子chess2 = chessArr.find(function(item){return curChess.x === item.x + 1 && curChess.y === item.y + 1&& curChess.c === item.c;})chess3 = chessArr.find(function(item){return curChess.x === item.x + 2 && curChess.y === item.y + 2 && curChess.c === item.c;})chess4 = chessArr.find(function(item){return curChess.x === item.x + 3 && curChess.y === item.y + 3 && curChess.c === item.c;})chess5 = chessArr.find(function(item){return curChess.x === item.x + 4 && curChess.y === item.y + 4 && curChess.c === item.c;})if(chess2 && chess3 && chess4 && chess5){// 进入此 if,说明游戏结束end(curChess, chess2, chess3, chess4, chess5);}// 检查有没有斜着的 5 个颜色一样的棋子chess2 = chessArr.find(function(item){return curChess.x === item.x - 1 && curChess.y === item.y + 1&& curChess.c === item.c;})chess3 = chessArr.find(function(item){return curChess.x === item.x - 2 && curChess.y === item.y + 2 && curChess.c === item.c;})chess4 = chessArr.find(function(item){return curChess.x === item.x - 3 && curChess.y === item.y + 3 && curChess.c === item.c;})chess5 = chessArr.find(function(item){return curChess.x === item.x - 4 && curChess.y === item.y + 4 && curChess.c === item.c;})if(chess2 && chess3 && chess4 && chess5){// 进入此 if,说明游戏结束end(curChess, chess2, chess3, chess4, chess5);}}
}function end(){if(!isGameOver){isGameOver = true; // 代表游戏结束// 1. 把所有的棋子标记出来for(var i=0;i<chessArr.length;i++){$(`div[data-row='${chessArr[i].y}'][data-line='${chessArr[i].x}']`).innerHTML = i + 1;}// 2. 把获胜的棋子加上一个红色阴影for(var i=0;i<arguments.length;i++){$(`div[data-row='${arguments[i].y}'][data-line='${arguments[i].x}']`).classList.add('win');}}
}// 游戏的主方法,相当于程序的入口
function main(){// 1. 初始化棋盘initChessboard();// 2. 绑定对应的事件bindEvent();
}
main();

结果展示

在这里插入图片描述

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

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

相关文章

XMOS将在CES 2025上展出多款由边缘AI驱动的创新音效、音频、识别和处理解决方案

全球智能物联网技术领导者暨匠心独到的半导体科技企业XMOS宣布&#xff1a;该公司将再次参加2025年国际消费电子展&#xff08;CES 2025&#xff09;&#xff0c;并将在本届CES上展出一系列由人工智能&#xff08;AI&#xff09;驱动的全新空间音效、语音捕获与降噪、音视频多模…

HCIA-Access V2.5_2_2_2网络通信基础_IP编址与路由

网络层数据封装 首先IP地址封装在网络层&#xff0c;它用于标识一台网络设备&#xff0c;其中IP地址分为两个部分&#xff0c;网络地址和主机地址&#xff0c;通过我们采用点分十进制的形式进行表示。 IP地址分类 对IP地址而言&#xff0c;它细分为五类&#xff0c;A,B,C,D,E,…

我的数据仓库与数据挖掘期末大作业重置版

文章目录 我的数据仓库与数据挖掘期末大作业重置版准备工作预设定及导入相对应的库库的导入调整 Jupyter Notebook 的预设定调整 MatPlotLib 和 Pandas 的输出设置 任务 1&#xff1a;预测问题数据的保存和读取数据的分析和预处理模型的选择和构建线性回归一元多项式回归 拟合预…

CUDA C编程权威指南习题解析

文章目录 一、1.6节习题二、2.6习题三、四、五、六、 一、1.6节习题 1.参考图1-5&#xff0c;分析以下几种数据划分形式&#xff1a; &#xff08;1&#xff09;对于二维数据&#xff0c;沿x轴进行块划分 &#xff08;2&#xff09;对于二维数据&#xff0c;沿y轴进行周期划…

cocos creator 的 widget组件的使用及踩坑

以下的内容基于cocos creator 3.8版本&#xff0c;如有错误&#xff0c;恳请指出。 &#x1f449;官方文档的指引 应用&#xff1a;以上官方指引有非常清晰的使用方式&#xff0c;接下来说明一些注意事项&#xff1a; 1、与canvas搭配的使用&#xff0c;解决多分别率适配问题。…

PHP搭建环境

一、安装apache 1、获取Apache安装软件 2、双击安装即可:指定对应的路径:E:server/apache 3、选择安装模式:使用自定义模式 4、选择安装位置 二、Apache的目录结构说明 三、Httpd.exe的详细应用 1、服务器进程:运行之后才能够工作

微积分复习笔记 Calculus Volume 2 - 4.1 Basics of Differential Equations

4.1 Basics of Differential Equations - Calculus Volume 2 | OpenStax

0003.基于springboot的“共享书角”图书借还管理系统

适合初学同学练手项目&#xff0c;部署简单&#xff0c;代码简洁清晰&#xff1b; 一、系统架构 前端&#xff1a;vue| elementui| 微信小程序 后端&#xff1a;springboot | mybatis-plus 环境&#xff1a;jdk1.8 | mysql | maven 系统设计说明: 二、代码及数据库 1.管理…

python学opencv|读取图像(十二)BGR图像转HSV图像

【1】引言 前述已经学习了opencv中图像BGR相关知识&#xff0c;文章链接包括且不限于下述&#xff1a; python学opencv|读取图像&#xff08;六&#xff09;读取图像像素RGB值_opencv读取灰度图-CSDN博客 python学opencv|读取图像&#xff08;七&#xff09;抓取像素数据顺利…

音频进阶学习八——傅里叶变换的介绍

文章目录 前言一、傅里叶变换1.傅里叶变换的发展2.常见的傅里叶变换3.频域 二、欧拉公式1.实数、虚数、复数2.对虚数和复数的理解3.复平面4.复数和三角函数5.复数的运算6.欧拉公式 三、积分运算1.定积分2.不定积分3.基本的积分公式4.积分规则线性替换法分部积分法 5.定积分计算…

智能高效的IDE GoLand v2024.3全新发布——支持最新Go语言

GoLand 使 Go 代码的阅读、编写和更改变得非常容易。即时错误检测和修复建议&#xff0c;通过一步撤消快速安全重构&#xff0c;智能代码完成&#xff0c;死代码检测和文档提示帮助所有 Go 开发人员&#xff0c;从新手到经验丰富的专业人士&#xff0c;创建快速、高效、和可靠的…

SQL server学习06-查询数据表中的数据(中)

目录 一&#xff0c;聚合函数 1&#xff0c;常用聚合函数 2&#xff0c;具体使用 二&#xff0c;GROP BY子句分组 1&#xff0c;基础语法 2&#xff0c;具体使用 3&#xff0c;加上HAVING对组进行筛选 4&#xff0c;使WHERE记录查询条件 汇总查询&#xff1a;在对数…

游戏引擎学习第52天

仓库 : https://gitee.com/mrxiao_com/2d_game 这节的内容相当多 回顾 在游戏中&#xff0c;实体被分为不同的类别&#xff1a;接近玩家的“高频实体”、距离较远并正在模拟的“低频实体”和不进行更新的“休眠实体”。这些实体会根据它们与玩家的距离进行处理&#xff0c;接…

websocket_asyncio

WebSocket 和 asyncio 指南 简介 本指南涵盖了使用 Python 中的 websockets 库进行 WebSocket 编程的基础知识&#xff0c;以及 asyncio 在异步非阻塞 I/O 中的作用。它提供了构建高效 WebSocket 服务端和客户端的知识&#xff0c;以及 asyncio 的特性和优势。 1. 什么是 WebS…

ARCGIS国土超级工具集1.2更新说明

ARCGIS国土超级工具集V1.2版本&#xff0c;功能已增加至47 个。在V1.1的基础上修复了若干使用时发现的BUG&#xff0c;新增了"矢量分割工具"菜单&#xff0c;同时增加及更新了了若干功能&#xff0c;新工具使用说明如下&#xff1a; 一、勘测定界工具栏更新界址点成果…

MySQL之数据库三大范式

一、什么是范式&#xff1f; 范式是数据库遵循设计时遵循的一种规范&#xff0c;不同的规范要求遵循不同的范式。 &#xff08;范式是具有最小冗余的表结构&#xff09; 范式可以 提高数据的一致性和 减少数据冗余和 更新异常的问题 数据库有六种范式&#xff08;1NF/2NF/3NF…

使用 mkcert 工具自签发 https 证书并进行本地受信

介绍 mkcert 是一个用于创建本地受信任的 SSL/TLS 证书的简单工具&#xff0c;特别适合开发者在本地环境中使用。它解决了为开发和测试目的创建自签名证书时遇到的信任问题。以下是关于 mkcert 的详细介绍&#xff1a; 特点 易用性&#xff1a;只需一条命令即可生成证书&…

【Swift】集合类型 - 数组、集合、字典

文章目录 集合的可变性数组数组类型简写语法创建空数组使用默认值创建数组通过合并两个数组创建一个新数组使用数组字面量创建数组访问和修改数组 Swift 提供了三种主要的 集合类型&#xff0c;分别是数组、集合和字典&#xff0c;用于存储值集合。数组是有序的值集合。集合是无…

探索 Janus-1.3B:一个统一的 Any-to-Any 多模态理解与生成模型

随着多模态技术的不断发展&#xff0c;越来越多的模型被提出以解决跨文本与图像等多种数据类型的任务。Janus-1.3B 是由 DeepSeek 推出的一个革命性的模型&#xff0c;它通过解耦视觉编码并采用统一的 Transformer 架构&#xff0c;带来了一个高度灵活的 any-to-any 多模态框架…

C# 中的闭包

文章目录 前言一、闭包的基本概念二、匿名函数中的闭包1、定义和使用匿名函数2、匿名函数捕获外部变量3、闭包的生命周期 三、Lambda 表达式中的闭包1、定义和使用 Lambda 表达式2、Lambda 表达式捕获外部变量3、闭包的作用域 四、闭包的应用场景1、事件处理2、异步编程3、迭代…