美文网首页
中国象棋,canvas实现

中国象棋,canvas实现

作者: 郝特么冷 | 来源:发表于2017-09-22 11:30 被阅读44次

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

<!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>

喜欢的给个赞赏吧。

相关文章

网友评论

      本文标题:中国象棋,canvas实现

      本文链接:https://www.haomeiwen.com/subject/odzxextx.html