<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
*{padding:0 ;margin: 0;}
html,body{width: 100%;height: 100%;}
canvas{margin: 0 auto;display: block;}
</style>
</head>
<body>
<canvas id="chess">不支持canvas</canvas> <script src="./myChess.js" type="text/javascript" charset="utf-8"></script>
<!--<script src="js/chessPiece.js" type="text/javascript" charset="utf-8"></script>-->
<script type="text/javascript">
var chess = new Chess("chess");
</script>
</body>
</html>

  

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][y-j].color){
count++;
if(count === 2 && this.composition[x][y-j].color != color){
moveRange.push({x: x, y: y-j});
}
} if(count >= 2){
break;
}
}
// 下
count = 0;
for(let j = 1; j<9-y; j++){
if(this.composition[x][y+j] === null){
if(count === 0){
moveRange.push({x: x, y: y+j});
}
}else if(this.composition[x][y+j].color){
count++;
if(count === 2 && this.composition[x][y+j].color != color){
moveRange.push({x: x, y: y+j});
}
} if(count >= 2){
break;
}
}
// 左
count = 0;
for(let j = 1; j<x+1; j++){
if(this.composition[x-j][y] === null){
if(count === 0){
moveRange.push({x: x-j, y: y});
}
}else if(this.composition[x-j][y].color){
count++;
if(count === 2 && this.composition[x-j][y].color != color){
moveRange.push({x: x-j, y: y});
}
} if(count >= 2){
break;
}
}
// 右
count = 0;
for(let j = 1; j<10-x; j++){
if(this.composition[x+j][y] === null){
if(count === 0){
moveRange.push({x: x+j, y: y});
}
}else if(this.composition[x+j][y].color){
count++;
if(count === 2 && this.composition[x+j][y].color != color){
moveRange.push({x: x+j, y: y});
}
} if(count >= 2){
break;
}
}
break;
case "兵":
case "卒":
if(this.bottomColor == color){
if(x >= 5){// 过河前
if(this.isEnemyOrEmpty(x-1, y, color)){
moveRange.push({x: x-1, y: y});
}
}else{// 过河后
if(this.isEnemyOrEmpty(x-1, y, color)){
moveRange.push({x: x-1, y: y});
}
if(this.isEnemyOrEmpty(x, y-1, color)){
moveRange.push({x: x, y: y-1});
}
if(this.isEnemyOrEmpty(x, y+1, color)){
moveRange.push({x: x, y: y+1});
}
}
}else{
if(x <= 4){// 过河前
if(this.isEnemyOrEmpty(x+1, y, color)){
moveRange.push({x: x+1, y: y});
}
}else{// 过河后
if(this.isEnemyOrEmpty(x+1, y, color)){
moveRange.push({x: x+1, y: y});
}
if(this.isEnemyOrEmpty(x, y-1, color)){
moveRange.push({x: x, y: y-1});
}
if(this.isEnemyOrEmpty(x, y+1, color)){
moveRange.push({x: x, y: y+1});
}
}
} break;
default: console.warn("兵种(%s)不认识",this.composition[x][y].text);
}
this.moveRange = moveRange;
return moveRange;
} // 移动 1.选择需要移动的棋子 2.点击推荐的可以移动的位置 3.之前的位置赋值为空,结束的位置赋值为当前棋子
move(x, y) {
this.composition[x][y] = this.toMove.data;
this.composition[this.toMove.x][this.toMove.y] = null;
console.log("%c%s", "fontsize: 20px; color:"+ this.active +";", this.chessManual(this.toMove.x, this.toMove.y, x, y, this.toMove.data.text, this.toMove.data.color));
this.chessSteps.push({
step:this.chessManual(this.toMove.x, this.toMove.y, x, y, this.toMove.data.text, this.toMove.data.color),
qijv:this.deepClone(this.composition),
});
//console.log("移动棋子:%o",this.composition[x][y]);
this.exchange();
this.clearChoose(); this.renderUi();
} // 清除选中的棋子
clearChoose() {
delete this.toMove.x;
delete this.toMove.y;
delete this.toMove.data;
} // 生成棋谱 // x增大为进减小为退
chessManual(x0, y0, x1, y1, text, color) { // 马 士 象需要特殊处理
// console.log(text, color, this.bottomColor);
var res = "";
var dx = x1 - x0;
if(color == this.bottomColor){
switch(text) {
case "車":
case "车":
case "炮":
case "砲":
case "将":
case "帅":
case "帥":
case "兵":
case "卒":
if (dx < 0) {
res = text + this.translateNum(9 - y0) + "进" + this.translateNum(-dx);
}else if (dx == 0) {
res = text + this.translateNum(9 - y0) + "平" + this.translateNum(9 - y1);
}else {
res = text + this.translateNum(9 - y0) + "退" + this.translateNum(dx);
}
break;
case "马":
case "馬":
case "士":
case "仕":
case "象":
case "相":
if (dx < 0) {
res = text + this.translateNum(9 - y0) + "进" + this.translateNum(9 - y1);
}else {
res = text + this.translateNum(9 - y0) + "退" + this.translateNum(9 - y1);
}
break;
default: console.warn("棋子%s无法识别",text);
}
}else{
switch(text) {
case "車":
case "车":
case "炮":
case "砲":
case "将":
case "帅":
case "帥":
case "兵":
case "卒":
if (dx < 0) {
res = text + this.translateNum(y0 + 1) + "退" + this.translateNum(-dx);
}else if (dx == 0) {
res = text + this.translateNum(y0 + 1) + "平" + this.translateNum(y1 + 1);
}else {
res = text + this.translateNum(y0 + 1) + "进" + this.translateNum(dx);
}
break;
case "马":
case "馬":
case "士":
case "仕":
case "象":
case "相":
if (dx < 0) {
res = text + this.translateNum(y0 + 1) + "退" + this.translateNum(y1 + 1);
}else {
res = text + this.translateNum(y0 + 1) + "进" + this.translateNum(y1 + 1);
}
break;
default: console.warn("棋子%s无法识别",text);
}
} return res;
} // 将数组转换成汉字
translateNum(num) {
var res = "";
switch(num){
case 0: res = "零"; break;
case 1: res = "一"; break;
case 2: res = "二"; break;
case 3: res = "三"; break;
case 4: res = "四"; break;
case 5: res = "五"; break;
case 6: res = "六"; break;
case 7: res = "七"; break;
case 8: res = "八"; break;
case 9: res = "九"; break;
default: console.warn("请输入0-9的一个整数");
}
return res;
} // 深度反转数组
deepReverse(arr){
if(arr instanceof Array) {
var copy = this.deepClone(arr);
var reverse = copy.reverse(); for(var i = 0, len = reverse.length; i < len; i++) {
if(reverse[i] instanceof Array){
reverse[i] = this.deepReverse(reverse[i]);
}
}
return reverse;
} throw new Error("此函数只能反转数组");
} // 深拷贝
deepClone(values) {
var copy; // Handle the 3 simple types, and null or undefined
if(null == values || "object" != typeof values) return values; // Handle Date
if(values instanceof Date) {
copy = new Date();
copy.setTime(values.getTime());
return copy;
} // Handle Array
if(values instanceof Array) {
copy = [];
for(var i = 0, len = values.length; i < len; i++) {
copy[i] = this.deepClone(values[i]);
}
return copy;
} // Handle Object
if(values instanceof Object) {
copy = {};
for(var attr in values) {
if(values.hasOwnProperty(attr)) copy[attr] = this.deepClone(values[attr]);
}
return copy;
} throw new Error("Unable to copy values! Its type isn't supported.");
}
}

  

