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