Vue實(shí)現(xiàn)五子棋小游戲
本文實(shí)例為大家分享了Vue實(shí)現(xiàn)五子棋小游戲的具體代碼,供大家參考,具體內(nèi)容如下
<!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> ?? ??? ?<!-- 棋盤網(wǎng)格層 --> ?? ??? ?<div class="boxRow" @click="downChess($event)"></div> ?? ??? ?<!-- 功能BTN --> ?? ??? ?<div class="btnGroup"> ?? ??? ??? ?<button @click="giveUp()">認(rèn)輸</button> ?? ??? ??? ?<button @click="regret()">悔棋</button> ?? ??? ??? ?<button @click="openNew()">重開(kāi)</button> ?? ??? ?</div> ?? ?</div> </body> <script> ?? ?new Vue({ ?? ??? ?el: ".fiveInRow", ?? ??? ?data: { ?? ??? ??? ?boxSize: 15, //棋盤大小 ?? ??? ??? ?chessType: "black", //棋子類型,默認(rèn)為黑 ?? ??? ??? ?blackList: [], //黑子列表 ?? ??? ??? ?whiteList: [], //白子列表 ?? ??? ??? ?totleNum: 0, //落子總數(shù) ?? ??? ??? ?isOver: 0 //游戲是否結(jié)束 ?? ??? ?}, ?? ??? ?created() { ?? ??? ??? ?this.createBox() ?? ??? ?}, ?? ??? ?watch: { ?? ??? ??? ?totleNum(val) { ?? ??? ??? ??? ?// 監(jiān)聽(tīng)棋盤落子數(shù) ?? ??? ??? ??? ?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() { ?? ??? ??? ??? ?// 創(chuàng)建棋盤網(wǎng)格 ?? ??? ??? ??? ?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>游戲已經(jīng)結(jié)束了,請(qǐng)重新開(kāi)始!</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("瞅哪呢?看準(zhǔn)點(diǎn)下!"); ?? ??? ??? ??? ?} ?? ??? ??? ?}, ?? ??? ??? ?getLayer(val) { ?? ??? ??? ??? ?// 獲取落點(diǎn)相對(duì)位置 ?? ??? ??? ??? ?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) { ?? ??? ??? ??? ?// 游戲結(jié)束 ?? ??? ??? ??? ?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() { ?? ??? ??? ??? ?// 認(rèn)輸投降 ?? ??? ??? ??? ?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("一個(gè)子都沒(méi)有,悔個(gè)雞兒悔!"); ?? ??? ??? ??? ?} ?? ??? ??? ?}, ?? ??? ??? ?openNew() { ?? ??? ??? ??? ?// 重新開(kāi)始 ?? ??? ??? ??? ?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.畫棋盤
小雨采用了最直接, 最暴力的方式, 就是把一堆小方塊堆起來(lái), 加上邊框, 棋盤有了…什么? 你問(wèn)我那五個(gè)點(diǎn)怎么畫上去的? 頁(yè)面上試出來(lái)的.
2.落子
落子是比較講究的. 首先獲取鼠標(biāo)點(diǎn)擊事件中的layerX, layerY, 這是鼠標(biāo)點(diǎn)擊的相對(duì)位置, 在本例中是比較好用的. 然后通過(guò) getLayer() 函數(shù)獲取點(diǎn)擊點(diǎn)最近的網(wǎng)格點(diǎn), 如下圖, 鼠標(biāo)點(diǎn)擊在紅框內(nèi)則落子. 最后在相比網(wǎng)格點(diǎn)半個(gè)棋子位的地方落子就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個(gè)函數(shù): isFive(), isFiveInStraight(), isFiveInSlope() 和 isFiveNearby().
isFive(): 這個(gè)只是調(diào)用后續(xù)函數(shù)的函數(shù), 它將獲勝條件分成了4類: 橫線獲勝, 豎線獲勝, 斜率為1的斜線獲勝 和 斜率為-1的斜線獲勝.
isFiveInStraight(): 判斷 橫線獲勝 和 豎線獲勝 的功能函數(shù). 這里的主要難點(diǎn)就是listSGT 對(duì)象的創(chuàng)建, 能否想到要用對(duì)象來(lái)實(shí)現(xiàn)落子的分類, 是這個(gè)函數(shù)的關(guān)鍵. 在 橫線獲勝 中, 將落子的layerY 坐標(biāo)作為對(duì)象的屬性, 將有相同layerY 坐標(biāo)的棋子的layerX 組成一個(gè)數(shù)組作為屬性的值. 豎線獲勝 同理.
isFiveInSlope(): 判斷 斜率為1的斜線獲勝 和 斜率為-1的斜線獲勝 的功能函數(shù). 與 isFiveInStraight() 不同的是, 在創(chuàng)建listSLP 對(duì)象時(shí), 以直線函數(shù) y = k x + b y = kx+by=kx+b 中截距(b) 作為對(duì)象的屬性, 以落子的layerX 坐標(biāo)組成的數(shù)組作為屬性的值, 其實(shí)用落子的layerY坐標(biāo)也是一樣的.
isFiveNearby(): 判斷五子是否相鄰的功能函數(shù). 此函數(shù)直接獲取上兩個(gè)函數(shù)中所創(chuàng)建對(duì)象的值, 也就是落子坐標(biāo)組成的數(shù)組. 首先判斷數(shù)組長(zhǎng)度是否大于5, 畢竟能少走一步是一步嘛. 之后將數(shù)組從小到大排序, 計(jì)算相鄰兩位的差, 并記錄. 連續(xù)記錄4次獲勝.
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
vue實(shí)現(xiàn)消息向上無(wú)縫滾動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)消息向上無(wú)縫滾動(dòng)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04Vue寫一個(gè)簡(jiǎn)單的倒計(jì)時(shí)按鈕功能
這篇文章主要介紹了基于Vue寫一個(gè)簡(jiǎn)單的倒計(jì)時(shí)按鈕功能,在項(xiàng)目開(kāi)發(fā)的過(guò)程,經(jīng)常會(huì)遇到發(fā)送驗(yàn)證碼,點(diǎn)擊之后有60秒倒計(jì)時(shí)的按鈕,今天小編就給大家分享實(shí)例代碼,需要的朋友參考下吧2018-04-04vue+element table表格實(shí)現(xiàn)動(dòng)態(tài)列篩選的示例代碼
這篇文章主要介紹了vue+element table表格實(shí)現(xiàn)動(dòng)態(tài)列篩選的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01vue中使用go()和back()兩種返回上一頁(yè)的區(qū)別說(shuō)明
這篇文章主要介紹了vue中使用go()和back()兩種返回上一頁(yè)的區(qū)別說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07vue項(xiàng)目history模式刷新404問(wèn)題解決辦法
這篇文章主要給大家介紹了關(guān)于vue項(xiàng)目history模式刷新404問(wèn)題的解決辦法,需要的朋友可以參考下2023-11-11el-tree懶加載的實(shí)現(xiàn)以及局部刷新方式
這篇文章主要介紹了el-tree懶加載的實(shí)現(xiàn)以及局部刷新方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04vue音樂(lè)播放器插件vue-aplayer的配置及其使用實(shí)例詳解
本篇文章主要介紹了vue音樂(lè)播放器插件vue-aplayer的配置及其使用實(shí)例詳解,具有一定的參考價(jià)值,有興趣的可以了解一下2017-07-07Vue中接收二進(jìn)制文件流實(shí)現(xiàn)pdf預(yù)覽的方法
本文主要介紹了Vue中接收二進(jìn)制文件流實(shí)現(xiàn)pdf預(yù)覽的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12