您的位置:首页 > Web前端 > HTML5

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

2015-01-11 19:19 561 查看
<!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>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