中国象棋js代码
代码语言:html
所属分类:游戏
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>BFW NEW PAGE</title> <script id="bfwone" data="dep=jquery.17&err=0" type="text/javascript" src="http://repo.bfw.wiki/bfwrepo/js/bfwone.js"></script> <script type="text/javascript"> class Chess { constructor(canvasId) { this.canvas = document.getElementById(canvasId); this.ctx = this.canvas.getContext("2d"); this.initCanvas(); this.resetData(); } // 重置数据,再来一局 resetData() { this.redBottom = true; // 红方在下边(这个属性可以用来给不同的用户显示不同的棋盘) this.toMove = {}; this.active = "red"; // 当前走棋方 this.bottomColor = "red"; // 红方在下边 this.chessSteps = []; // 走棋记录 this.initChessBoard(); this.initComposition(); this.drawPieces(); } // 切换走棋方 exchange() { this.active = this.active == 'red' ? 'black': 'red'; // this.reverseChess(); } // 反转棋局数组 reverseChess() { this.composition = this.deepReverse(this.composition); } // 渲染棋盘和棋子 renderUi() { //清除之前的画布 this.ctx.clearRect(0, 0, this.width, this.height); this.initChessBoard(); this.drawPieces(); } // 输赢判断 getVictor() { var flag = false; for (let i = 0, len = this.composition.length; i < len; i++) { for (let j = 0, len1 = this.composition[i].length; j < len1; j++) { // if(){ // // } } } } // 初始化canvas并绑定点击事件 initCanvas() { // var bodys = document.documentElement || document.body; var body = document.body; // console.log("%O",body); var h = body.clientHeight; var w = body.clientWidth; if (h > w) { this.cellWidth = w / 10; } else { this.cellWidth = h / 11; } this.width = this.cellWidth * 10; this.height = this.cellWidth * 11; this.canvas.width = this.width; this.canvas.height = this.height; // 绑定点击事件 this.canvas.addEventListener("click", (e)=> { var offset = this.canvas.getBoundingClientRect(); var x = Math.round((e.clientX - offset.left - this.cellWidth) / this.cellWidth); var y = Math.round((e.clientY - offset.top - this.cellWidth) / this.cellWidth); // console.log(x, y, "点击位置"); // 走棋 if (x >= 0 && x <= 8 && y <= 9 && y >= 0) { this.goStep(y, x); console.log(this.chessSteps); } else { console.log("点在其他地方,没在棋局中"); } }, false); } // 初始化棋盘 initChessBoard() { //设置全局属性 var padding = 2; var borderWidth = 5; var borderColor = "#333"; var bgColor = "#a6753a"; var lineColor = "#333"; var fontColor = bgColor; var bgWidth = this.cellWidth - borderWidth - padding; // 画边框 this.ctx.strokeStyle = bgColor; this.ctx.lineWidth = bgWidth*2; this.ctx.lineJoin = "miter"; this.ctx.beginPath(); this.ctx.moveTo(0, 0); this.ctx.lineTo(this.width, 0); this.ctx.lineTo(this.width, this.height); this.ctx.lineTo(0, this.height); this.ctx.closePath(); this.ctx.stroke(); // 画外边线 this.ctx.strokeStyle = borderColor; this.ctx.lineWidth = borderWidth; this.ctx.lineJoin = "miter"; this.ctx.beginPath(); this.ctx.moveTo(0+bgWidth, 0+bgWidth); this.ctx.lineTo(0+this.width-bgWidth, 0+bgWidth); this.ctx.lineTo(this.width-bgWidth, this.height-bgWidth); this.ctx.lineTo(0+bgWidth, this.height-bgWidth); this.ctx.stroke(); this.ctx.save(); this.ctx.translate(this.cellWidth, this.cellWidth); this.ctx.beginPath(); // 画横线 for (let i = 0; i < 10; i++) { this.ctx.moveTo(0, this.cellWidth*i); this.ctx.lineTo(this.cellWidth*8, this.cellWidth*i); } // 画纵线 for (let i = 0; i < 9; i++) { this.ctx.moveTo(this.cellWidth*i, 0); this.ctx.lineTo(this.cellWidth*i, this.cellWidth*4); this.ctx.moveTo(this.cellWidth*i, this.cellWidth*5); this.ctx.lineTo(this.cellWidth*i, this.cellWidth*9); } // 链接断线 this.ctx.moveTo(0, this.cellWidth*4); this.ctx.lineTo(0, this.cellWidth*5); this.ctx.moveTo(this.cellWidth*8, this.cellWidth*4); this.ctx.lineTo(this.cellWidth*8, this.cellWidth*5); this.ctx.strokeStyle = lineColor; this.ctx.lineWidth = 1; this.ctx.stroke(); // 写(楚河、汉界)汉字 this.ctx.font = `${this.cellWidth*0.75}px 方正舒体`; // 隶书 方正舒体 this.ctx.fillStyle = fontColor; this.ctx.textBaseline = "middle"; this.ctx.textAlign = "center"; this.ctx.fillText("楚", this.cellWidth*1.5, this.cellWidth*4.5); this.ctx.fillText("河", this.cellWidth*2.5, this.cellWidth*4.5); this.ctx.fillText("汉", this.cellWidth*5.5, this.cellWidth*4.5); this.ctx.fillText("界", this.cellWidth*6.5, this.cellWidth*4.5); // 画炮位 var paoArr = [{ x: 1, y: 2 }, { x: 7, y: 2 }, { x: 7, y: 7 }, { x: 1, y: 7 }]; for (let i = 0, len = paoArr.length; i < len; i++) { this.markP(paoArr[i].x, paoArr[i].y); } // 画兵和卒位 var bingArr = []; for (let i = 0; i < 9; i += 2) { bingArr.push({ x: i, y: 3 }); bingArr.push({ x: i, y: 6 }); } // 画皇宫 this.ctx.beginPath(); this.ctx.moveTo(this.cellWidth*3, 0); this.ctx.lineTo(this.cellWidth*5, this.cellWidth*2); this.ctx.moveTo(this.cellWidth*5, 0); this.ctx.lineTo(this.cellWidth*3, this.cellWidth*2); this.ctx.moveTo(this.cellWidth*3, this.cellWidth*9); this.ctx.lineTo(this.cellWidth*5, this.cellWidth*7); this.ctx.moveTo(this.cellWidth*5, this.cellWidth*9); this.ctx.lineTo(this.cellWidth*3, this.cellWidth*7); this.ctx.stroke(); for (let i = 0, len = bingArr.length; i < len; i++) { this.markP(bingArr[i].x, bingArr[i].y); } this.ctx.restore(); } // 方向数字化 nd(direction) { var res = { h: 0, v: 0 }; // h horizontal v vertical switch (direction) { case "r": res.h = 1; res.v = 0; break; case "rd": res.h = 1; res.v = 1; break; case "d": res.h = 0; res.v = 1; break; case "ld": res.h = -1; res.v = 1; break; case "l": res.h = -1; res.v = 0; break; case "lt": res.h = -1; res.v = -1; break; case "t": res.h = 0; res.v = -1; break; case "rt": res.h = 1; res.v = -1; break; default: console.error("方向输入有误"); } return res; } markP(x, y) { // 标出上下左右 var arr = []; if (x === 0) { arr = ["rt", "rd"]; } else if (x === 8) { arr = ["lt", "ld"]; } else { arr = ["lt", "rt", "rd", "ld"]; } var padding = this.cellWidth/10; var length = this.cellWidth/5 for (let i = 0; i < arr.length; i++) { this.mark(x, y, arr[i], padding, length); } } // 四个标记中的一个 mark(x, y, direction, padding, length) { var d = this.nd(direction); var h = d.h; var v = d.v; this.ctx.beginPath(); this.ctx.moveTo(this.cellWidth*x+h*(padding+length), this.cellWidth*y+v*padding); this.ctx.lineTo(this.cellWidth*x+h*padding, this.cellWidth*y+v*padding); this.ctx.lineTo(this.cellWidth*x+h*padding, this.cellWidth*y+v*(padding+length)); this.ctx.stroke(); } // 初始化棋局 initComposition() { var origin = [ ["車", "馬", "象", "士", "将", "士", "象", "馬", "車"], ["", "", "", "", "", "", "", "", ""], ["", "炮", "", "", "", "", "", "炮", ""], ["卒", "", "卒", "", "卒", "", "卒", "", "卒"], ["", "", "", "", "", "", "", "", ""], ["", "", "", "", "", "", "", "", ""], ["兵", "", "兵", "", "兵", "", "兵", "", "兵"], ["", "砲", "", "", "", "", "", "砲", ""], ["", "", "", "", "", "", "", "", ""], ["車", "馬", "相", "仕", "帥", "仕", "相", "馬", "車"] ]; this.composition = []; for (let i = 0, len = origin.length; i < len; i++) { this.composition[i] = []; for (let j = 0, len1 = origin[i].length; j < len1; j++) { if (origin[i][j] == "") { this.composition[i][j] = null; } else { if (i <= 4) { // 黑方 this.composition[i][j] = { color: "black", text: origin[i][j]}; } else { // 红方 this.composition[i][j] = { color: "red", text: origin[i][j]}; } } } } console.log(this.composition); } // 画所有的棋子 drawPieces() { for (let i = 0, len = this.composition.length; i < len; i++) { for (let j = 0, len1 = this.composition[i].length; j < len1; j++) { if (this.composition[i][j]) { // this.composition[i][j].drawOnePiece(); this.drawOnePiece(j, i, this.composition[i][j].text, this.composition[i][j].color) } } } } // 画一个棋子 drawOnePiece(x, y, text, color) { var r = this.cellWidth * 0.45; var xx = this.cellWidth * x + this.cellWidth; var yy = this.cellWidth * y + this.cellWidth; var bgColor = "black"; //"#eab885"; this.ctx.save(); let radgrad = this.ctx.createRadialGradient(xx, yy, r, xx, yy, r*0.8); radgrad.addColorStop(0, "#de9555"); radgrad.addColorStop(0.75, "#de9555"); radgrad.addColorStop(1, "#eab885"); this.ctx.fillStyle = radgrad; this.ctx.beginPath(); this.ctx.arc(xx, yy, r, 0, Math.PI*2); this.ctx.shadowOffsetX = 3; this.ctx.shadowOffsetY = 3; this.ctx.shadowBlur = 1; this.ctx.shadowColor = "rgba(53,29,4,0.7)"; this.ctx.fill(); this.ctx.restore(); this.ctx.font = `${r*2*0.75}px 隶书`; // 隶书 方正舒体 this.ctx.fillStyle = color; this.ctx.textBaseline = "middle"; this.ctx.textAlign = "center"; this.ctx.fillText(text, xx, yy); } // hightLight(x,y){ // // } goStep(x, y) { // 已经选择了——1.换一个;(2.移动;3.吃子;)4.乱走; // 没有选择——1.选一个;2.乱选; if (Object.keys(this.toMove).length) { if (this.composition[x] && this.composition[x][y] && this.composition[x][y].color == this.active) { // 选择我方的棋子 this.chooseToMove(x, y); } else { // 选择敌方的棋子 if (this.inRange(x, y)) { // 吃子 this.move(x, y); } else { // 乱选 console.log("还没有轮到你走棋"); } } } else { if (this.composition[x] && this.composition[x][y] && this.composition[x][y].color == this.active) { // 选择我方的棋子 this.chooseToMove(x, y); } } // 点在棋子上——选择、吃子、乱点 // 点在空位置上——移动、乱移动 /*if(this.composition[x][y]){ // 注意,这里的x和y的顺序没有写错 if(this.composition[x] && this.composition[x][y].color == this.active){ // 选择我方的棋子 this.chooseToMove(x, y); }else{// 选择敌方的棋子 if(this.inRange(x, y)){ // 吃子 this.move(x, y); }else{ // 乱选 console.log("还没有轮到你走棋"); } } }else{ if(this.inRange(x, y)){ // 移动到空位置 this.move(x, y); }else{ // 乱移动 console.warn("好好走"); } }*/ } // 已选择棋子是否可以移动 oneCanMove() { if (this.moveRange.length) { return true; } else { return false; } } // 选择移动的棋子 chooseToMove(x, y) { this.renderUi(); this.getMoveRange(x, y); this.hint(); this.toMove = {}; if (this.oneCanMove()) { this.toMove.x = x; this.toMove.y = y; this.toMove.data = this.composition[x][y]; //this.highLight(); } else { this.clearChoose(); console.warn("这个棋子不可以移动"); } // console.log(this.toMove, "选择后的要移动的棋子") } // 判断移动的最终位置是否在移动范围内 inRange(x, y) { var flag = false; for (let i = 0, len = this.moveRange.length; i < len; i++) { if (x == this.moveRange[i].x && y == this.moveRange[i].y) { flag = true; break; } } return flag; } // 是否为敌方 或 空 走棋用的判断 isEnemyOrEmpty(x, y, color) { if (this.composition[x] && this.composition[x][y] === null) { return true; } else { if (this.composition[x] && this.composition[x][y] && this.composition[x][y].color != color) { return true; } else { return false; } } } // 显示可以走的位置 hint() { //console.log(this.moveRange,"移动范围") for (let i = 0, len = this.moveRange.length; i < len; i++) { this.drawHint(this.moveRange[i].x, this.moveRange[i].y); } } // 画一个提示点 drawHint(x, y) { this.ctx.beginPath(); var cx = this.cellWidth * y + this.cellWidth; var cy = this.cellWidth * x + this.cellWidth; this.ctx.arc(cx, cy, this.cellWidth*0.1, 0, Math.PI*2); this.ctx.fillStyle = "#e73480"; this.ctx.fill(); } // 是否为空判断 isEmpty(x, y) { if (this.composition[x] && this.composition[x][y] === null) { return true; } else { return false; } } // 是否为敌判断 isEnemy(x, y, color) { if (this.composition[x] && this.composition[x][y] && this.composition[x][y].color != color) { return true; } else { return false; } } // 已选择棋子的移动范围 参数:棋子在棋局中的位置 getMoveRange(x, y) { // this.moveRange = []; var moveRange = []; var color = this.composition[x] && this.composition[x][y].color; var darr; // 需要判断的移动方向 switch (this.composition[x][y].text) { case "車": case "车": for (let j = 1; j < y+1; j++) { if (this.isEmpty(x, y-j)) { moveRange.push({ x: x, y: y-j }); } else { if (this.isEnemy(x, y-j, color)) { moveRange.push({ x: x, y: y-j }); } break; } } for (let j = 1; j < x+1; j++) { if (this.isEmpty(x-j, y)) { moveRange.push({ x: x-j, y: y }); } else { if (this.isEnemy(x-j, y, color)) { moveRange.push({ x: x-j, y: y }); } break; } } for (let j = 1; j < 9-y; j++) { if (this.isEmpty(x, y+j)) { moveRange.push({ x: x, y: y+j }); } else { if (this.isEnemy(x, y+j, color)) { moveRange.push({ x: x, y: y+j }); } break; } } for (let j = 1; j < 10-x; j++) { if (this.isEmpty(x+j, y)) { moveRange.push({ x: x+j, y: y }); } else { if (this.isEnemy(x+j, y, color)) { moveRange.push({ x: x+j, y: y }); } break; } } break; case "馬": case "马": if (this.isEnemyOrEmpty(x+1, y+2, color)) { if (this.composition[x] && this.composition[x][y+1] === null) { moveRange.push({ x: x+1, y: y+2 }); } } if (this.isEnemyOrEmpty(x+1, y-2, color)) { if (this.composition[x] && this.composition[x][y-1] === null) { moveRange.push({ x: x+1, y: y-2 }); } } if (this.isEnemyOrEmpty(x+2, y+1, color)) { if (this.composition[x+1] && this.composition[x+1][y] === null) { moveRange.push({ x: x+2, y: y+1 }); } } if (this.isEnemyOrEmpty(x+2, y-1, color)) { if (this.composition[x+1] && this.composition[x+1][y] === null) { moveRange.push({ x: x+2, y: y-1 }); } } if (this.isEnemyOrEmpty(x-2, y+1, color)) { if (this.composition[x-1] && this.composition[x-1][y] === null) { moveRange.push({ x: x-2, y: y+1 }); } } if (this.isEnemyOrEmpty(x-2, y-1, color)) { if (this.composition[x-1] && this.composition[x-1][y] === null) { moveRange.push({ x: x-2, y: y-1 }); } } if (this.isEnemyOrEmpty(x-1, y+2, color)) { if (this.composition[x] && this.composition[x][y+1] === null) { moveRange.push({ x: x-1, y: y+2 }); } } if (this.isEnemyOrEmpty(x-1, y-2, color)) { if (this.composition[x] && this.composition[x][y-1] === null) { moveRange.push({ x: x-1, y: y-2 }); } } break; case "象": case "相": var rowlow, rowup, collow = 0, colup = 8; // 行和列的判断上下限 if (x > 4) { // 下方一边 rowlow = 5; rowup = 9; } else { // 上方一边 rowlow = 0; rowup = 4; } if (x-2 >= rowlow && y-2 >= collow) { if (this.isEnemyOrEmpty(x-2, y-2, color)) { if (this.composition[x-1] && this.composition[x-1][y-1] === null) { moveRange.push({ x: x-2, y: y-2 }); } } } if (x-2 >= rowlow && y+2 <= colup) { if (this.isEnemyOrEmpty(x-2, y+2, color)) { if (this.composition[x-1] && this.composition[x-1][y+1] === null) { moveRange.push({ x: x-2, y: y+2 }); } } } if (x+2 <= rowup && y-2 >= collow) { if (this.isEnemyOrEmpty(x+2, y-2, color)) { if (this.composition[x+1] && this.composition[x+1][y-1] === null) { moveRange.push({ x: x+2, y: y-2 }); } } } if (x+2 <= rowup && y+2 <= colup) { if (this.isEnemyOrEmpty(x+2, y+2, color)) { if (this.composition[x+1] && this.composition[x+1][y+1] === null) { moveRange.push({ x: x+2, y: y+2 }); } } } break; case "仕": case "士": var rowlow, rowup, collow = 3, colup = 5; // 行和列的判断上下限 if (x > 4) { // 下方一边 rowlow = 7; rowup = 9; } else { // 上方一边 rowlow = 0; rowup = 2; } if (this.isEnemyOrEmpty(x-1, y-1, color)) { if (x-1 >= rowlow && y-1 >= collow) { moveRange.push({ x: x-1, y: y-1 }); } } if (this.isEnemyOrEmpty(x-1, y+1, color)) { if (x-1 >= rowlow && y+1 <= colup) { moveRange.push({ x: x-1, y: y+1 }); } } if (this.isEnemyOrEmpty(x+1, y-1, color)) { if (x+1 <= rowup && y-1 >= collow) { moveRange.push({ x: x+1, y: y-1 }); } } if (this.isEnemyOrEmpty(x+1, y+1, color)) { if (x+1 <= rowup && y+1 <= colup) { moveRange.push({ x: x+1, y: y+1 }); } } break; case "将": case "帥": case "帅": var rowlow, rowup, collow = 3, colup = 5; // 行和列的判断上下限 if (x > 4) { // 下方一边 rowlow = 7; rowup = 9; } else { // 上方一边 rowlow = 0; rowup = 2; } if (this.isEnemyOrEmpty(x-1, y, color)) { if (x-1 >= rowlow) { // 老将不越上边界 moveRange.push({ x: x-1, y: y }); } } if (this.isEnemyOrEmpty(x+1, y, color)) { if (x+1 <= rowup) { // 老将不越下边界 moveRange.push({ x: x+1, y: y }); } } if (this.isEnemyOrEmpty(x, y-1, color)) { if (y-1 >= collow) { // 老将不越左边界 moveRange.push({ x: x, y: y-1 }); } } if (this.isEnemyOrEmpty(x, y+1, color)) { if (y+1 <= colup) { // 老将不越右边界 moveRange.push({ x: x, y: y+1 }); } } break; case "炮": case "砲": var count = 0; // 上方 count = 0; for (let j = 1; j < y+1; j++) { if (this.composition[x][y-j] === null) { if (count === 0) { moveRange.push({ x: x, y: y-j }); } } else if (this.composition[x].........完整代码请登录后点击上方下载按钮下载查看
网友评论0