一、背景 {#一、背景}
近一个月没写 Javascript 代码,有点生疏。正好浏览网页时弹出五子棋的游戏广告,于是想通过编写这个小游戏练练手。
二、简单介绍 {#二、简单介绍}
2.1 效果展示 {#2.1-效果展示}
2.2 实现思路 {#2.2-实现思路}
-
棋盘:通过图片(chessboard.png)和 div 标签渲染出棋盘。
-
棋子:通过图片(black_flag.png、white_flag.png等)渲染出黑白棋子。落子前,鼠标出会出现一个可以随鼠标移动的棋子。我们创建一个浮动的 div,动态设置其 top 和 left 。
-
落子:给容器(class="container")添加 click 事件,给其添加对应的 classname。即被点击的单元格设置棋子背景图片。此外,需要判断落子点是否存在棋子。
-
输赢:使用二维数组保存棋盘(棋子)状态,通过横向、纵向、左上到右下和右上到左下四个方向进行判断是否有 5 个以上连续同颜色(样式)的棋子。
2.3 涉及技术 {#2.3-涉及技术}
DOM操作、面向对象、事件操作和间隔函数 setInterval
2.4 项目结构 {#2.4-项目结构}
三、实现步骤 {#三、实现步骤}
3.1 绘制棋盘 {#3.1-绘制棋盘}
style.css 内容:
|---------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| html,body { padding: 0; margin: 0; } .container { position: relative; width: 540px; height: 540px; margin: 10px auto; padding-top: 7px; padding-left: 7px; background: url("../images/chessboard.png") no-repeat; cursor: pointer; } .none { position: absolute; width: 36px; height: 36px; box-sizing: border-box; /*border: 1px solid #fff;*/ } .black_flag { position: absolute; width: 36px; height: 36px; background: url("../images/black_flag.png") no-repeat; } .black_flag_cur { position: absolute; background: url("../images/black_flag_cur.png") no-repeat; /*设置点击无效*/ pointer-events: none; } .white_flag { position: absolute; width: 36px; height: 36px; background: url("../images/white_flag.png") no-repeat; } .white_flag_cur { position: absolute; background: url("../images/white_flag_cur.png") no-repeat; /*设置点击无效*/ pointer-events: none; }
|
chessboard.js 代码:
|------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| var Chessboard = function() { // 保存棋盘棋子状态 this.flagArr = []; this.size = 36; } // 初始化棋盘 Chessboard.prototype.init = function() { var container = document.getElementById("container"); for (var i = 0; i < 15; i++) { var arr = []; for (var j = 0; j < 15; j++) { var div = document.createElement("div"); div.className = "none"; div.style.top = (i * this.size) + "px"; div.style.left = (j * this.size) + "px"; container.appendChild(div); arr.push(div); } this.flagArr.push(arr); } }
|
game.js 代码:
|-------------------------|-------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8
| var Game = function() { } Game.prototype.start = function() { var chessboard = new Chessboard(); chessboard.init(); }
|
最终效果如下:
为了方便查看 div 与棋盘图片中格子之间的对应关系,笔者将 div 边框设置成白色。
从图中我们可以看到,div 大小正好对应棋盘的落子点。我们将 div 背景设置成棋子图片就实现了落子操作。
3.2 绘制棋子 {#3.2-绘制棋子}
chessboard.js 代码:
|------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| var Chessboard = function() { // 保存棋盘棋子状态 this.flagArr = []; this.size = 36; // 默认黑色为先手 this.currentFlag = true; // 保存落子前的样式映射 this.flagCurMap = []; // 黑子 this.flagCurMap[true] = "black_flag_cur"; // 白子 this.flagCurMap[false] = "white_flag_cur"; } // 初始化棋盘 Chessboard.prototype.init = function() { var container = document.getElementById("container"); for (var i = 0; i < 15; i++) { var arr = []; for (var j = 0; j < 15; j++) { var div = document.createElement("div"); div.className = "none"; div.style.top = (i * this.size) + "px"; div.style.left = (j * this.size) + "px"; container.appendChild(div); arr.push(div); } this.flagArr.push(arr); } // 添加事件监听器 this.addListener(container); } // 落子事件监听器 Chessboard.prototype.addListener = function() { var that = this; // 设置落子前的鼠标样式 var mouse = document.createElement("div"); mouse.id = "mouse"; mouse.style.width = mouse.style.height = 36 + "px"; document.body.appendChild(mouse); document.body.onmousemove = function(event) { mouse.className = that.flagCurMap[that.currentFlag]; var x = event.clientX - 16; var y = event.clientY - 16; mouse.style.top = y + "px"; mouse.style.left = x + "px"; } }
|
结果如下图:
3.3 落子 {#3.3-落子}
在 chessboard.js 的监听器方法中添加落子的点击事件:
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| var Chessboard = function() { // 保存棋盘棋子状态 this.flagArr = []; this.size = 36; // 默认黑色为先手 this.currentFlag = true; // 保存落子前的样式映射 this.flagCurMap = []; // 黑子 this.flagCurMap[true] = "black_flag_cur"; // 白子 this.flagCurMap[false] = "white_flag_cur"; // 保存落子后的样式映射 this.flagMap = []; // 黑子 this.flagMap[true] = "black_flag"; // 白子 this.flagMap[false] = "white_flag"; // 保存结果映射关系 this.resultMap = []; this.resultMap[true] = "黑子胜利"; this.resultMap[false] = "白子胜利"; } // 初始化棋盘 Chessboard.prototype.init = function() { var container = document.getElementById("container"); for (var i = 0; i < 15; i++) { var arr = []; for (var j = 0; j < 15; j++) { var div = document.createElement("div"); div.className = "none"; div.style.top = (i * this.size) + "px"; div.style.left = (j * this.size) + "px"; container.appendChild(div); arr.push(div); } this.flagArr.push(arr); } // 添加事件监听器 this.addListener(container); } // 落子事件监听器 Chessboard.prototype.addListener = function(container) { var that = this; // 设置落子前的鼠标样式 var mouse = document.createElement("div"); mouse.id = "mouse"; mouse.style.width = mouse.style.height = 36 + "px"; document.body.appendChild(mouse); document.body.onmousemove = function(event) { mouse.className = that.flagCurMap[that.currentFlag]; var x = event.clientX - 16; var y = event.clientY - 16; mouse.style.top = y + "px"; mouse.style.left = x + "px"; } // 落子监听 container.onclick = function(event) { // 判断落子点是否存在棋子 if (event.target.className != "none") { alert("此处不能落子!"); return; } // 落子,设置棋子图片 event.target.className = that.flagMap[that.currentFlag]; // 换棋手 that.currentFlag = !that.currentFlag; } }
|
运行结果如下:
3.4 判断输赢 {#3.4-判断输赢}
在 chessboard.js 的落子监听实践代码中,判断是否五连子:
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
| // 落子事件监听器 Chessboard.prototype.addListener = function(container) { var that = this; // 设置落子前的鼠标样式 var mouse = document.createElement("div"); mouse.id = "mouse"; mouse.style.width = mouse.style.height = 36 + "px"; document.body.appendChild(mouse); document.body.onmousemove = function(event) { mouse.className = that.flagCurMap[that.currentFlag]; var x = event.clientX - 16; var y = event.clientY - 16; mouse.style.top = y + "px"; mouse.style.left = x + "px"; } // 落子监听 container.onclick = function(event) { // 判断落子点是否存在棋子 if (event.target.className != "none") { alert("此处不能落子!"); return; } // 落子,设置棋子图片 event.target.className = that.flagMap[that.currentFlag]; // 当前落子坐标 var x = Math.floor(event.target.offsetLeft / that.size); var y = Math.floor(event.target.offsetTop / that.size); // 判断是否胜利 if (that._checkSuccess(x, y)) { document.getElementById("mouse").style.display = "none"; container.onclick = null; document.body.onmousemove = null; alert(that.resultMap[that.currentFlag]); return; } // 换棋手 that.currentFlag = !that.currentFlag; } } // 判断棋局 Chessboard.prototype._checkSuccess = function(x, y) { var result = false; // 当前落子的样式/颜色 var className = this.flagArr[y][x].className; // 横向判断 var count = 0; for (var i = 0; i < 15; i++) { if (className == this.flagArr[y][i].className) { count++; if (count >= 5) { return true; } } else { count = 0; } } // 纵向判断 for (var j = 0; j < 15; j++) { if (className == this.flagArr[j][x].className) { count++; if (count >= 5) { return true; } } else { count = 0; } } // 左上到右下判断 var a = y - x; var index = 0; if (a > 0) { for (a; a < 15; a++) { if (className == this.flagArr[a][index++].className) { count++; if (count >= 5) { return true; } } else { count = 0; } } } else { a = Math.abs(a); for (a; a < 15; a++) { if (className == this.flagArr[index++][a].className) { count++; if (count >= 5) { return true; } } else { count = 0; } } } // 右上到左下判断 var b = 14 - y -x; var index2 = 14; if (b > 0) { b = 14 - b; index2 = 0; for (b; b >= 0; b--) { if (className == this.flagArr[index2++][b].className) { count++; if (count >= 5) { return true; } } else { count = 0; } } } else { b = Math.abs(b); for (b; b < 15; b++) { if (className == this.flagArr[index2--][b].className) { count++; if (count >= 5) { return true; } } else { count = 0; } } } if (count >= 5) { result = true; } return result; }
|
演示结果:
剩余的一些文本提示,倒计时就不在此处介绍。具体代码可以在下边提供的链接中下载。