中国象棋(Canvas制作)

昨天看了别人写的一个中国象棋,自己也仿照着写了一下基本上效果实现了,不过还是有一些需要改进,😔,不断完善吧。

代码如下:

  1 <!DOCTYPE html>
  2 <html>
  3     <head>
  4         <meta charset="UTF-8">
  5         <title>中国象棋</title>
  6         <style type="text/css">
  7             body{
  8                 background: #eee;
  9             }
 10             #canvas,#canvas1{
 11                 position: absolute;
 12                 left: 50%;
 13                 top: 50%;
 14                 /*宽度是250px,高度是250px*/
 15                 margin-left: -250px;
 16                 margin-top: -250px;
 17             }
 18             /*层级较高*/
 19             #canvas{
 20                 z-index: 10;
 21             }
 22             /*层级低但是有背景颜色*/
 23             #canvas1{
 24                 z-index: 1;
 25                 background: #b3b37d;    
 26             }
 27             #title{
 28                 width: 100px;
 29                 height: 50px;
 30                 position: absolute;
 31                 left: 50%;
 32                 top: 50%;
 33                 margin-left: -50px;
 34                 margin-top: -280px;
 35                 text-align: center;
 36             }
 37         </style>
 38     </head>
 39     <body onselectstart="return false;">
 40         <h2 id="title"></h2>
 41         <canvas id="canvas" width="" height=""></canvas>
 42         <canvas id="canvas1" width="" height=""></canvas>
 43     </body>
 44 </html>
 45 <script type="text/javascript">
 46     //开始画象棋布局
 47     //定义一个棋盘所有的棋子,这是一个二维数组
 48     var chess = [
 49     //['名称(txt)','横坐标x','纵坐标y','哪边下子','判断是红棋还是黑棋','判断是什么棋']
 50     //chess.length = 32,一共32颗棋子
 51         ['',50,50,1,1,1],['',450,50,1,1,1],
 52         ['',100,50,1,1,2],['',400,50,1,1,2],
 53         ['',150,50,1,1,3],['',350,50,1,1,3],//3
 54         ['',200,50,1,1,4],['',300,50,1,1,4],//4
 55         ['',250,50,1,1,5],//5
 56         ['',100,150,1,1,6],['',400,150,1,1,6],//6
 57         ['',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
 58         ['',50,500,1,0,1],['',450,500,1,0,1],
 59         ['',100,500,1,0,2],['',400,500,1,0,2],
 60         ['',150,500,1,0,3],['',350,500,1,0,3],
 61         ['',200,500,1,0,4],['',300,500,1,0,4],
 62         ['',250,500,1,0,5],
 63         ['',100,400,1,0,6],['',400,400,1,0,6],
 64         ['',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]
 65     ];
 66     
 67     //建一个数组来存放我们点击的那个棋子的所有参数
 68     //参数:x坐标,y坐标,哪边下子,判断是红棋还是黑棋,判断是什么棋
 69     var desc_click = [0,0,0,-1,0];
 70     //判断当前是哪边出手1表示"汉方"0表示"楚方"
 71     var whose = 1;
 72     
 73     window.onload = function (){
 74         var canvas = document.getElementById("canvas");
 75         var canvas1 = document.getElementById("canvas1");
 76         
 77         canvas.width = 500;
 78         canvas.height = 550;
 79         
 80         canvas1.width = 500;
 81         canvas1.height = 550;
 82         
 83         var context = canvas.getContext("2d");
 84         var context1 = canvas1.getContext("2d");
 85         
 86         draw_ChessBoard(context1);//画棋盘
 87         draw_Chess_All(context);//画棋子
 88         update_h2();//更换当前的出手的人
 89         
 90         canvas.onclick = function(e){
 91             //三个参数 第一个是当前的context,第二个是点击的棋子到画板左边的距离,第三个是当前点击的棋子到画板上边的距离
 92             get_Chess(context,e.clientX - canvas.offsetLeft,e.clientY - canvas.offsetTop);
 93             update_h2();
 94         };
 95     }
 96     
 97     //获取棋子 三个参数 第一个是在canvas上画 第二个是坐标x第三个是坐标y
 98     function get_Chess(context,x,y){
 99         //定义俩个变量
100         var sub_x = 0,sub_y = 0;
101         if (x<30||y<30||x>470||y>570) {return false};
102         //这里就是一个四舍五入和向下取整,以便棋子能在棋盘上按格走
103         if (x%100>80||x%100<20) {sub_x = 100*Math.round(x/100)};
104         if (x%100>30&&x%100<70) {sub_x = x>100?(Math.floor(x/100)*100 + 50):50};
105         if (y%100>80||y%100<20) {sub_y = 100*Math.round(y/100)};
106         if (y%100>30&&y%100<70) {sub_y = y>100?(Math.floor(y/100)*100 + 50):50};
107         
108         if(sub_x > 0 && sub_y > 0){
109             for (var i = 0;i < chess.length; i++) {
110                 if (chess[i][1] == sub_x && chess[i][2] == sub_y && chess[i][3] > 0) {
111                     if (chess[i][4] == whose) {//可见第5个参数是判断当前该哪边出手的数
112                         draw_check(context,sub_x,sub_y);//画棋子
113                         //参数:x坐标,y坐标,数组里的第几个,数组的第五个参数即该哪边下,第六个参数
114                         desc_click = [sub_x,sub_y,i,chess[i][4],chess[i][5]];
115                         return false;
116                     }
117                     if(desc_click[3] == whose&&chess[i][4]!=whose){
118                         //这一步判断是否成功换人下子
119                         if(go(sub_x,sub_y,desc_click[4],true)){
120                             chess[desc_click[2]][1] = sub_x;//
121                             chess[desc_click[2]][2] = sub_y;//
122                             chess[i][3] = 0;//棋子第三个参数赋值为0
123                             whose = whose == 0?1:0;//是不是"楚"如果是就换,如果不是就是"楚"
124                             repaint(context);//调用函数重新画整个棋盘
125                             if(chess[i][5] == 5) {document.getElementById("canvas").onclick = null;}//
126                         }
127                     }
128                     return false;
129                 }
130             }
131         }
132         if(sub_x >= 50&&sub_x<=450&&sub_y>=50&&sub_y<=550&&desc_click[3] == whose){
133             if(go(sub_x,sub_y,desc_click[4])){
134                 chess[desc_click[2]][1] = sub_x;
135                 chess[desc_click[2]][2] = sub_y;
136                 repaint(context);
137                 desc_click = [0,0,0,-1,0];
138                 whose = whose ==0?1:0;
139             }
140         }
141     }
142     
143     function repaint(context){
144         context.clearRect(0,0,500,550);
145         draw_Chess_All(context);
146     }
147     //画棋盘
148     function draw_ChessBoard(context){
149         //定义线宽
150         context.lineWidth = 2;
151         //开始画线
152         context.beginPath();
153         //画横线
154         for (var i = 1; i <= 10; i++) {
155             context.moveTo(50,50*i);
156             context.lineTo(450,50*i);
157         }
158         //画竖线
159         for (var i = 1; i <= 9; i++) {
160             context.moveTo(50*i,50);
161             context.lineTo(50*i,500);
162         }
163         context.stroke();
164         
165         //画中心的斜线
166         context.beginPath();
167         context.moveTo(200,50);
168         context.lineTo(300,150);
169         context.moveTo(300,50);
170         context.lineTo(200,150);
171         
172         context.moveTo(200,400);
173         context.lineTo(300,500);
174         context.moveTo(300,400);
175         context.lineTo(200,500);
176         context.stroke();
177         
178         context.beginPath();
179         
180         for (var i = 0; i < 2; i++) {
181             for (var j = 0; j < 2; j++) {
182                 //绘制炮的位置的四个标记
183                 //绘制左上角的
184                 context.moveTo(85 + 300*i,145 + 250*j);
185                 context.lineTo(95 + 300*i,145 + 250*j);
186                 context.lineTo(95 + 300*i,135 + 250*j);
187                 //绘制右上角的
188                 context.moveTo(105 + 300*i,135 + 250*j);
189                 context.lineTo(105 + 300*i,145 + 250*j);
190                 context.lineTo(115 + 300*i,145 + 250*j);
191                 //绘制左下角
192                 context.moveTo(85 + 300*i,155 + 250*j);
193                 context.lineTo(95 + 300*i,155 + 250*j);
194                 context.lineTo(95 + 300*i,165 + 250*j);
195                 //绘制右下角
196                 context.moveTo(105 + 300*i,165 + 250*j);
197                 context.lineTo(105 + 300*i,155 + 250*j);
198                 context.lineTo(115 + 300*i,155 + 250*j);
199             }
200         }
201         
202         context.stroke();
203         //临时存储一下
204         context.save();
205         //画最外层的粗线条边框
206         context.beginPath();
207         context.lineWidth = 3;
208         context.strokeRect(46,46,408,458);
209         context.fillStyle = "#b3b37d";
210         context.fillRect(51,251,398,48);
211         context.restore();
212         
213         context.save();
214         context.font = "bold 40px KaiTi_GB2312";
215         context.translate(100,295);
216         context.rotate(-90*Math.PI/180);
217         context.fillText("",0,40);
218         context.restore();
219         
220         context.save();
221         context.font = "bold 40px KaiTi_GB2312";
222         context.translate(150,295);
223         context.rotate(-90*Math.PI/180);
224         context.fillText("",0,40);
225         context.restore();
226         
227         context.save();
228         context.font = "bold 40px KaiTi_GB2312";
229         context.translate(400,255);
230         context.rotate(90*Math.PI/180);
231         context.fillText("",0,40);
232         context.restore();
233         
234         context.save();
235         context.font = "bold 40px KaiTi_GB2312";
236         context.translate(350,255);
237         context.rotate(90*Math.PI/180);
238         context.fillText("",0,40);
239         context.restore();
240     }
241     //
242     function draw_Chess_All(context){
243         for (var i = 0;i < chess.length; i++) {
244             if (chess[i][3]>0) {
245                 draw_Chess_One(context,chess[i][1],chess[i][2],chess[i][0],chess[i][4]);
246             }
247         }
248     }
249     
250     //绘制棋子 参数:context即当前的画板 x坐标 y坐标 填充的文字 判断是红棋还是黑棋
251     function draw_Chess_One(context,x,y,txt,p){
252         //p值是判断是黑棋还是红棋
253         var color = p>0?"#ff0000":"#000000";
254         context.save();
255         context.beginPath();
256         //棋子颜色填充用的是渐变
257         var b_Color = context.createLinearGradient(x+15,y-15,x-15,y+15);
258         b_Color.addColorStop(0,"#f3f5d5");
259         b_Color.addColorStop(1,"#8c834d");
260         //棋子的样式
261         context.arc(x,y,22,0,2*Math.PI);
262         context.fillStyle = b_Color;
263         context.fill();
264         //开始画棋子
265         context.beginPath();
266         context.arc(x,y,17,0,2*Math.PI);
267         context.fillStyle = "#f5da94";
268         context.strokeStyle = "#c9c876";
269         context.stroke();
270         context.fill();
271         
272         context.beginPath();
273         context.fillStyle = color;
274         context.font = "900 24px KaiTi_GB2312";
275         context.fillText(txt,x-12,y+8);
276         context.restore();
277         
278     }
279     //绘制选中某个棋子的那个框
280      function draw_check(context,x,y){
281          //重新画整个棋盘
282          repaint(context);
283          //开始画左上角
284          context.beginPath();
285          context.moveTo(x-23,y-10);
286          context.lineTo(x-23,y-23);
287          context.lineTo(x-10,y-23);
288          //开始画右上角
289          context.moveTo(x+10,y-23);
290          context.lineTo(x+23,y-23);
291          context.lineTo(x+23,y-10);
292          //开始画左下角
293          context.moveTo(x-23,y+10);
294          context.lineTo(x-23,y+23);
295          context.lineTo(x-10,y+23);
296          //开始画右下角
297          context.moveTo(x+23,y+10);
298          context.lineTo(x+23,y+23);
299          context.lineTo(x+10,y+23);
300          context.stroke();
301      }
302     //吃子
303     function go(x2,y2,txt,eat){
304         //定义x1是点击的那个对象数组的第一个值 y1是第二个值
305         var x1 = desc_click[0];
306         var y1 = desc_click[1];
307         //定义最大值和最小值
308         var min_x = x1 > x2?x2:x1;
309         var max_x = x1 > x2?x1:x2;
310         var min_y = y1 > y2?y2:y1;
311         var max_y = y1 > y2?y1:y2;
312         //定义是否可以吃子
313         var can_go = true;
314         var num = 0;
315         //判断是不是俩个将帅面对面
316         if (is_face_to_face(x2)) {
317             return false;
318         }
319         //下棋
320         switch (txt){
321             case 1:
322                 // 如果俩车不在同一条直线上
323                 if(x1!=x2&&y1!=y2){
324                     //不能吃子
325                     can_go = false;
326                     break;
327                 }
328                 //开始遍历
329                 for(var i = 0;i < chess.length; i++){
330                     //
331                     if(chess[i][1] == x1 && chess[i][2] > min_y && chess[i][2] < max_y && chess[i][3] != 0){
332                         can_go = false; 
333                     }
334                     //
335                     if(chess[i][2] == y1 && chess[i][1] > min_x && chess[i][1] < max_x && chess[i][3] != 0){
336                         can_go = false;
337                     }
338                 }
339                 break;
340             case 2://如果是马怎么走
341                 can_go = false;
342                 if(x1-50==x2&&y1-100==y2&&!is_chess(x1,y1-50)){can_go = true};
343                 if(x1+50==x2&&y1-100==y2&&!is_chess(x1,y1-50)){can_go = true};
344                 if(x1-50==x2&&y1+100==y2&&!is_chess(x1,y1+50)){can_go = true};
345                 if(x1+50==x2&&y1+100==y2&&!is_chess(x1,y1+50)){can_go = true};
346                 if(x1-100==x2&&y1-50==y2&&!is_chess(x1-50,y1)){can_go = true};
347                 if(x1-100==x2&&y1+50==y2&&!is_chess(x1-50,y1)){can_go = true};
348                 if(x1+100==x2&&y1-50==y2&&!is_chess(x1+50,y1)){can_go = true};
349                 if(x1+100==x2&&y1+50==y2&&!is_chess(x1+50,y1)){can_go = true};
350                 break;
351             case 3://象怎么走
352                 can_go = false;
353                 if(whose == 1 && y2 > 250) {break};
354                 if(whose == 0 && y2 < 300) {break};
355                 if(x1-100==x2&&y1-100==y2&&!is_chess(x1-50,y1-50)) {can_go=true};
356                 if(x1+100==x2&&y1-100==y2&&!is_chess(x1+50,y1-50)) {can_go=true};
357                 if(x1-100==x2&&y1+100==y2&&!is_chess(x1-50,y1+50)) {can_go=true};
358                 if(x1+100==x2&&y1+100==y2&&!is_chess(x1+50,y1+50)) {can_go=true};
359                 break;
360             case 4://士怎么走
361                 can_go= false;
362                 if(x2<200||x2>300){break};
363                 if(whose == 1&&y2>150){break};
364                 if(x1+50==x2&&y1+50==y2){can_go = true};
365                 if(x1+50==x2&&y1-50==y2){can_go = true};
366                 if(x1-50==x2&&y1+50==y2){can_go = true};
367                 if(x1-50==x2&&y1-50==y2){can_go = true};
368                 break;
369             case 5://帅怎么走
370                 can_go = false;
371                 if(x2<200||x2>300){break};
372                 //红棋的帅
373                 if(whose == 1&&y2>150){break};
374                 //黑棋的将
375                 if(whose==0&&y2<400){break};
376                 //判断怎么能走
377                 if(x1+50==x2&&y1==y2){can_go=true};
378                 if(x1-50==x2&&y1==y2){can_go=true};
379                 if(x1==x2&&y1+50==y2){can_go=true};
380                 if(x1==x2&&y1-50==y2){can_go=true};
381                 break;
382             case 6://炮怎么走
383                 //不能原地走
384                 if(x1!=x2&&y1!=y2){
385                     can_go = false;
386                     break;
387                 }
388                 //如果吃子
389                 if(eat){
390                     for(var i = 0;i < chess.length; i++){
391                         if(chess[i][1]==x1&&chess[i][2]>min_y&&chess[i][2]<max_y&&chess[i][3]!=0){num++};
392                         if(chess[i][2]==y1&&chess[i][1]>min_x&&chess[i][1]<max_x&&chess[i][3]!=0){num++};
393                     }
394                     if(num!=1){can_go = false};
395                     break;
396                 }
397                 //
398                 for(var i=0;i<chess.length;i++){
399                     if(chess[i][1]==x1&&chess[i][2]>min_y&&chess[i][2]<max_y&&chess[i][3]!=0){can_go = false};
400                     if(chess[i][2]==y1&&chess[i][1]>min_x&&chess[i][1]<max_x&&chess[i][3]!=0){can_go = false};
401                 }
402                 break;
403             case 7://兵怎么走
404                 if(whose==1&&y1>y2){can_go = false};
405                 if(whose==0&&y1<y2){can_go = false};
406                 if(whose==1&&y1<=250&&x1!=x2){can_go = false};
407                 if(whose==0&&y1>=300&&x1!=x2){can_go = false};
408                 if(max_x-min_x+max_y-min_y>50){can_go = false};
409                 break;
410         }
411         return can_go;
412     }
413     //判断这颗棋子是否存在
414     function is_chess(x,y){
415         //定义existe判断是否这颗棋子还活着默认是死了
416         var existe = false;
417         for(var i = 0;i<chess.length;i++){
418             //如果某颗棋子的横纵坐标都有并且chess[i][3]任然等于1这个参数是true表示活着
419             if(chess[i][1]==x && chess[i][2]==y && chess[i][3]==1){existe = true;};
420         }
421         return existe;
422     }
423     //这是一个判断俩个帅是否是面对面(有bug)
424     function is_face_to_face(x){
425         //定义四个参数红色的和黑色的x,y坐标
426         var r_x = 0,r_y=0,b_x=0,b_y=0,num=0;
427         //定义一个状态
428         var state = false;
429         //
430         for(var i=0;i<chess.length;i++){
431             //chess[i][5]值就是从1到7分别代表不同的棋子,例如1表示军7表示兵卒
432             //5表示将帅
433             if(chess[i][5]==5 && chess[i][4]==1){//如果将帅活着并且1表示红棋
434                 //获取到这个棋子的横纵坐标
435                 r_x=chess[i][1];
436                 r_y=chess[i][2];
437             }
438             if(chess[i][5]==5 && chess[i][4]==0){//如果将帅活着并且1表示黑棋
439                 //获取到当前棋子的横纵坐标
440                 b_x=chess[i][1];
441                 b_y=chess[i][2];
442             }
443         }
444         //如果红色和黑色的横坐标相同时
445         if(r_x == b_x){
446             //遍历一遍chess数组
447             for(var i = 0;i<chess.length;i++){
448                 //如果当前棋子的位置没变并且是红棋落子时
449                 if(chess[i][1] == r_x && chess[i][3] > 0){num++;}
450             }
451             //??有问题
452             if(num - 2 == 1 && x != r_x){state = true;}
453         }
454         return state;
455     }
456     
457     function update_h2(){
458         var h2 = document.getElementById("title");
459         h2.innerHTML = whose == 1?"":"";
460         h2.style.color = whose == 1?"#ff0000":"#000";
461     }
462     
463     
464 </script>

 

posted @ 2016-11-07 14:28  冰封ice  阅读(915)  评论(0编辑  收藏  举报