js+canvas实现象棋的布局、走棋位置提示、走棋代码的更多相关文章

  1. browser-sync第一次打开提示路径错误,path.js应该输出字符串;之后重启一直提示插入代码片段,插入后无效依然提示

    网上找到gulp类似提示,是node版本问题. nvm派上用场, browser-sync@2.23.6,node用的8.3.0 解决办法: nvm install 7.8.0 nvm use 7.8 ...

  2. HTML5学习总结——canvas绘制象棋(canvas绘图)

    一.HTML5学习总结——canvas绘制象棋 1.第一次:canvas绘制象棋(笨方法)示例代码: <!DOCTYPE html> <html> <head> & ...

  3. JS+canvas实现人机大战之五子棋

    效果图: html代码如下: <!DOCTYPE html><html>    <head>        <meta charset="utf-8 ...

  4. 原生JS+Canvas实现五子棋游戏

    一.功能模块 先看下现在做完的效果: 线上体验:https://wj704.github.io/five_game.html 主要功能模块为: 1.人机对战功能 2.悔棋功能 3.撤销悔棋功能 二.代 ...

  5. js canvas游戏初级demo-躲避障碍物

    在线演示地址 http://200ok.fun:3100/html/game_demo.html 继上次js canvas游戏初级demo-上下左右移动(https://www.cnblogs.com ...

  6. 【微信小程序项目实践总结】30分钟从陌生到熟悉 web app 、native app、hybrid app比较 30分钟ES6从陌生到熟悉 【原创】浅谈内存泄露 HTML5 五子棋 - JS/Canvas 游戏 meta 详解,html5 meta 标签日常设置 C#中回滚TransactionScope的使用方法和原理

    [微信小程序项目实践总结]30分钟从陌生到熟悉 前言 我们之前对小程序做了基本学习: 1. 微信小程序开发07-列表页面怎么做 2. 微信小程序开发06-一个业务页面的完成 3. 微信小程序开发05- ...

  7. [JS,Canvas]日历时钟

    [JS,Canvas]日历时钟 Html: <!doctype html> <html> <head> <meta charset="UTF-8&q ...

  8. 利用js+canvas实现的时钟效果图

    canvas+js时钟特效 运用js+canvas方面的知识完成一个时钟的效果图,再利用for循环实现指针的转动效果: <!--网页文档的声明--> <!doctype html&g ...

  9. JS基础 复习: Javascript的书写位置

    爱创课堂JS基础 复习: Javascript的书写位置复习 js书写位置:body标签的最底部.实际工作中使用书写在head标签内一对script标签里.alert()弹出框.console.log ...

