中国象棋,canvas实现

下面是我参考别人的代码编写的中国象棋,其中的逻辑什么如果有错还请大家提出来啊。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>中国象棋</title>
        <style type="text/css">
            body{
                background: #eee;
            }
            #canvas,#canvas1{
                position: absolute;
                left: 50%;
                top: 50%;
                /*宽度是250px,高度是250px*/
                margin-left: -250px;
                margin-top: -250px;
            }
            /*层级较高*/
            #canvas{
                z-index: 10;
            }
            /*层级低但是有背景颜色*/
            #canvas1{
                z-index: 1;
                background: #b3b37d;    
            }
            #title{
                width: 100px;
                height: 50px;
                position: absolute;
                left: 50%;
                top: 50%;
                margin-left: -50px;
                margin-top: -280px;
                text-align: center;
            }
        </style>
    </head>
    <body onselectstart="return false;">
        <h2 id="title"></h2>
        <canvas id="canvas" width="" height=""></canvas>
        <canvas id="canvas1" width="" height=""></canvas>
    </body>
</html>
<script type="text/javascript">
    //开始画象棋布局
    //定义一个棋盘所有的棋子,这是一个二维数组
    var chess = [
    //['名称(txt)','横坐标x','纵坐标y','哪边下子','判断是红棋还是黑棋','判断是什么棋']
    //chess.length = 32,一共32颗棋子
        ['车',50,50,1,1,1],['车',450,50,1,1,1],
        ['馬',100,50,1,1,2],['馬',400,50,1,1,2],
        ['象',150,50,1,1,3],['象',350,50,1,1,3],//3
        ['士',200,50,1,1,4],['士',300,50,1,1,4],//4
        ['帅',250,50,1,1,5],//5
        ['炮',100,150,1,1,6],['炮',400,150,1,1,6],//6
        ['兵',50,200,1,1,7],['兵',150,200,1,1,7],['兵',250,200,1,1,7],['兵',350,200,1,1,7],['兵',450,200,1,1,1,7],//7
        ['车',50,500,1,0,1],['车',450,500,1,0,1],
        ['馬',100,500,1,0,2],['馬',400,500,1,0,2],
        ['象',150,500,1,0,3],['象',350,500,1,0,3],
        ['士',200,500,1,0,4],['士',300,500,1,0,4],
        ['将',250,500,1,0,5],
        ['炮',100,400,1,0,6],['炮',400,400,1,0,6],
        ['卒',50,350,1,0,7],['卒',150,350,1,0,7],['卒',250,350,1,0,7],['卒',350,350,1,0,7],['卒',450,350,1,0,7]
    ];
    
    //建一个数组来存放我们点击的那个棋子的所有参数
    //参数:x坐标,y坐标,哪边下子,判断是红棋还是黑棋,判断是什么棋
    var desc_click = [0,0,0,-1,0];
    //判断当前是哪边出手1表示"汉方"0表示"楚方"
    var whose = 1;
    
    window.onload = function (){
        var canvas = document.getElementById("canvas");
        var canvas1 = document.getElementById("canvas1");
        
        canvas.width = 500;
        canvas.height = 550;
        
        canvas1.width = 500;
        canvas1.height = 550;
        
        var context = canvas.getContext("2d");
        var context1 = canvas1.getContext("2d");
        
        draw_ChessBoard(context1);//画棋盘
        draw_Chess_All(context);//画棋子
        update_h2();//更换当前的出手的人
        
        canvas.onclick = function(e){
            //三个参数 第一个是当前的context,第二个是点击的棋子到画板左边的距离,第三个是当前点击的棋子到画板上边的距离
            get_Chess(context,e.clientX - canvas.offsetLeft,e.clientY - canvas.offsetTop);
            update_h2();
        };
    }
    
    //获取棋子 三个参数 第一个是在canvas上画 第二个是坐标x第三个是坐标y
    function get_Chess(context,x,y){
        //定义俩个变量
        var sub_x = 0,sub_y = 0;
        if (x<30||y<30||x>470||y>570) {return false};
        //这里就是一个四舍五入和向下取整,以便棋子能在棋盘上按格走
        if (x%100>80||x%100<20) {sub_x = 100*Math.round(x/100)};
        if (x%100>30&&x%100<70) {sub_x = x>100?(Math.floor(x/100)*100 + 50):50};
        if (y%100>80||y%100<20) {sub_y = 100*Math.round(y/100)};
        if (y%100>30&&y%100<70) {sub_y = y>100?(Math.floor(y/100)*100 + 50):50};
        
        if(sub_x > 0 && sub_y > 0){
            for (var i = 0;i < chess.length; i++) {
                if (chess[i][1] == sub_x && chess[i][2] == sub_y && chess[i][3] > 0) {
                    if (chess[i][4] == whose) {//可见第5个参数是判断当前该哪边出手的数
                        draw_check(context,sub_x,sub_y);//画棋子
                        //参数:x坐标,y坐标,数组里的第几个,数组的第五个参数即该哪边下,第六个参数
                        desc_click = [sub_x,sub_y,i,chess[i][4],chess[i][5]];
                        return false;
                    }
                    if(desc_click[3] == whose&&chess[i][4]!=whose){
                        //这一步判断是否成功换人下子
                        if(go(sub_x,sub_y,desc_click[4],true)){
                            chess[desc_click[2]][1] = sub_x;//
                            chess[desc_click[2]][2] = sub_y;//
                            chess[i][3] = 0;//棋子第三个参数赋值为0
                            whose = whose == 0?1:0;//是不是"楚"如果是就换,如果不是就是"楚"
                            repaint(context);//调用函数重新画整个棋盘
                            if(chess[i][5] == 5) {document.getElementById("canvas").onclick = null;}//
                        }
                    }
                    return false;
                }
            }
        }
        if(sub_x >= 50&&sub_x<=450&&sub_y>=50&&sub_y<=550&&desc_click[3] == whose){
            if(go(sub_x,sub_y,desc_click[4])){
                chess[desc_click[2]][1] = sub_x;
                chess[desc_click[2]][2] = sub_y;
                repaint(context);
                desc_click = [0,0,0,-1,0];
                whose = whose ==0?1:0;
            }
        }
    }
    
    function repaint(context){
        context.clearRect(0,0,500,550);
        draw_Chess_All(context);
    }
    //画棋盘
    function draw_ChessBoard(context){
        //定义线宽
        context.lineWidth = 2;
        //开始画线
        context.beginPath();
        //画横线
        for (var i = 1; i <= 10; i++) {
            context.moveTo(50,50*i);
            context.lineTo(450,50*i);
        }
        //画竖线
        for (var i = 1; i <= 9; i++) {
            context.moveTo(50*i,50);
            context.lineTo(50*i,500);
        }
        context.stroke();
        
        //画中心的斜线
        context.beginPath();
        context.moveTo(200,50);
        context.lineTo(300,150);
        context.moveTo(300,50);
        context.lineTo(200,150);
        
        context.moveTo(200,400);
        context.lineTo(300,500);
        context.moveTo(300,400);
        context.lineTo(200,500);
        context.stroke();
        
        context.beginPath();
        
        for (var i = 0; i < 2; i++) {
            for (var j = 0; j < 2; j++) {
                //绘制炮的位置的四个标记
                //绘制左上角的
                context.moveTo(85 + 300*i,145 + 250*j);
                context.lineTo(95 + 300*i,145 + 250*j);
                context.lineTo(95 + 300*i,135 + 250*j);
                //绘制右上角的
                context.moveTo(105 + 300*i,135 + 250*j);
                context.lineTo(105 + 300*i,145 + 250*j);
                context.lineTo(115 + 300*i,145 + 250*j);
                //绘制左下角
                context.moveTo(85 + 300*i,155 + 250*j);
                context.lineTo(95 + 300*i,155 + 250*j);
                context.lineTo(95 + 300*i,165 + 250*j);
                //绘制右下角
                context.moveTo(105 + 300*i,165 + 250*j);
                context.lineTo(105 + 300*i,155 + 250*j);
                context.lineTo(115 + 300*i,155 + 250*j);
            }
        }
        
        context.stroke();
        //临时存储一下
        context.save();
        //画最外层的粗线条边框
        context.beginPath();
        context.lineWidth = 3;
        context.strokeRect(46,46,408,458);
        context.fillStyle = "#b3b37d";
        context.fillRect(51,251,398,48);
        context.restore();
        
        context.save();
        context.font = "bold 40px KaiTi_GB2312";
        context.translate(100,295);
        context.rotate(-90*Math.PI/180);
        context.fillText("楚",0,40);
        context.restore();
        
        context.save();
        context.font = "bold 40px KaiTi_GB2312";
        context.translate(150,295);
        context.rotate(-90*Math.PI/180);
        context.fillText("河",0,40);
        context.restore();
        
        context.save();
        context.font = "bold 40px KaiTi_GB2312";
        context.translate(400,255);
        context.rotate(90*Math.PI/180);
        context.fillText("汉",0,40);
        context.restore();
        
        context.save();
        context.font = "bold 40px KaiTi_GB2312";
        context.translate(350,255);
        context.rotate(90*Math.PI/180);
        context.fillText("界",0,40);
        context.restore();
    }
    //
    function draw_Chess_All(context){
        for (var i = 0;i < chess.length; i++) {
            if (chess[i][3]>0) {
                draw_Chess_One(context,chess[i][1],chess[i][2],chess[i][0],chess[i][4]);
            }
        }
    }
    
    //绘制棋子 参数:context即当前的画板 x坐标 y坐标 填充的文字 判断是红棋还是黑棋
    function draw_Chess_One(context,x,y,txt,p){
        //p值是判断是黑棋还是红棋
        var color = p>0?"#ff0000":"#000000";
        context.save();
        context.beginPath();
        //棋子颜色填充用的是渐变
        var b_Color = context.createLinearGradient(x+15,y-15,x-15,y+15);
        b_Color.addColorStop(0,"#f3f5d5");
        b_Color.addColorStop(1,"#8c834d");
        //棋子的样式
        context.arc(x,y,22,0,2*Math.PI);
        context.fillStyle = b_Color;
        context.fill();
        //开始画棋子
        context.beginPath();
        context.arc(x,y,17,0,2*Math.PI);
        context.fillStyle = "#f5da94";
        context.strokeStyle = "#c9c876";
        context.stroke();
        context.fill();
        
        context.beginPath();
        context.fillStyle = color;
        context.font = "900 24px KaiTi_GB2312";
        context.fillText(txt,x-12,y+8);
        context.restore();
        
    }
    //绘制选中某个棋子的那个框
     function draw_check(context,x,y){
         //重新画整个棋盘
         repaint(context);
         //开始画左上角
         context.beginPath();
         context.moveTo(x-23,y-10);
         context.lineTo(x-23,y-23);
         context.lineTo(x-10,y-23);
         //开始画右上角
         context.moveTo(x+10,y-23);
         context.lineTo(x+23,y-23);
         context.lineTo(x+23,y-10);
         //开始画左下角
         context.moveTo(x-23,y+10);
         context.lineTo(x-23,y+23);
         context.lineTo(x-10,y+23);
         //开始画右下角
         context.moveTo(x+23,y+10);
         context.lineTo(x+23,y+23);
         context.lineTo(x+10,y+23);
         context.stroke();
     }
    //吃子
    function go(x2,y2,txt,eat){
        //定义x1是点击的那个对象数组的第一个值 y1是第二个值
        var x1 = desc_click[0];
        var y1 = desc_click[1];
        //定义最大值和最小值
        var min_x = x1 > x2?x2:x1;
        var max_x = x1 > x2?x1:x2;
        var min_y = y1 > y2?y2:y1;
        var max_y = y1 > y2?y1:y2;
        //定义是否可以吃子
        var can_go = true;
        var num = 0;
        //判断是不是俩个将帅面对面
        if (is_face_to_face(x2)) {
            return false;
        }
        //下棋
        switch (txt){
            case 1:
                // 如果俩车不在同一条直线上
                if(x1!=x2&&y1!=y2){
                    //不能吃子
                    can_go = false;
                    break;
                }
                //开始遍历
                for(var i = 0;i < chess.length; i++){
                    //
                    if(chess[i][1] == x1 && chess[i][2] > min_y && chess[i][2] < max_y && chess[i][3] != 0){
                        can_go = false; 
                    }
                    //
                    if(chess[i][2] == y1 && chess[i][1] > min_x && chess[i][1] < max_x && chess[i][3] != 0){
                        can_go = false;
                    }
                }
                break;
            case 2://如果是马怎么走
                can_go = false;
                if(x1-50==x2&&y1-100==y2&&!is_chess(x1,y1-50)){can_go = true};
                if(x1+50==x2&&y1-100==y2&&!is_chess(x1,y1-50)){can_go = true};
                if(x1-50==x2&&y1+100==y2&&!is_chess(x1,y1+50)){can_go = true};
                if(x1+50==x2&&y1+100==y2&&!is_chess(x1,y1+50)){can_go = true};
                if(x1-100==x2&&y1-50==y2&&!is_chess(x1-50,y1)){can_go = true};
                if(x1-100==x2&&y1+50==y2&&!is_chess(x1-50,y1)){can_go = true};
                if(x1+100==x2&&y1-50==y2&&!is_chess(x1+50,y1)){can_go = true};
                if(x1+100==x2&&y1+50==y2&&!is_chess(x1+50,y1)){can_go = true};
                break;
            case 3://象怎么走
                can_go = false;
                if(whose == 1 && y2 > 250) {break};
                if(whose == 0 && y2 < 300) {break};
                if(x1-100==x2&&y1-100==y2&&!is_chess(x1-50,y1-50)) {can_go=true};
                if(x1+100==x2&&y1-100==y2&&!is_chess(x1+50,y1-50)) {can_go=true};
                if(x1-100==x2&&y1+100==y2&&!is_chess(x1-50,y1+50)) {can_go=true};
                if(x1+100==x2&&y1+100==y2&&!is_chess(x1+50,y1+50)) {can_go=true};
                break;
            case 4://士怎么走
                can_go= false;
                if(x2<200||x2>300){break};
                if(whose == 1&&y2>150){break};
                if(x1+50==x2&&y1+50==y2){can_go = true};
                if(x1+50==x2&&y1-50==y2){can_go = true};
                if(x1-50==x2&&y1+50==y2){can_go = true};
                if(x1-50==x2&&y1-50==y2){can_go = true};
                break;
            case 5://帅怎么走
                can_go = false;
                if(x2<200||x2>300){break};
                //红棋的帅
                if(whose == 1&&y2>150){break};
                //黑棋的将
                if(whose==0&&y2<400){break};
                //判断怎么能走
                if(x1+50==x2&&y1==y2){can_go=true};
                if(x1-50==x2&&y1==y2){can_go=true};
                if(x1==x2&&y1+50==y2){can_go=true};
                if(x1==x2&&y1-50==y2){can_go=true};
                break;
            case 6://炮怎么走
                //不能原地走
                if(x1!=x2&&y1!=y2){
                    can_go = false;
                    break;
                }
                //如果吃子
                if(eat){
                    for(var i = 0;i < chess.length; i++){
                        if(chess[i][1]==x1&&chess[i][2]>min_y&&chess[i][2]<max_y&&chess[i][3]!=0){num++};
                        if(chess[i][2]==y1&&chess[i][1]>min_x&&chess[i][1]<max_x&&chess[i][3]!=0){num++};
                    }
                    if(num!=1){can_go = false};
                    break;
                }
                //
                for(var i=0;i<chess.length;i++){
                    if(chess[i][1]==x1&&chess[i][2]>min_y&&chess[i][2]<max_y&&chess[i][3]!=0){can_go = false};
                    if(chess[i][2]==y1&&chess[i][1]>min_x&&chess[i][1]<max_x&&chess[i][3]!=0){can_go = false};
                }
                break;
            case 7://兵怎么走
                if(whose==1&&y1>y2){can_go = false};
                if(whose==0&&y1<y2){can_go = false};
                if(whose==1&&y1<=250&&x1!=x2){can_go = false};
                if(whose==0&&y1>=300&&x1!=x2){can_go = false};
                if(max_x-min_x+max_y-min_y>50){can_go = false};
                break;
        }
        return can_go;
    }
    //判断这颗棋子是否存在
    function is_chess(x,y){
        //定义existe判断是否这颗棋子还活着默认是死了
        var existe = false;
        for(var i = 0;i<chess.length;i++){
            //如果某颗棋子的横纵坐标都有并且chess[i][3]任然等于1这个参数是true表示活着
            if(chess[i][1]==x && chess[i][2]==y && chess[i][3]==1){existe = true;};
        }
        return existe;
    }
    //这是一个判断俩个帅是否是面对面(有bug)
    function is_face_to_face(x){
        //定义四个参数红色的和黑色的x,y坐标
        var r_x = 0,r_y=0,b_x=0,b_y=0,num=0;
        //定义一个状态
        var state = false;
        //
        for(var i=0;i<chess.length;i++){
            //chess[i][5]值就是从1到7分别代表不同的棋子,例如1表示军7表示兵卒
            //5表示将帅
            if(chess[i][5]==5 && chess[i][4]==1){//如果将帅活着并且1表示红棋
                //获取到这个棋子的横纵坐标
                r_x=chess[i][1];
                r_y=chess[i][2];
            }
            if(chess[i][5]==5 && chess[i][4]==0){//如果将帅活着并且1表示黑棋
                //获取到当前棋子的横纵坐标
                b_x=chess[i][1];
                b_y=chess[i][2];
            }
        }
        //如果红色和黑色的横坐标相同时
        if(r_x == b_x){
            //遍历一遍chess数组
            for(var i = 0;i<chess.length;i++){
                //如果当前棋子的位置没变并且是红棋落子时
                if(chess[i][1] == r_x && chess[i][3] > 0){num++;}
            }
            //??有问题
            if(num - 2 == 1 && x != r_x){state = true;}
        }
        return state;
    }
    
    function update_h2(){
        var h2 = document.getElementById("title");
        h2.innerHTML = whose == 1?"汉":"楚";
        h2.style.color = whose == 1?"#ff0000":"#000";
    }
    
    
</script>

喜欢的给个赞赏吧。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,469评论 25 707
  • 天空之镜 怀着无比向往的心情来到茶卡盐湖,可惜是阴天。天啊!身边路过的人都说,差点冻死在夏天。去的那天是真么太冷了...
    悦心言阅读 247评论 0 0
  • 今天和好友有聊起关于未来,渺茫,百感交集。 说起我最近的状态,可以用“极度虚脱”来形容,一方面满载理想的来深看市场...
    soulmatex阅读 158评论 2 3
  • 凉亭中落子之声清脆,不急不缓,不骄不躁,两人的对话也清晰入耳。 “她已去了好些年,皇上不再立后吗?”那人满头白发,...
    相思未歇阅读 282评论 0 1