小游戏——js+h5[canvas]+cs3制作【五子棋】小游戏

五子棋小游戏学习——

有一个问题是,棋盘线的颜色,在canvas中,明明设置了灰色,但在我的预览中还是黑色的,很重的颜色。

以下是复刻的源码:

  1 <!DOCTYPE html>
  2 <html>
  3 
  4     <head>
  5         <meta charset="UTF-8">
  6         <title>五子棋游戏</title>
  7         <meta name="Description" content="git上看到的一个很值得学习练习的简易h5+js制作的小游戏,很久没有摸键盘码代码了,刚好拿来练练手。" />
  8         <style type="text/css">
  9             canvas {
 10                 display: block;
 11                 margin: 50px auto;
 12                 -webkit-box-shadow: -2px -2px 2px #efefef, 5px 5px 5px #b9b9b9;
 13                 box-shadow: -2px -2px 2px #efefef, 5px 5px 5px #b9b9b9;
 14                 cursor: pointer;
 15             }
 16             
 17             .btn_wrap {
 18                 display: flex;
 19                 flex-direction: row;
 20                 justify-content: center;
 21             }
 22             
 23             .btn_wrap div {
 24                 margin: 0 10px;
 25             }
 26             
 27             div>span {
 28                 display: inline-block;
 29                 padding: 10px 20px;
 30                 color: #FFF;
 31                 background: #ee82ee;
 32                 -webkit-border-radius: 5px;
 33                 -moz-border-radius: 5px;
 34                 border-radius: 5px;
 35                 cursor: pointer;
 36             }
 37             
 38             div.unable span {
 39                 background: #d6d6d4;
 40                 color: #adacaa;
 41             }
 42             
 43             #result-wrap {
 44                 text-align: center;
 45             }
 46         </style>
 47     </head>
 48 
 49     <body>
 50         <h3 id="result-wrap">--五子棋游戏--</h3>
 51         <canvas id="chess" width="450px" height="450px"></canvas>
 52         <div class="btn_wrap">
 53             <div id="restart" class="restart">
 54                 <span>重新开始</span>
 55             </div>
 56             <div id="goback" class="goback unable">
 57                 <span>悔棋</span>
 58             </div>
 59             <div id="return" class="return unable">
 60                 <span>
 61                     撤销悔棋
 62                 </span>
 63             </div>
 64         </div>
 65         <a href="https://github.com/wj704/wj704.github.io/blob/master/five_game.html">原文地址</a>
 66     </body>
 67     <script type="text/javascript">
 68         var over = false;
 69         var me = true; //我
 70         var _nowi = 0,
 71             _nowj = 0;
 72         var _compi = 0,
 73             _compj = 0;
 74         var _myWin = [],
 75             _compWin = [];
 76         var backAble = false,
 77             returnAble = false;
 78         var resultTxt = document.getElementById('result-wrap');
 79 
 80         var chressBord = [];
 81         for(var i = 0; i < 15; i++) {
 82             chressBord[i] = [];
 83             for(var j = 0; j < 15; j++) {
 84                 chressBord[i][j] = 0;
 85             }
 86         }
 87 
 88         //赢法的统计数组
 89         var myWin = [];
 90         var computerWin = [];
 91 
 92         //赢法数组
 93         var wins = [];
 94         for(var i = 0; i < 15; i++) {
 95             wins[i] = [];
 96             for(var j = 0; j < 15; j++) {
 97                 wins[i][j] = [];
 98             }
 99         }
