腾讯cdc php面试,腾讯CDC面试题之五子棋 - dom版(ES6)

废话不多说上代码!

完整项目地址: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

// 是否已分出胜负

this.win = false

// 走棋记录

this.history = []

// 当前步

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

// 棋盘网格

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 #ddd`

}

// 刻画棋子

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)

// 每次落子结束都要判断输赢

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

})

// 保存坐标,角色,快照

this.currentStep++

this.role = Object.is(this.role, 1) ? 2 : 1

}

}

}

// 判断输赢

checkReferee(x, y, role) {

if((x == undefined) || (y == undefined) || (role == undefined)) return

// 连杀分数

let countContinuous = 0

// 所在矩阵数据

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)

}

})

// 当前落棋点所在的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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值