五子棋小游戏学习——
有一个问题是,棋盘线的颜色,在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