100 
101         var count = 0; //赢法总数
102         //横线赢法
103         for(var i = 0; i < 15; i++) {
104             for(var j = 0; j < 11; j++) {
105                 for(var k = 0; k < 5; k++) {
106                     wins[i][j + k][count] = true;
107                 }
108                 count++;
109             }
110         }
111 
112         //竖线赢法
113         for(var i = 0; i < 15; i++) {
114             for(var j = 0; j < 11; j++) {
115                 for(var k = 0; k < 5; k++) {
116                     wins[j + k][i][count] = true;
117                 }
118                 count++;
119             }
120         }
121 
122         //正斜线赢法
123         for(var i = 0; i < 11; i++) {
124             for(var j = 0; j < 11; j++) {
125                 for(var k = 0; k < 5; k++) {
126                     wins[i + k][j + k][count] = true;
127                 }
128                 count++;
129             }
130         }
131 
132         //反斜线赢法
133         for(var i = 0; i < 11; i++) {
134             for(var j = 14; j > 3; j--) {
135                 for(var k = 0; k < 5; k++) {
136                     wins[i + k][j - k][count] = true;
137                 }
138                 count++;
139             }
140         }
141 
142         //debugger
143         for(var i = 0; i < count; i++) {
144             myWin[i] = 0;
145             _myWin[i] = 0;
146             computerWin[i] = 0;
147             _compWin[i] = 0;
148         }
149         var chess = document.getElementById('chess');
150         var context = chess.getContext('2d')
151         context.storkeStyle = '#bfbfbf'; //边框颜色
152         var backbtn = document.getElementById('goback');
153         var returnbtn = document.getElementById('return');
154         window.onload = function() {
155             drawChessBoard();
156         }
157 
158         document.getElementById('restart').onclick = function() {
159             window.location.reload();
160         }
161         //我,下棋
162         chess.onclick = function(e) {
163             if(over) {
164                 return;
165             }
166             if(!me) {
167                 return;
168             }
169             //悔棋功能可用
170             backbtn.className = backbtn.className.replace(new RegExp("(\\s|^)unable(\\s|$)"), " ");
171             var x = e.offsetX;
172             var y = e.offsetY;
173             var i = Math.floor(x / 30);
174             var j = Math.floor(y / 30);
175             _nowi = i;
176             _nowj = j;
177             if(chressBord[i][j] == 0) {
178                 oneStep(i, j, me);
179                 chressBord[i][j] = 1; //我,已占位置
180                 for(var k = 0; k < count; k++) { //将可能赢的情况都加1
181                     if(wins[i][j][k]) {
182                         //debugger
183                         myWin[k]++;
184                         _compWin[k] = computerWin[k];
185                         computerWin[k] = 6; //这个位置对方不可能赢了
186                         if(myWin[k] == 5) {
187                             //window.alert('你赢了');
188                             resultTxt.innerHTML = '恭喜,你赢了!';
189                             over = true;
190                         }
191                     }
192                 }
193                 if(!over) {
194                     me = !me;
195                     computerAI();
196                 }
197             }
198         }
199 
200         //悔棋
201         backbtn.onclick = function(e) {
202             if(!backAble) {
203                 return;
204             }
205             over = false;
206             me = true;
207             //resultTxt.innerHTMl = "(⊙o⊙),悔棋中";
208             //撤销悔棋功能可用
209             returnbtn.className = returnbtn.className.replace(new RgeExp("(\\s|^)unable(\\s|$)"), " ");
210             //我,悔棋
211             chressBord[_nowi][_nowj] = 0; //我,已占位置 还原
212             minusStep(_nowi, _nowj); //销毁棋子
213             for(var k = 0; k < count; k++) { //将可能赢得情况都减1
214                 if(wins[_nowi][_nowj][k]) {
215                     myWin[k]--;
216                     computerWin[k] = _compWin[k]; //这个位置对方可能赢
217                 }
218             }
219 
220             //计算机相应的悔棋
221             chressBord[_compi][_compj] = 0; //计算机,已占位置 还原
222             minusStep(_compi, _compj); //销毁棋子
223             for(var k = 0; k < count; k++) {
224                 if(wins[_compi][_compj][k]) {
225                     computerWin[k]--;
226                     myWin[k] = _myWin[i]; //这个位置对方可能赢
227                 }
228             }
229             resultTxt.innerHTML = "--益智五子棋--";
230             returnAble = true;
231             backAble = false;
232         }
233 
234         //撤销悔棋
235         returnbtn.onclick = function(e) {
236             if(!returnAble) {
237                 return;
238             }
239             //我,撤销悔棋
240             chressBord[_nowi][_nowj] = 1; //我,已占位置
241             oneStep(_nowi, _nowj, me);
242             for(var k = 0; k < count; k++) {
243 
244                 if(wins[_nowi][_nowj][k]) {
245                     myWin[k]++;
246                     _compWin[k] = computerWin[k];
247                     computerWin[k] = 6; //这个位置对方不可能赢
248                 }
249                 if(myWin[k] == 5) {
250                     resultTxt.innerHTML = '恭喜,你赢了!';
251                     over = true;
252                 }
253             }
254 
255             //计算机撤销相应的悔棋
256             chressBord[_compi][_compj] = 2; //计算机,已占位置
257             oneStep(_compi, _compj, false);
258             for(var k = 0; k < count; k++) { //将可能赢得情况减一
259                 if(wins[_compi][_compj][k]) {
260                     computerWin[k]++;
261                     _myWin[k] = myWin[k];
262                     myWin[k] = 6; //这个位置对方不可能赢
263                 }
264                 if(computerWin[k] == 5) {
265                     resultTxt.innerHTML = "┗|`O′|┛ 嗷~~,计算机赢了,继续加油!";
266                     over = true;
267                 }
268             }
269             returnbtn.className += " " + "unable";
270             returnAble = false;
271             backAble = true;
272         }
273 
274         //计算机下棋
275         var computerAI = function() {
276             var myScore = [];
277             var computerScore = [];
278             var max = 0;
279             var u = 0,
280                 v = 0;
281             for(var i = 0; i < 15; i++) {
282                 myScore[i] = [];
283                 computerScore[i] = [];
284                 for(var j = 0; j < 15; j++) {
285                     myScore[i][j] = 0;
286                     computerScore[i][j] = 0;
287                 }
288             }
289             for(var i = 0; i < 15; i++) {
290                 for(var j = 0; j < 15; j++) {
291                     if(chressBord[i][j] == 0) {
292                         for(var k = 0; k < count; k++) {
293                             if(wins[i][j][k]) {
294 
295                                 if(myWin[k] == 1) {
296                                     myScore[i][j] += 200;
297                                 } else if(myWin[k] == 2) {
298                                     myScore[i][j] += 400;
299                                 } else if(myWin[k] == 3) {
300                                     myScore[i][j] += 2000;
301                                 } else if(myWin[k] == 4) {
302                                     myScore[i][j] += 10000;
303                                 }
304 
305                                 if(computerWin[k] == 1) {
306                                     computerScore[i][j] += 220;
307                                 } else if(computerWin[k] == 2) {
308                                     computerScore[i][j] += 420;
309                                 } else if(computerWin[k] == 3) {
310                                     computerScore[i][j] += 2100;
311                                 } else if(computerWin[k] == 4) {
312                                     computerScore[i][j] += 20000;
313                                 }
314                             }
315                         }
316                         if(myScore[i][j] > max) {
317                             max = myScore[i][j];
318                             u = i;
319                             v = j;
320                         } else if(myScore[i][j] == max) {
321                             if(computerScore[i][j] > computerScore[u][v]) {
322                                 u = i;
323                                 v = j;
324                             }
325                         }
326                         if(computerScore[i][j] > max) {
327                             max = computerScore[i][j];
328                             u = i;
329                             v = j; 
330                         } else if(computerScore[i][j] == max) {
331                             if(myScore[i][j] > myScore[u][v]) {
332                                 u = i;
333                                 v = j;
334                             }
335                         }
336 
337                     }
338                 }
339             }
340 
341             _compi = u;
342             _compj = v;
343             oneStep(u, v, false);
344             chressBord[u][v] = 2; //计算机占据位置
345             for(var k = 0; k < count; k++) {
346                 if(wins[u][v][k]) {
347                     computerWin[k]++;
348                     _myWin[k] = myWin[k];
349                     myWin[k] = 6; //这个位置对方不可能赢了;
350                     if(computerWin[k] == 5) {
351                         resultTxt.innerHTML = "┗|`O′|┛ 嗷~~,计算机赢了,继续加油!";
352                         over = true;
353                     }
354                 }
355             }
356             if(!over) {
357                 me = !me;
358             }
359             backAble = true;
360             returnAble = false;
361             var hasClass = new RegExp('unable').test("" + returnbtn.className + "");
362             if(!hasClass) {
363                 returnbtn.className += " " + "unable";
364             }
365         }
366 
367         //绘画键盘;
368         var drawChessBoard = function() {
369             for(var i = 0; i < 15; i++) {
370                 context.moveTo(15 + i * 30, 15);
371                 context.lineTo(15 + i * 30, 435);
372                 context.stroke();
373                 context.moveTo(15, 15 + i * 30);
374                 context.lineTo(435, 15 + i * 30);
375                 context.stroke();
376             }
377         }
378 
379         //画棋子
380         var oneStep = function(i, j, me) {
381             context.beginPath();
382             context.arc(15 + i * 30, 15 + j * 30, 13, 0, 2 * Math.PI); //画圆
383             context.closePath();
384             //渐变
385             var gradient = context.createRadialGradient(15 + i * 30 + 2, 15 + j * 30 - 2, 13, 15 + i * 30 + 2, 15 + j * 30 - 2, 0);
386 
387             if(me) {
388                 gradient.addColorStop(0, '#0a0a0a');
389                 gradient.addColorStop(1, '#636766');
390             } else {
391                 gradient.addColorStop(0, '#d1d1d1');
392                 gradient.addColorStop(1, '#f9f9f9');
393             }
394             context.fillStyle = gradient;
395             context.fill();
396         }
397 
398         //销毁棋子
399         var minusStep = function(i, j) {
400             //擦除该圆
401             context.clearRect((i) * 30, (j) * 30, 30, 30);
402 
403             //重画该圆周围的格子
404             context.beginPath();
405             context.moveTo(15 + i * 30, j * 30);
406             context.lineTo(15 + i * 30, j * 30 + 30);
407             context.moveTo(i * 30, j * 30 + 15);
408             context.lineTo((i + 1) * 30, j * 30 + 15);
409             context.stroke();
410         }
411     </script>
412 
413 </html>