随机推荐

  1. Spring_Hibernate整合准备

    1,Spring整合Hibernate   整合什么? 1)由IOC容器来生成Hibernate的SessionFactory 2)让Hibernate使用上Spring的声明式事务 2,整合步骤 1 ...

  2. Excel函数学习:HLOOKUP函数

    Excel函数学习:HLOOKUP函数 HLOOKUP函数查找表的第一行中的值,返回该表中与找到的值在同一列的另一个值. 什么情况下使用HLOOKUP? HLOOKUP函数可以在查找行中找到精确匹配值 ...

  3. 玩转 Django2.0 笔记1

    模板静态  路由 urls.py urlpatterns = [ path("<year>/<int:month>/<slug:day>",my ...

  4. EL表达式如何读取一个string型的list 一个单纯的的字符串list

    <c:forEach begin="0" end="${columnList.size()-1}" var="i"> ${ co ...

  5. Linux下安装docker,更改镜像仓库地址,并部署springboot应用

    今天做不成的事,明天也不会做好. 各位同学大家好,随着docker的快速发展,越来越多的人开始使用,一方面随着容器化这个趋势越来越火,docker成为了其中的佼佼者:二来容器化确实降低了运维的门槛,让 ...

  6. Struts_登录练习(未配置拦截器)

    1.在domain中建个User.java和其配置文件 并在hibernate.cfg.xml中加入配置 2.配置struts文件 3.在jsp文件中修改action地址和name属性,并标注错误信息 ...

  7. 洛谷P2381 圆圆舞蹈

    P2381 圆圆舞蹈 题目描述 熊大妈的乃修在时针的带领下,围成了一个圆圈舞蹈,由于没有严格的教育,奶牛们之间的间隔不一致. 奶牛想知道两只最远的奶牛到底隔了多远.奶牛A到B的距离为A顺时针走和逆时针 ...

  8. Leetcode40. Combination Sum组合总数2 II

    给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的每个数字在每个组合中只能使用一次. ...

  9. Leetcode96.Unique Binary Search Trees不同的二叉搜索树

    给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种? 示例: 输入: 3 输出: 5 解释: 给定 n = 3, 一共有 5 种不同结构的二叉搜索树: 假设n个节点存在二叉排序树的 ...

  10. IIS 配置问题

    1 IIS错误需要重新运行配置 重新注册.netframework. 解决方式:cmd   C:\Windows\Microsoft.NET\Framework\v4.0.30319 aspnet_r ...