Vue实现五子棋小游戏
作者:雨迹丶
本文实例为大家分享了Vue实现五子棋小游戏的具体代码,供大家参考,具体内容如下
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>五子棋</title> <script src="./configJS/vue.js"></script> <script src="./configJS/jQuery 1.10.2.js"></script> <style> .fiveInRow { position: absolute; width: 100%; } .fiveStar { position: absolute; display: flex; width: 542px; height: 720px; margin: -24px 65px; justify-content: space-around; align-items: center; } .starGroup { height: 100%; display: flex; flex-direction: column; justify-content: space-around; } .star { width: 10px; height: 10px; border-radius: 50%; background: black; } .boxRow { position: absolute; display: flex; margin: 20px; border: 1px solid black; box-sizing: border-box; } .box { width: 45px; height: 45px; border: 1px solid black; box-sizing: border-box; } .chessBlock { position: absolute; margin: 20px; } .chessBox { position: absolute; z-index: 9; width: 42px; height: 42px; display: flex; justify-content: center; align-items: center; } .chess { width: 40px; height: 40px; border-radius: 50%; border: 1px solid black; box-sizing: border-box; } .overCover { position: absolute; display: flex; flex-direction: column; justify-content: center; align-items: center; width: 632px; height: 632px; color: red; z-index: 11; } .btnGroup { position: absolute; top: 700px; left: 235px; display: flex; } .btnGroup button { margin: 0 10px; } </style> </head> <body> <div class="fiveInRow"> <!-- 棋盘五星层 --> <div class="fiveStar"> <div class="starGroup"> <div class="star"></div> <div class="star"></div> </div> <div class="star"></div> <div class="starGroup"> <div class="star"></div> <div class="star"></div> </div> </div> <!-- 落子层 --> <div class="chessBlock"></div> <!-- 棋盘网格层 --> <div class="boxRow" @click="downChess($event)"></div> <!-- 功能BTN --> <div class="btnGroup"> <button @click="giveUp()">认输</button> <button @click="regret()">悔棋</button> <button @click="openNew()">重开</button> </div> </div> </body> <script> new Vue({ el: ".fiveInRow", data: { boxSize: 15, //棋盘大小 chessType: "black", //棋子类型,默认为黑 blackList: [], //黑子列表 whiteList: [], //白子列表 totleNum: 0, //落子总数 isOver: 0 //游戏是否结束 }, created() { this.createBox() }, watch: { totleNum(val) { // 监听棋盘落子数 let boxRow = $(".boxRow")[0]; let overCover = `<div class="overCover"> <h1 style="color:red;">棋盘满了,下一把吧!!!</h1> </div>`; if (val === this.boxSize * this.boxSize) { boxRow.innerHTML += overCover; this.isOver = 1; } } }, methods: { createBox() { // 创建棋盘网格 let box = `<div class="box"></div>`; let boxRow = $(".boxRow")[0]; for (let i = 1; i < this.boxSize; i++) { let boxCloum = `<div class="boxCloum">`; for (let j = 1; j < this.boxSize; j++) { boxCloum += box; } boxRow.innerHTML += boxCloum + `</div>`; } }, downChess(ev) { // 判断落子 if (!this.isOver) { this.down(ev); } else { let overCover = $(".overCover")[0]; let newSpan = `<h2>游戏已经结束了,请重新开始!</h2>`; if (overCover.children.length <= 3) overCover.innerHTML += newSpan; } }, down(ev) { // 落子 let chessBlock = $(".chessBlock")[0]; let layerX = this.getLayer(ev.layerX); let layerY = this.getLayer(ev.layerY); if (layerX >= 0 && layerY >= 0) { let chessTemp = `<div class="chessBox" style="left:${layerX-21}px;top:${layerY-21}px;" ><span class="chess" style="background:${this.chessType};"></span></div>`; chessBlock.innerHTML += chessTemp; this.totleNum++; if (this.chessType === "black") { this.blackList.push([layerX, layerY]); this.isFive(this.blackList); this.chessType = "white"; } else { this.whiteList.push([layerX, layerY]); this.isFive(this.whiteList); this.chessType = "black"; } } else { console.log("瞅哪呢?看准点下!"); } }, getLayer(val) { // 获取落点相对位置 if (val % 45 <= 20) { return val - val % 45; } else if (val % 45 >= 25) { return val - val % 45 + 45; } else { return -1; } }, isFive(list) { // 判断是否落成五子 this.isFiveInStraight(list, 0, 1); this.isFiveInStraight(list, 1, 0); this.isFiveInSlope(list, -1); this.isFiveInSlope(list, 1); }, isFiveInStraight(list, a, b) { // 判断五子是否在水平线或垂直线 let listSGT = {}; for (let i = 0; i < list.length; i++) { if (!listSGT[list[i][b]]) { listSGT[list[i][b]] = [list[i][a]]; } else { listSGT[list[i][b]].push(list[i][a]); this.isFiveNearby(listSGT[list[i][b]]); } } }, isFiveInSlope(list, slope) { // 判断五子是否在正斜线或反斜线 let listSLP = {}; for (let i = 0; i < list.length; i++) { let b = list[i][1] - slope * list[i][0]; if (!listSLP[b]) { listSLP[b] = [list[i][0]]; } else { listSLP[b].push(list[i][0]); this.isFiveNearby(listSLP[b]); } } }, isFiveNearby(arr) { // 判断五子是否相邻,连成一线 let idx = 0; let player = this.chessType === "black" ? "Black(黑)" : "White(白)"; if (arr.length >= 5) { arr.sort((a, b) => a - b) for (let i = 1; i < arr.length; i++) { idx = arr[i] - arr[i - 1] === 45 ? idx + 1 : 0; if (idx === 4) this.gameOver(player); } } }, gameOver(player) { // 游戏结束 console.log(player + " Win!!!"); let boxRow = $(".boxRow")[0]; let overCover = `<div class="overCover"><h1>${player} Win!!!</h1></div>`; boxRow.innerHTML += overCover; this.isOver = 1; }, giveUp() { // 认输投降 let player = this.chessType === "black" ? "White(白)" : "Black(黑)"; if (!this.isOver) this.gameOver(player); }, regret() { // 悔棋 if (this.totleNum > 0 && !this.isOver) { let chessBlock = $(".chessBlock")[0]; chessBlock.removeChild(chessBlock.children[--this.totleNum]); if (this.chessType === "black") { this.whiteList.pop(); this.chessType = "white"; } else { this.blackList.pop(); this.chessType = "black"; } } else { console.log("一个子都没有,悔个鸡儿悔!"); } }, openNew() { // 重新开始 let chessBlock = $(".chessBlock")[0]; let boxRow = $(".boxRow")[0]; for (let i = this.totleNum - 1; i >= 0; i--) { chessBlock.removeChild(chessBlock.children[i]); } if (boxRow.children[14]) boxRow.removeChild(boxRow.children[14]); this.chessType = "black"; this.blackList = []; this.whiteList = []; this.totleNum = this.isOver = 0; } } }) </script> </html>
主要思路
1.画棋盘
小雨采用了最直接, 最暴力的方式, 就是把一堆小方块堆起来, 加上边框, 棋盘有了…什么? 你问我那五个点怎么画上去的? 页面上试出来的.
2.落子
落子是比较讲究的. 首先获取鼠标点击事件中的layerX, layerY, 这是鼠标点击的相对位置, 在本例中是比较好用的. 然后通过 getLayer() 函数获取点击点最近的网格点, 如下图, 鼠标点击在红框内则落子. 最后在相比网格点半个棋子位的地方落子就OK了.
3.判断获胜条件
isFive(list) { // 判断是否落成五子 this.isFiveInStraight(list, 0, 1); this.isFiveInStraight(list, 1, 0); this.isFiveInSlope(list, -1); this.isFiveInSlope(list, 1); }, isFiveInStraight(list, a, b) { // 判断五子是否在水平线或垂直线 let listSGT = {}; for (let i = 0; i < list.length; i++) { if (!listSGT[list[i][b]]) { listSGT[list[i][b]] = [list[i][a]]; } else { listSGT[list[i][b]].push(list[i][a]); this.isFiveNearby(listSGT[list[i][b]]); } } }, isFiveInSlope(list, slope) { // 判断五子是否在正斜线或反斜线 let listSLP = {}; for (let i = 0; i < list.length; i++) { let b = list[i][1] - slope * list[i][0]; if (!listSLP[b]) { listSLP[b] = [list[i][0]]; } else { listSLP[b].push(list[i][0]); this.isFiveNearby(listSLP[b]); } } }, isFiveNearby(arr) { // 判断五子是否相邻,连成一线 let idx = 0; let player = this.chessType === "black" ? "Black(黑)" : "White(白)"; if (arr.length >= 5) { arr.sort((a, b) => a - b) for (let i = 1; i < arr.length; i++) { idx = arr[i] - arr[i - 1] === 45 ? idx + 1 : 0; if (idx === 4) this.gameOver(player); } } },
这里主要有4个函数: isFive(), isFiveInStraight(), isFiveInSlope() 和 isFiveNearby().
isFive(): 这个只是调用后续函数的函数, 它将获胜条件分成了4类: 横线获胜, 竖线获胜, 斜率为1的斜线获胜 和 斜率为-1的斜线获胜.
isFiveInStraight(): 判断 横线获胜 和 竖线获胜 的功能函数. 这里的主要难点就是listSGT 对象的创建, 能否想到要用对象来实现落子的分类, 是这个函数的关键. 在 横线获胜 中, 将落子的layerY 坐标作为对象的属性, 将有相同layerY 坐标的棋子的layerX 组成一个数组作为属性的值. 竖线获胜 同理.
isFiveInSlope(): 判断 斜率为1的斜线获胜 和 斜率为-1的斜线获胜 的功能函数. 与 isFiveInStraight() 不同的是, 在创建listSLP 对象时, 以直线函数 y = k x + b y = kx+by=kx+b 中截距(b) 作为对象的属性, 以落子的layerX 坐标组成的数组作为属性的值, 其实用落子的layerY坐标也是一样的.
isFiveNearby(): 判断五子是否相邻的功能函数. 此函数直接获取上两个函数中所创建对象的值, 也就是落子坐标组成的数组. 首先判断数组长度是否大于5, 毕竟能少走一步是一步嘛. 之后将数组从小到大排序, 计算相邻两位的差, 并记录. 连续记录4次获胜.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。