以下是对源码的分析与学习笔记:

五子棋小游戏代码详解:

结构上:

一个h3用来放标题,给了个id同时为了后期就可以更改提示信息放进去。

放一块画布

放三个按钮,分别是重来,悔棋,放弃悔棋。

样式中:

一:box-shadow

Box-shadow值得注意:一个box同时用了两个box-shadow;如下:

box-shadow: -2px -2px 2px #efefef, 5px 5px 5px #b9b9b9;

做一个案例彻底分析下:

box-shadow: -2px -2px 2px #f00, 5px 5px 5px #164A84;

为了看着明白,特地弄了对比明显的颜色。

色值说明:#f00【红色】, #164A84【蓝色】

X,y值得说明:-2px -2px, 5px 5px;【这么写,阴影是在是坐上和右下】

角度和x,y取值的关系表:

x,y的取值

阴影所在的角度

有阴影的两条边是

总结:

+x,+y

右下角

右边和下边

从左上角开始想象:

+x,-y

右上角

右边和上边

X负责左右,正右负左;

-x,+y

左下角

左边和下边

Y负责上下,正下负上;

-x,-y

左上角

左边和上边

二、display:flex;

Flex浏览器支持情况很差,仅火狐和谷歌通用。Ie10还不支持,手机上的浏览器全军覆没。

