js五子棋效果

任务分解
一、绘制棋盘
二、绑定事件
1、先计算出需要绘制棋子的坐标 即将来绘制的棋子在哪个单元格内
2、绘制棋子 首先判断棋子是否存在 应该添加到哪个单元格内,分四种情况:
1.1 正常情况
1.2 最右侧 超出边界只能放在最后一个单元格内
1.3 左下侧 超出边界只能放在最后一个单元格内
1.4 右下侧 超出边界只能放在最后一个单元格内
3、当5个连续的棋子一样就算赢了 游戏结束 处理结束的逻辑 五个连续的需要处理四种情况:
1.1 横向的5个连续相同的棋子
1.2 竖着的5个连续相同的棋子
1.3 二个斜着的5个连续相同的棋子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</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>
*{
/* margin: 0;
padding: 0; */
}
.container{
width: 500px;
height: 500px;
border: 1px solid #ccc;
background-color: bisque;
margin: 30px auto;
display: flex;
justify-content: center;
align-items: center;
}
.chessboard{
border-collapse: collapse;
border-spacing: 0;
width: 94%;
height: 94%;
}
.chessboard td{
border: 1px solid #000;
position: relative;
}
.chess{
position: absolute;
top: -50%;
left: -50%;
width: 80%;
height: 80%;
background-color: lightgrey;
border-radius: 50%;
color: lightgrey;
font-size: 12px;
font-weight: bold;
/* 弹性盒文字居中 */
display: flex;
align-items: center;
justify-content: center;
}
.white{
background: #fff;
}
.blackc{
background-color: #000;
}
.win{
border: 1px solid red;
box-shadow: 0 0 3px 2px red;
}
function $(selector) {
return document.querySelector(selector);
}
function $$(selector) {
return document.querySelectorAll(selector);
}
var chessboard = document.querySelector('.chessboard');
var whichOne = "white";
//生成的最大范围区间
var sectionNum = 14;
//是否结束
var isGameOver = false;
var chessArr = [];
function initChessboard() {
var tableContent = '';
for (var i = 0; i < sectionNum; i++) {
var row = `<tr>`;
for (var j = 0; j < sectionNum; j++) {
row += `<td data-row="${i}" data-line="${j}"></td>`;
}
row += '</tr>';
tableContent += row;
}
chessboard.innerHTML = tableContent;
}
//offsetLeft 一个元素相对于父元素的的水平偏移量
function bindEvent() {
chessboard.addEventListener('click', function (e) {
console.log(e);
if (!isGameOver) {
var temp = Object.assign({}, e.target.dataset);
if (e.target.nodeName === 'TD') {
//首先判断点击的td 所处的坐标 (从而计算出 棋子在哪个单元格)
//比较鼠标点击的位置 与单元格的一半哪个大哪个小 从而计算出棋子是在当前单元格还是在下一个单元格内
//求出单元格的宽高
var tdw = chessboard.clientWidth * 0.94 / sectionNum;
//比一半小则保留当前在当前单元格内
//比一半大则保留在下一个单元格内
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('恭喜你赢了,是否要重新开始?')) {
//重新开始 重新绘制 数组置空
isGameOver = false;
initChessboard();
chessArr = [];
}
}
})
}
function chessMove(chessPoint) {
//检测棋子已经绘制 在点击到当前范围内不在绘制棋子
//判断棋子是否已经存在
if (exist(chessPoint) && !isGameOver) {
//绘制棋子 就是将div添加到单元格内
var newDiv = `<div class="chess ${chessPoint.c}" data-row="${chessPoint.y}" data-line="${chessPoint.x}">`;
chessArr.push(chessPoint);
//添加到哪个单元格内分四种情况 (处理边界条件)
//正常情况
if (chessPoint.x < 14 && chessPoint.y < 14) {
var tdP = $(`td[data-row='${chessPoint.y}'][data-line='${chessPoint.x}']`);
console.log(tdP)
tdP.innerHTML += newDiv;
}
//最右侧 超出边界只能放在最后一个单元格内
if (chessPoint.x === 14 && chessPoint.y < 14) {
var tdP = $(`td[data-row='${chessPoint.y}'][data-line='${chessPoint.x - 1}']`);
tdP.innerHTML += newDiv;
tdP.lastChild.style.left = '50%';
}
//左下侧 超出边界只能放在最后一个单元格内
if (chessPoint.x < 14 && chessPoint.y === 14) {
var tdP = $(`td[data-row='${chessPoint.y - 1}'][data-line='${chessPoint.x}']`);
tdP.innerHTML += newDiv;
tdP.lastChild.style.top = '50%';
}
//右下侧 超出边界只能放在最后一个单元格内
if (chessPoint.x === 14 && chessPoint.y === 14) {
var tdP = $(`td[data-row='${chessPoint.y - 1}'][data-line='${chessPoint.x - 1}']`);
tdP.innerHTML += newDiv;
tdP.lastChild.style.left = '50%';
tdP.lastChild.style.top = '50%';
}
whichOne = whichOne === 'white' ? 'blackc' : 'white';
}
//判断游戏是否结束
checker()
}
function exist(chessPoint) {
var res = chessArr.find(function (item) {
return item.x === chessPoint.x && item.y === chessPoint.y && item.c === chessPoint.c
})
return res === undefined ? true : false;
}
function checker() {
console.log(chessArr);
for (var i = 0; i < chessArr.length; i++) {
var chess = chessArr[i];
var chess2, chess3, chess4, chess5;
//处理边界条件 5个连续的 分四种情况
//连续横着的
chess2 = chessArr.find(function (item) {
return chess.x === item.x + 1 && chess.y === item.y && chess.c === item.c;
});
chess3 = chessArr.find(function (item) {
return chess.x === item.x + 2 && chess.y === item.y && chess.c === item.c;
});
chess4 = chessArr.find(function (item) {
return chess.x === item.x + 3 && chess.y === item.y && chess.c === item.c;
});
chess5 = chessArr.find(function (item) {
return chess.x === item.x + 4 && chess.y === item.y && chess.c === item.c;
});
if (chess2 && chess3 && chess4 && chess5) {
end(chess, chess2, chess3, chess4, chess5);
}
//连续竖着的
chess2 = chessArr.find(function (item) {
return chess.y === item.y + 1 && chess.x === item.x && chess.c === item.c;
})
chess3 = chessArr.find(function (item) {
return chess.y === item.y + 2 && chess.x === item.x && chess.c === item.c;
})
chess4 = chessArr.find(function (item) {
return chess.y === item.y + 3 && chess.x === item.x && chess.c === item.c;
})
chess5 = chessArr.find(function (item) {
return chess.y === item.y + 4 && chess.x === item.x && chess.c === item.c;
})
if (chess2 && chess3 && chess4 && chess5) {
end(chess, chess2, chess3, chess4, chess5);
}
//连续斜着的
chess2 = chessArr.find(function (item) {
return chess.x === item.x + 1 && chess.y === item.y + 1 && chess.c === item.c;
});
chess3 = chessArr.find(function (item) {
return chess.x === item.x + 2 && chess.y === item.y + 2 && chess.c === item.c;
});
chess4 = chessArr.find(function (item) {
return chess.x === item.x + 3 && chess.y === item.y + 3 && chess.c === item.c;
});
chess5 = chessArr.find(function (item) {
return chess.x === item.x + 4 && chess.y === item.y + 4 && chess.c === item.c;
});
if (chess2 && chess3 && chess4 && chess5) {
end(chess, chess2, chess3, chess4, chess5);
}
//反斜着的
chess2 = chessArr.find(function (item) {
return chess.x === item.x - 1 && chess.y === item.y + 1 && chess.c === item.c;
});
chess3 = chessArr.find(function (item) {
return chess.x === item.x - 2 && chess.y === item.y + 2 && chess.c === item.c;
});
chess4 = chessArr.find(function (item) {
return chess.x === item.x - 3 && chess.y === item.y + 3 && chess.c === item.c;
});
chess5 = chessArr.find(function (item) {
return chess.x === item.x - 4 && chess.y === item.y + 4 && chess.c === item.c;
});
if (chess2 && chess3 && chess4 && chess5) {
end(chess, chess2, chess3, chess4, chess5);
}
}
}
function end() {
if (!isGameOver) {
isGameOver = true;
//结束之后显示棋子的顺序
for (var i = 0; i < chessArr.length; i++) {
$(`div[data-row='${chessArr[i].y}'][data-line='${chessArr[i].x}']`).innerHTML = i + 1;
}
//给胜利的棋子加高亮显示
for (var j = 0; j < arguments.length; j++) {
console.dir($(`div[data-row='${arguments[j].y}'][data-line='${arguments[j].x}']`))
$(`div[data-row='${arguments[j].y}'][data-line='${arguments[j].x}']`).classList.add('win');
}
}
}
function main() {
//初始化棋盘
initChessboard();
//绑定监听事件
bindEvent();
}
main();
js五子棋效果的更多相关文章
- JS原生效果瀑布流布局的实现(一)
JS原生效果 实现: HTML页面布局: <!DOCTYPE html> <html> <head> <meta charset="utf-8&qu ...
- js sleep效果
js sleep效果 s = setInterval(function(){ //需要执行的函数 alert("我延迟了2秒弹出"); },2000); 并不是每2秒执行一次,而是 ...
- JS打字效果的动态菜单代码分享
这篇文章主要介绍了JS打字效果的动态菜单,推荐给大家,有需要的小伙伴可以参考下. 这是一款基于javascript实现的打字效果的动态菜单特效代码,分享给大家学习学习. 小提示:浏览器中如果不能正常运 ...
- js 动画效果实现
1. 实现方式 - 应用场景 自己写 - 简单的.不用 jq 的项目 jq - 普通动画 成熟插件 - 复杂动画 2. 相关文章 JavaScript基于时间的动画算法 九种原生js动画效果 Twee ...
- 页面倒计时跳转页面效果,js倒计时效果
页面倒计时跳转页面效果,js倒计时效果 >>>>>>>>>>>>>>>>>>>> ...
- 非常不错的一个JS分页效果代码
这里分享一个不错的js分页代码. 代码中cpage是页面计数,应为全局变量,可以随处调用它: totalpage是总页数. 与asp分页代码很类似,也是先取得记录总数,然后实现分页,基本的分页思路与原 ...
- 纯js倒计时效果(交流加群:452892873)(本群每天都更新学习资料)
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- js 技巧 (十)广告JS代码效果大全 【3】
3.[允许关闭] 与前面两个代码不同的是,广告图下方增加了一个图片按纽,允许访客点击关闭广告图片,下面文本框中就是实现效果所需代码: var delta=0.015; var coll ...
- js 技巧 (十)广告JS代码效果大全 【1】
广告JS代码效果大全 1.[普通效果] 现在很多网站广告做的如火如荼,现在我就来介绍一下常见的对联浮动广告效果的代码使用方法,介绍的这种效果,在1024*768分辨率下正常显示,在800*60 ...
- Js 拖动效果
<!DOCTYPE html> <html> <head> <meta charset="utf8"> <title>j ...
随机推荐
- PC大屏自适应
通常来说PC端的页面并不像移动端页面那样对屏幕大小和分别率有那么强的依赖.一般的页面都是取屏幕中间的一块宽度(1280px), 两边留白, 高度随着内容的长度滚动.这样无论窗口怎么变化,页面都是可用的 ...
- 使用ob_tools包收集分析oceanbase数据库oracle租户缓慢sql语句
概述 1.手册目的: 本手册旨在提供一种系统化的方法论,以便发现和分析慢SQL语句.通过使用ob_tools包,收集和分析在交付期间,应用程序在不同场景下进行压测时所产生的慢SQL语句,从而实现性能调 ...
- 使用技巧 | 红米 Redmi Note 12 Turbo优化记录(去广告等)
原文链接:https://engapi.com/article/7569 原文也是我写的. 我的红米Redmi note8 pro 6+128已有些卡顿,遂在K70推出之际下单了Redmi Note ...
- 鸿蒙NEXT开发案例:随机数生成
[引言] 本项目是一个简单的随机数生成器应用,用户可以通过设置随机数的范围和个数,并选择是否允许生成重复的随机数,来生成所需的随机数列表.生成的结果可以通过点击"复制"按钮复制到剪 ...
- SpringBoot实现轻量级动态定时任务管控及组件化
关于动态定时任务 关于在SpringBoot中使用定时任务,大部分都是直接使用SpringBoot的@Scheduled注解,如下: @Component public class TestTask ...
- web移动端屏幕适配方案
因为手机屏幕的分辨率大小不一 ,如果使用传统的静态布局,把每个元素的宽高样式写死,在不同的屏幕中就有各种各样的显示效果.这显然不是我们想要的结果.我们需要的是根据屏幕分辨率的不同,来适配不同的样式大小 ...
- Epicor 10 SaaS云登录
随着云计算的普及,几乎所有的软件都可以云化了,但事实上,并没有.尤其是在管理软件领域起步较早的 ERP 似乎在云化的道路上一直步履蹒跚. 随着公共云的成熟,人们的观念已经改变.云计算和 SaaS 提供 ...
- word常规操作
为何写标 招标: A公司要买100台电脑 [需求] 投标: 电脑公司看到招标后,就会投标:自我介绍(公司,产品,售后) [自我介绍满足需求] 中标: A公司选择XX公司 [选择] 保密价格内容 不能透 ...
- Zookeeper Java API操作流程
首先需要配置一台Zookeeper服务器 pom文件 <dependencies> <!-- https://mvnrepository.com/artifact/org.a ...
- TypeNameExtractor could not be found
TypeNameExtractor could not be foundException 一.注意: 如果项目中使用了 knif4j或swagger (knif4j内核中就使用了swagger) 项 ...