修复界面bug并增加了自动提示是否输赢的 关于之前博客"html5 canvas 绘制象棋(将持续改进)"

<!DOCTYPE HTML>
<html >
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>象棋</title>
<style>
canvas.middle{
border:1px solid #dddddd;
cursor:crosshair;
</style>
</head>
<body>
<canvas width="600px" height="600px" id="middle" class="middle">


</canvas >




<script type="text/javascript">
var mycanvas = document.getElementById("middle");
var stepCount = 0;
ctx = mycanvas.getContext("2d");
var layout={
offsetWidth: 600,//canvas 中用于作为绘图面板的总宽度
offsetHeight: 600,
cell: 50,
padding: 30,
middleHeight: 80
};
var style={
board: {
bgColor: "rgb(255,200,100)",
border: "rgb(100,255,200)",
lineWidth: 2,
middle_bound: {
fontColor: "rgba(0,255,0,1)",
fontSize: 18,
fontName: "Arial"
}
},
qizi: {
radius: 16, //半径
bgColor: "rgba(200,200,200,1)",
sideColor: "rgba(200,180,220,1)",
red_fontColor: "rgba(255,0,0,1)",
black_fontColor: "rgba(0,0,0,1)",
fontSize: 14,
fontName: "Arial",
goColor: "rgb(255,0,0)"
}
};
function getPosToPanel(xIndex, yIndex){//获取棋盘上qizi[yIndex][xIndex]处棋子的中心位置
var temp = {x:xIndex,y:yIndex};
temp.x = layout.padding + xIndex * layout.cell;
temp.y = layout.padding + yIndex * layout.cell;
if(yIndex >= 5){
temp.y += layout.middleHeight - layout.cell;
}
return temp;
}
function getXY(evt){ // get click pos base on <canvas>, so(0,0) is at the left-top of <canvas>
var clientX = evt.clientX, clientY = evt.clientY;
var temp = {x : 0, y:0};
var parObj=mycanvas;
var offset=mycanvas.offsetLeft;
while(parObj=parObj.offsetParent){
offset+=parObj.offsetLeft;
}
    temp.x = clientX - offset;
var parObj=mycanvas;
var offset=mycanvas.offsetTop;
while(parObj=parObj.offsetParent){
offset+=parObj.offsetTop;
}
    temp.y = clientY - offset;
return temp;
}
function getQiziClickIndex(evt){ //根据点击事件,返回点击范围所在处属于哪个索引的棋子,返回值为0-89,-1表示错误值
var temp = getXY(evt);
temp.x = temp.x - layout.padding;
temp.y = temp.y - layout.padding;
var i, j;
i = Math.round(temp.x / layout.cell);
if( temp.y <= layout.cell * 4 + style.qizi.radius ){
j = Math.round(temp.y / layout.cell);//求出距离第i行,j列最近
}else if( temp.y >= layout.cell * 4 + layout.middleHeight - style.qizi.radius){//在楚河汉界的下方
j = Math.round( (temp.y - (layout.cell * 4 + layout.middleHeight) ) / layout.cell ) + 5;
}else{
return -1;
}
if( i >= 9 || j >= 10 || i < 0 || j < 0 ){
return -1;
}
var pos = getPosToPanel(i, j);
pos.x -= layout.padding;
pos.y -= layout.padding;
if( Math.pow(temp.x - pos.x, 2) + Math.pow(temp.y - pos.y, 2) < style.qizi.radius *style.qizi.radius ){//在棋子范围内
return i + j * 9;
}
return -1;// 不在棋子范围内
}
var qiziIndex = new Array(90);
var qiziyanse = new Array(90);
function initQiziArray(){
for( var i = 0; i < qiziIndex.length; ++i){
qiziIndex[i] = "";
qiziyanse[i] = 0;//-1 red, 1 black, 0 none
}
qiziIndex[0] = qiziIndex[8] = "车";
qiziIndex[1] = qiziIndex[7] = "马";
qiziIndex[2] = qiziIndex[6] = "相";
qiziIndex[3] = qiziIndex[5] = "士";
qiziIndex[4] = "将";
qiziIndex[19] = qiziIndex[25] = "炮";
qiziIndex[27] = qiziIndex[29] = qiziIndex[31] = qiziIndex[33] = qiziIndex[35] = "兵";
qiziyanse[0] = qiziyanse[8] =qiziyanse[1] =qiziyanse[7] =qiziyanse[2] = qiziyanse[6] =qiziyanse[3]
=qiziyanse[5] =qiziyanse[4] =qiziyanse[19] =qiziyanse[25] =qiziyanse[27] =qiziyanse[29]
=qiziyanse[31] =qiziyanse[33] =qiziyanse[35] = 1;
qiziIndex[81] = "车";
qiziIndex[89] = "车";
qiziIndex[82] = "马";
qiziIndex[88] = "马";
qiziIndex[83] = "相";
qiziIndex[87] = "相";
qiziIndex[84] = qiziIndex[86] = "士";
qiziIndex[85] = "将";
qiziIndex[64] = "炮";
qiziIndex[70] = "炮";
qiziIndex[54] = qiziIndex[56] = qiziIndex[58] = qiziIndex[60] = qiziIndex[62] = "兵";
qiziyanse[81] = qiziyanse[89] =qiziyanse[82] =qiziyanse[88] =qiziyanse[83] =qiziyanse[87]
=qiziyanse[84] =qiziyanse[85] =qiziyanse[86] =qiziyanse[64] =qiziyanse[70] =qiziyanse[54]
=qiziyanse[56] =qiziyanse[58] =qiziyanse[60] = qiziyanse[62] = -1;
//qiziIndex[10] = "相";qiziyanse[10]=1;
}
initQiziArray();
function drawQizi(name,index, red_black){//在指定的棋子位置,画出指定的棋子
if(red_black != -1 && red_black != 1 || index > 89 || index <0 ){
return;
}
var pos = getPosToPanel( index%9, Math.floor(index/9));
var x = pos.x;
var y = pos.y;
ctx.fillStyle=style.qizi.bgColor; //定义演示
ctx.strokeStyle=style.qizi.sideColor;
ctx.lineWidth=style.board.lineWidth;
ctx.beginPath(); //从新开始画,防止冲突重叠
ctx.arc(x, y,style.qizi.radius, Math.PI*0,Math.PI*2,true); //x坐标,y坐标,直径,始,终,时针方向
ctx.closePath(); //结束画布,防止冲突重叠
ctx.fill(); //结束渲染
ctx.font = "Normal " + style.qizi.fontSize + "px " + style.qizi.fontName;
ctx.fillStyle= ((red_black == -1) ? style.qizi.red_fontColor : style.qizi.black_fontColor); //定义演示
ctx.fillText(name, x, y);
ctx.stroke();
qiziyanse[index] = red_black;
qiziIndex[index] = name;
}




function drawChess(){//在棋盘上画出所有棋子
var i = 0;
for(i = 0; i<90; ++i){
drawQizi(qiziIndex[i], i, qiziyanse[i]) ;
}
}
function canJump(srcIndex, dstIndex){// 判断srcIndex的棋子是否可以吃掉dstIndex的棋子,或者srcIndex 是否可以跳到dstIndex处
if(srcIndex <0 || srcIndex >= 90 || dstIndex < 0 || dstIndex >= 90  //棋子不在棋盘内
|| qiziyanse[srcIndex] == qiziyanse[dstIndex] || qiziyanse[srcIndex] == 0 ||
qiziyanse[srcIndex] == -1 && stepCount % 2 == 1 || qiziyanse[srcIndex] == 1 && stepCount % 2 == 0 ){//空子或者同色棋子不可以发生 吃子或走棋 行为
return false;
}
var xIndex = {};
var yIndex = {};
xIndex.src = srcIndex%9;
xIndex.dst = dstIndex%9;
yIndex.src = Math.floor(srcIndex/9);
yIndex.dst = Math.floor(dstIndex/9);
switch(qiziIndex[srcIndex]){
case "车":
var existMiddleQizi = false;
var increase = 0;
if(xIndex.src == xIndex.dst){
increase = 9;
}else if(yIndex.src == yIndex.dst){
increase = 1;
}
if( increase > 0 ){
var min = srcIndex, max = dstIndex;
if(srcIndex > dstIndex){
min = dstIndex;
max = srcIndex;
}
for(var i = min + increase; i < max; i+= increase){
if(qiziyanse[i] != 0){
existMiddleQizi = true;
break;
}
}
return !existMiddleQizi;
}else{
return false;
}
case "马":
return Math.abs(xIndex.src-xIndex.dst) * Math.abs(yIndex.src - yIndex.dst) == 2 &&
( Math.abs(xIndex.src-xIndex.dst)==1 && qiziIndex[xIndex.src + (yIndex.src+yIndex.dst)/2 * 9] == "" ||
 Math.abs(yIndex.src-yIndex.dst)==1 && qiziIndex[yIndex.src*9 + (xIndex.src+xIndex.dst)/2 % 9] == ""
); //成 ”日" 且不能 别着 马腿
        case "炮":
var min = srcIndex, max = dstIndex;
var increase = 0;
if( xIndex.src == xIndex.dst ){
increase = 9;
}else if(yIndex.src == yIndex.dst){
increase = 1;
}else{
return false;
}
var middleQiziCount = 0;
if(srcIndex > dstIndex){
min = dstIndex;
max = srcIndex;
}
for(var i = min + increase; i < max && middleQiziCount < 2; i+= increase){
if(qiziyanse[i] != 0){
++middleQiziCount;
}
}
return qiziyanse[srcIndex] != qiziyanse[dstIndex] && qiziyanse[dstIndex] != 0 && middleQiziCount == 1 || qiziyanse[dstIndex] == 0 && middleQiziCount == 0;
case "兵":
case "卒":
return Math.abs(xIndex.dst - xIndex.src) == 1 && yIndex.src == yIndex.dst && (yIndex.src - 4.5)*qiziyanse[srcIndex] > 0
|| xIndex.src == xIndex.dst && qiziyanse[srcIndex]*(dstIndex - srcIndex) == 9 ;
case "相":
case "象":
return Math.abs(xIndex.src-xIndex.dst) == 2 && Math.abs(yIndex.src - yIndex.dst) == 2 && qiziIndex[(srcIndex + dstIndex)>>1] == "";
case "将":
case "帅":
   return (Math.abs(xIndex.src - xIndex.dst) + Math.abs(yIndex.src-yIndex.dst) == 1) && Math.abs(xIndex.dst - 4) <= 1 &&
(qiziyanse[ srcIndex ] == -1 ? Math.abs(yIndex.dst - 8) <= 1 : Math.abs(yIndex.dst - 1 ) <= 1);
case "士":
   return (Math.abs(xIndex.src - xIndex.dst) == 1 && Math.abs(yIndex.src-yIndex.dst) == 1) && Math.abs(xIndex.dst - 4) <= 1 &&
(qiziyanse[srcIndex] == -1 ? Math.abs(yIndex.dst - 8) <= 1 : Math.abs(yIndex.dst - 1 ) <= 1);
default:
return false;
}
}
function drawChessPanel(){
// draw bgColor
ctx.fillStyle=style.board.bgColor;
ctx.beginPath();
ctx.rect(0, 0, layout.offsetWidth, layout.offsetHeight);
ctx.closePath();
ctx.fill();
// prepare to draw lines
var p = layout.padding,
s = layout.cell,
w = layout.cell * 8,
h = layout.cell * 4;
m = layout.middleHeight;
ctx.strokeStyle=style.board.border;
ctx.lineWidth= style.board.lineWidth;
ctx.beginPath();
// horizonal lines
for(var i = 0; i <= 4; i++){
ctx.moveTo(p, s * i + p + 0.5);
ctx.lineTo(w + p, s * i + p + 0.5);
}
var fixL = p + h + m;
for(var i = 5; i <= 9; i++){
ctx.moveTo(p, s * (i - 5) + fixL + 0.5);
ctx.lineTo(w + p, s * (i - 5) + fixL + 0.5);
}
// vertical lines
ctx.moveTo(p + 0.5, p);
ctx.lineTo(p + 0.5, 2*h + m + p);
ctx.moveTo(w + p + 0.5, p);
ctx.lineTo(w + p + 0.5, 2*h + m + p);
for(var i = 1; i < 8; i++){
ctx.moveTo(s * i + p + 0.5, p);
ctx.lineTo(s * i + p + 0.5, s * 4 + p);
ctx.moveTo(s * i + p + 0.5 , h + p + m);
ctx.lineTo(s * i + p + 0.5, h *2 + m + p );
}
 //"X" shapes
ctx.moveTo(s * 3 + p, p);
ctx.lineTo(s * 5 + p, s * 2 + p);
ctx.moveTo(s * 5 + p, 0 + p);
ctx.lineTo(s * 3 + p + 0.5, s * 2 + p);
ctx.moveTo(s * 3 + p + 0.5, h + s * 2 + m + p);
ctx.lineTo(s * 5 + p + 0.5,  h + s * 4 + m + p);
ctx.moveTo(s * 5 + p + 0.5, h + s * 2 + m + p);
ctx.lineTo(s * 3 + p, h + s * 4 + m + p);
ctx.closePath();
ctx.stroke();




ctx.font= "Normal " + style.board.middle_bound.fontSize + "px " + style.board.middle_bound.fontName;
ctx.fillStyle=style.board.middle_bound.fontColor;
ctx.textAlign="center";
ctx.textBaseline="middle";
ctx.fillText("楚河", p + s * 2, p + s * 4 + layout.middleHeight/2);
ctx.fillText("漢界", p + s * 6, p + s * 4 + layout.middleHeight/2);
ctx.stroke();
}


drawChessPanel();
drawChess();
function drawClearQizi(xIndex, yIndex){
var pos;
pos = getPosToPanel(xIndex, yIndex);
var old  = {};
old.bgColor = style.qizi.bgColor; //保存棋子的样式设置
old.sideColor = style.qizi.sideColor;
old.red_fontColor = style.qizi.red_fontColor;
old.black_fontColor = style.qizi.black_fontColor;
old.radius = style.qizi.radius;


style.qizi.bgColor = style.board.bgColor; //使用背景设置
style.qizi.sideColor = style.board.bgColor;
style.qizi.red_fontColor = style.board.bgColor;
style.qizi.black_fontColor = style.board.bgColor;
style.qizi.radius = style.qizi.radius + 1 ; // 还没搞清为何这个地方要增加一个才行
drawQizi("", xIndex + yIndex*9 , qiziyanse[yIndex*9 + xIndex]); //用背景色的圆恢复棋盘颜色


style.qizi.bgColor = old.bgColor; //还原棋子的样式设置
style.qizi.sideColor = old.sideColor;
style.qizi.red_fontColor = old.red_fontColor;
style.qizi.black_fontColor = old.black_fontColor;
style.qizi.radius = old.radius;






ctx.strokeStyle=style.board.border;
ctx.lineWidth= style.board.lineWdith;
ctx.beginPath();
var lineTop = Math.max(pos.y - style.qizi.radius - style.board.lineWidth , layout.padding);
var lineBottom = Math.min(pos.y + style.qizi.radius + style.board.lineWidth , layout.middleHeight + 8 * layout.cell + layout.padding);
if (yIndex == 4 ){   // 楚河汉界 的边界棋子绘制
lineBottom = layout.padding + layout.cell * 4;
if( xIndex == 0 || xIndex == 8){
lineBottom += style.qizi.radius + style.board.lineWidth;
}
}else if(yIndex == 5 ){
lineTop = layout.padding + layout.cell * 4 + layout.middleHeight ;
if( xIndex == 0 || xIndex == 8){
lineTop -= style.qizi.radius + style.board.lineWidth;
}
}
ctx.moveTo(pos.x + 0.5 , lineTop);
ctx.lineTo(pos.x + 0.5,  lineBottom);
ctx.moveTo(Math.max(pos.x - style.qizi.radius - style.board.lineWidth, layout.padding), pos.y + 0.5);
ctx.lineTo(Math.min(pos.x + style.qizi.radius + style.board.lineWidth, layout.padding + layout.cell * 8), pos.y + 0.5);
//绘制将帅的斜线
var r_sqrt2 = Math.ceil(style.qizi.radius/Math.sqrt(2)) + 1;
if(xIndex == 3 && (yIndex == 0 || yIndex == 7) ){
ctx.moveTo(pos.x, pos.y);
ctx.lineTo(pos.x + r_sqrt2, pos.y + r_sqrt2);
}else if(xIndex == 3 && (yIndex == 2 || yIndex == 9) ){
ctx.moveTo(pos.x , pos.y);
ctx.lineTo(pos.x + r_sqrt2, pos.y - r_sqrt2);
}else if(xIndex == 4 && (yIndex == 1 || yIndex == 8) ){
ctx.moveTo(pos.x, pos.y);
ctx.lineTo(pos.x - r_sqrt2, pos.y - r_sqrt2);
ctx.moveTo(pos.x, pos.y);
ctx.lineTo(pos.x + r_sqrt2, pos.y - r_sqrt2);
ctx.moveTo(pos.x, pos.y);
ctx.lineTo(pos.x - r_sqrt2, pos.y + r_sqrt2);
ctx.moveTo(pos.x, pos.y);
ctx.lineTo(pos.x + r_sqrt2, pos.y + r_sqrt2);
}else if(xIndex == 5 && (yIndex == 0 || yIndex == 7) ){
ctx.moveTo(pos.x, pos.y);
ctx.lineTo(pos.x - r_sqrt2, pos.y + r_sqrt2);
}else if(xIndex == 5 && (yIndex == 2 || yIndex == 9) ){
ctx.moveTo(pos.x, pos.y);
ctx.lineTo(pos.x - r_sqrt2, pos.y - r_sqrt2);
}
//结束将帅斜线的绘制


//显示图形
ctx.closePath();
ctx.stroke();


qiziIndex[yIndex*9 + xIndex] = ""; //更新棋盘
qiziyanse[yIndex*9 + xIndex] = 0;
}
function drawFourCross(xIndex, yIndex, color){
var oldStyle = ctx.strokeStyle;
color? ctx.strokeStyle = color : ctx.strokeStyle = style.qizi.goColor;
var pos = getPosToPanel(xIndex, yIndex);
ctx.beginPath();
ctx.moveTo(pos.x - style.qizi.radius, pos.y - style.qizi.radius);
ctx.lineTo(pos.x - style.qizi.radius, pos.y - style.qizi.radius/2);
ctx.moveTo(pos.x - style.qizi.radius, pos.y - style.qizi.radius);
ctx.lineTo(pos.x - style.qizi.radius/2, pos.y - style.qizi.radius);


ctx.moveTo(pos.x - style.qizi.radius, pos.y + style.qizi.radius);
ctx.lineTo(pos.x - style.qizi.radius, pos.y + style.qizi.radius/2);
ctx.moveTo(pos.x - style.qizi.radius, pos.y + style.qizi.radius);
ctx.lineTo(pos.x - style.qizi.radius/2, pos.y + style.qizi.radius);


ctx.moveTo(pos.x + style.qizi.radius, pos.y - style.qizi.radius);
ctx.lineTo(pos.x + style.qizi.radius/2, pos.y - style.qizi.radius);
ctx.moveTo(pos.x + style.qizi.radius, pos.y - style.qizi.radius);
ctx.lineTo(pos.x + style.qizi.radius, pos.y - style.qizi.radius/2);


ctx.moveTo(pos.x + style.qizi.radius, pos.y + style.qizi.radius);
ctx.lineTo(pos.x + style.qizi.radius, pos.y + style.qizi.radius/2);
ctx.moveTo(pos.x + style.qizi.radius, pos.y + style.qizi.radius);
ctx.lineTo(pos.x + style.qizi.radius/2, pos.y + style.qizi.radius);
ctx.closePath();
ctx.stroke();
ctx.strokeStyle = oldStyle;
}
function drawLastGo(xIndex, yIndex, color){
//drawClearQizi(xIndex, yIndex);
drawFourCross(xIndex, yIndex);
//drawFourCross(xIndex, yIndex, "rgb(0,0,255)");
}
function clearLastGo(xIndex, yIndex){
   drawFourCross(xIndex, yIndex, style.board.bgColor);




}
var isDown = false;
var timer = null;
var g_num_down = -1;
var g_num_up = -1;
mycanvas.onmousedown= function(evt){
g_num_down = getQiziClickIndex(evt);
if(g_num_down != -1){
var oldColor = style.qizi.bgColor;
style.qizi.bgColor = "rgba(200,170,190,1.0)";
drawQizi(qiziIndex[g_num_down], g_num_down, qiziyanse[g_num_down]) ;
style.qizi.bgColor = oldColor;
}
isDown = true;
};
var g_last_go = -1;
var g_last_go2 = -1;
mycanvas.onmouseup = function(evt){
if( !isDown ){
return;
}
g_num_up = getQiziClickIndex(evt);
if(g_num_up != -1 && g_num_down != -1 && canJump(g_num_down, g_num_up) ){
if(g_last_go != -1){
clearLastGo(g_last_go%9, Math.floor(g_last_go/9));
}
if(g_last_go2 != -1)
{
clearLastGo(g_last_go2%9, Math.floor(g_last_go2/9));
}
var oldColor = style.qizi.bgColor;
var whowin = 0;
if(qiziIndex[g_num_up] == "将")
{
whowin = qiziyanse[g_num_down];
}
drawQizi(qiziIndex[g_num_down], g_num_up, qiziyanse[g_num_down]) ;
style.qizi.bgColor=oldColor;
drawClearQizi(g_num_down%9, Math.floor(g_num_down/9));
g_last_go = g_num_down;
g_last_go2 = g_num_up;
drawLastGo(g_num_down%9, Math.floor(g_num_down/9));
drawFourCross(g_num_up%9, Math.floor(g_num_up/9));
stepCount += 1;
if(whowin == -1)
alert("红方胜利");
else if(whowin == 1)
alert("黑方胜利");


}else if( g_num_down != -1 ){
drawQizi(qiziIndex[g_num_down], g_num_down, qiziyanse[g_num_down]) ;
}
isDown = false;
}


</script>
</body>
</html>

猜你喜欢

转载自blog.csdn.net/wangxugangzy05/article/details/42613851