兼容写法:

display:-webkit-flex;

display: -moz-flex;

一个flexbox布局是有一个伸缩容器(flex containers)和这个容器里的伸缩内容(flex items)组成。

伸缩容器(flex containers)是一个HTML标签元素,并且“display”属性显式的设置了“flex”属性值。在伸缩容器中的所有子元素都会自动变成伸缩项目(flex items)。

三、Flex-direction:row(默认值);

四、Justify-content: center;

注:

本代码纯属学习与练习之用

源代码及博文见掘金地址:https://juejin.im/post/594669d461ff4b006cf132ff

git地址:https://github.com/wj704/wj704.github.io/blob/master/five_game.html

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏游戏开发那些事

【Unity3d游戏开发】浅谈UGUI中的Canvas以及三种画布渲染模式

  Canvas画布是承载所有UI元素的区域。Canvas实际上是一个游戏对象上绑定了Canvas组件。所有的UI元素都必须是Canvas的自对象。如果场景中没...

17710
来自专栏IMWeb前端团队

rem不是神农草,治不了移动端百病

有很多朋友一聊起做移动端重构,第一个问题就是用什么单位合适。%,还是rem?(如果你还不太了解rem是什么单位,可先前往CSS3的REM设置字体大小了解。) 然...

232100
来自专栏Coco的专栏

不可思议的纯CSS导航栏下划线跟随效果

24630
来自专栏Thinks

谈响应式web设计代码实现

在研究响应式的时候,记录了一些感想,分享出来,抛砖引玉,希望可以和大家一起讨论。总结下来,响应式比之前想象的要复杂得多。 1. ie9以下(不包括ie9)采用i...

6710
来自专栏数据小魔方

图表案例|全球游戏行业用户渠道调查报告(尼尔森)

今天要跟大家分享的是一个尼尔森的典型图表案例——全球游戏行业用户渠道调查报告! 而且本图表是一个使用单选按钮的动态图表,非常适合作为案例来讲,同时可以巩固一下最...

40080
来自专栏韦弦的偶尔分享

微信小程序展开全文

设置130为临界值,是试了3行基本不超过120rpx,4行基本大于140rpx,取了个中间值

24010
来自专栏Coco的专栏

两行 CSS 代码实现图片任意颜色赋色技术

14020
来自专栏前端杂货铺

尽量使用translate而不是改变top/left进行动画(翻译)

前言     本文翻译自 Why Moving Elements With Translate() Is Better Than Pos:abs Top/lef...

30640
来自专栏Coco的专栏

不可思议的纯CSS导航栏下划线跟随效果

30230
来自专栏我和未来有约会

CaseStudy(showcase)界面篇-desing设计界面

做silvelight也有一段时间了,相册、游戏,刚刚完成的showcase这个小程序算是一个阶段了。这里就以showcase这个项目来做一下CaseStudy...

18470

扫码关注云+社区

领取腾讯云代金券