摘要:廢話不多說上代碼完整項目地址項目地址棋盤樣式棋盤元素初始化初始化角色黑旗子白旗是否已分出勝負(fù)走棋記錄當(dāng)前步清空棋子和事件初始化棋盤矩陣刻畫棋盤棋盤網(wǎng)格刻畫棋子每次落子結(jié)束都要判斷輸贏落子如果點擊的是棋子則中斷空的棋位才可落子落
廢話不多說上代碼!
完整項目地址:GitHub項目地址
class Gobang { constructor(options) { this.options = options this.gobang = document.getElementById(options.canvas || "gobang") this.chessboard = this.gobang.children[0] this.chessmans = this.gobang.children[1] // 棋盤樣式 this.gobangStyle = Object.assign({ padding: 30, count: 15 }, options.gobangStyle || {}) // 棋盤元素 this.lattice = { width: (this.gobang.clientWidth - this.gobangStyle.padding * 2) / this.gobangStyle.count, height: (this.gobang.clientHeight - this.gobangStyle.padding * 2) / this.gobangStyle.count } // 初始化 this.resetAndInit() } // 初始化 resetAndInit() { const {options} = this // 角色 => 1黑旗子 2白旗 this.role = options.role || this.role || 1 // 是否已分出勝負(fù) this.win = false // 走棋記錄 this.history = [] // 當(dāng)前步 this.currentStep = 0 // 清空棋子和事件 this.chessmans.onclick = null this.chessmans.innerHTML = "" // 初始化 this.drawChessboard() this.listenDownChessman() this.initChessboardMatrix() } // 棋盤矩陣 initChessboardMatrix() { const checkerboard = [] for(let x = 0; x < this.gobangStyle.count + 1; x++) { checkerboard[x] = [] for(let y = 0; y < this.gobangStyle.count + 1; y++) { checkerboard[x][y] = 0 } } this.checkerboard = checkerboard } // 刻畫棋盤 drawChessboard() { const { gobangStyle, gobang } = this // 棋盤網(wǎng)格 const lattices = Array.from({ length: gobangStyle.count * gobangStyle.count }, () => ``).join("") this.chessboard.className = `chessboard lattice-${gobangStyle.count}` this.chessboard.innerHTML = lattices this.gobang.style.border = `${gobangStyle.padding}px solid #ffffd` } // 刻畫棋子 drawChessman(x, y, isBlack) { const { gobangStyle, lattice, gobang } = this const newChessman = document.createElement("div") newChessman.setAttribute("id", `x${x}-y${y}-r${isBlack ? 1 : 2}`) newChessman.className = isBlack ? "chessman black" : "chessman white" newChessman.style.width = lattice.width * 0.6 newChessman.style.height = lattice.height * 0.6 newChessman.style.left = (x * lattice.width) - lattice.width * 0.3 newChessman.style.top = (y * lattice.height) - lattice.height * 0.3 this.chessmans.appendChild(newChessman) // 每次落子結(jié)束都要判斷輸贏 setTimeout(() => { this.checkReferee(x, y, isBlack ? 1 : 2) }, 0) } // 落子 listenDownChessman(isBlack = false) { this.chessmans.onclick = event => { // 如果點擊的是棋子則中斷 if(event.target.className.includes("chessman ")) { return false } let { offsetX: x, offsetY: y } = event x = Math.round(x / this.lattice.width) y = Math.round(y / this.lattice.height) // 空的棋位才可落子 if(this.checkerboard[x][y] !== undefined && Object.is(this.checkerboard[x][y], 0)) { // 落子后,更新矩陣,切換角色,并記錄 this.checkerboard[x][y] = this.role this.drawChessman(x, y, Object.is(this.role, 1)) // 落子完畢后,有可能是悔棋之后落子的,這種情況下就該重置歷史記錄 this.history.length = this.currentStep this.history.push({ x, y, role: this.role }) // 保存坐標(biāo),角色,快照 this.currentStep++ this.role = Object.is(this.role, 1) ? 2 : 1 } } } // 判斷輸贏 checkReferee(x, y, role) { if((x == undefined) || (y == undefined) || (role == undefined)) return // 連殺分?jǐn)?shù) let countContinuous = 0 // 所在矩陣數(shù)據(jù) const XContinuous = this.checkerboard.map(x => x[y]) const YContinuous = this.checkerboard[x] const S1Continuous = [] const S2Continuous = [] this.checkerboard.forEach((_y, i) => { // 左斜線 const S1Item = _y[y - (x - i)] // alert(S1Item) if(S1Item !== undefined) { S1Continuous.push(S1Item) } // 右斜線 const S2Item = _y[y + (x - i)] if(S2Item !== undefined) { S2Continuous.push(S2Item) } }) // 當(dāng)前落棋點所在的X軸/Y軸/交叉斜軸,只要有能連起來的5個子的角色即有勝者 ; [XContinuous, YContinuous, S1Continuous, S2Continuous].forEach(axis => { if(axis.some((x, i) => axis[i] !== 0 && axis[i - 2] === axis[i - 1] && axis[i - 1] === axis[i] && axis[i] === axis[i + 1] && axis[i + 1] === axis[i + 2])) { countContinuous++ } }) // 如果贏了,則解綁事件 if(countContinuous) { this.chessmans.onclick = null this.win = true alert((role == 1 ? "黑" : "白") + "子勝") } } // 悔棋 regretChess() { // 找到最后一次的記錄,回滾UI,更新矩陣 if(this.history.length && !this.win) { const prev = this.history[this.currentStep - 1] if(prev) { const { x, y, role } = prev const targetChessman = document.getElementById(`x${x}-y${y}-r${role}`) targetChessman.parentNode.removeChild(targetChessman) this.checkerboard[prev.x][prev.y] = 0 this.currentStep-- this.role = Object.is(this.role, 1) ? 2 : 1 } } } // 撤銷悔棋 revokedRegretChess() { const next = this.history[this.currentStep] if(next) { this.drawChessman(next.x, next.y, next.role === 1) this.checkerboard[next.x][next.y] = next.role this.currentStep++ this.role = Object.is(this.role, 1) ? 2 : 1 } } } // 實例化游戲 const gobangGame = new Gobang({ role: 2, canvas: "game", gobangStyle: { padding: 30, count: 16 } }) console.log(gobangGame)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/88325.html
摘要:這是我在一次面試中,被面試官所提問的一道題在這次面試題中相等指的是對象的屬性個數(shù)值相等有這樣兩個李德華張德華我能想到的一種方案解答過程的思考由于沒有,我只能通過轉(zhuǎn)化成數(shù)組進(jìn)入第二步,對象中的屬性在另一個中是否存在。 這是我在一次面試中,被面試官所提問的一道題 在這次面試題中 相等:指的是對象的屬性個數(shù)值相等 有這樣兩個obj let obj1 = { name:李德華, ...
摘要:前端日報精選專題之跟著學(xué)節(jié)流冴羽的博客全家桶仿微信項目,支持多人在線聊天和機器人聊天騰訊前端團隊社區(qū)編碼的奧秘模塊實現(xiàn)入門淺析知乎專欄前端每周清單發(fā)布新版本提升應(yīng)用性能的方法中文寇可往吾亦可往用實現(xiàn)對決支付寶的微信企業(yè)付款到零 2017-06-20 前端日報 精選 JavaScript專題之跟著 underscore 學(xué)節(jié)流 - 冴羽的JavaScript博客 - SegmentFau...
摘要:前言很認(rèn)真的說吧,在和騰訊面試官的面試的過程。騰訊二面自我介紹二面的面試官和一面不是同一個面試官,所以在這個時候,我的基本介紹還是和一面一樣,介紹自己的基本信息,以及怎么想到學(xué)習(xí)前端和怎么學(xué)習(xí)前端。 前言 很認(rèn)真的說吧,在和騰訊面試官的面試的過程。有點感覺是在聊天一樣,他們是面試官,但是感覺更像是引路人,不管結(jié)果的好壞,在騰訊面試的過程,只要你認(rèn)真去聽去問,就可以學(xué)到很多東西吧。 如果...
摘要:擁有兩個版本,無依賴的獨立版和版本。除了對象,也可監(jiān)聽內(nèi)元素的手勢需要引擎內(nèi)置對象支持綁定相關(guān)事件。據(jù)不完全統(tǒng)計,目前服務(wù)于興趣部落群動漫騰訊學(xué)院騰訊等多個部門團隊和項目。也可以在事件回調(diào)里根據(jù)攜帶的信息使用去操作。 簡介 針對多點觸控設(shè)備編程的Web手勢組件,快速幫助你的web程序增加手勢支持,也不用再擔(dān)心click 300ms的延遲了。擁有兩個版本,無依賴的獨立版和react版本。...
閱讀 3152·2021-11-24 10:24
閱讀 2957·2021-11-11 16:54
閱讀 3083·2021-09-22 15:55
閱讀 2037·2019-08-30 15:44
閱讀 1908·2019-08-29 18:41
閱讀 2770·2019-08-29 13:43
閱讀 3061·2019-08-29 12:51
閱讀 1193·2019-08-26 12:19