当前位置:   article > 正文

【前端】AI五子棋游戏186行

【前端】AI五子棋游戏186行

这个来源于网上,不过代码改了不少,减少了些代码便于学习。 

  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4. <h3>AI五子棋游戏</h3>
  5. <canvas id="chess" width="450px" height="450px"></canvas>
  6. <script>
  7. var chressBord = []; //棋盘
  8. var wins = []; //存放所有5个棋子在一条线上所有可能性,第一维存放y, 第二维存放x,第三维存放当前的可能性编号
  9. var count = 0; //赢法总数量
  10. var myWin = []; //我们赢法的统计数组
  11. var computerWin = []; //计算机赢法的统计数组
  12. var chess = document.getElementById("chess");
  13. var context = chess.getContext('2d');
  14. for(var i = 0; i < 15; i++)
  15. {
  16. chressBord[i] = [];
  17. wins[i] = [];
  18. for(var j = 0; j < 15; j++)
  19. {
  20. chressBord[i][j] = 0;
  21. wins[i][j] = [];
  22. }
  23. }
  24. //横线赢法
  25. for(var i = 0; i < 15; i++)
  26. for(var j = 0; j < 11; j++,count++)
  27. for(var k = 0; k < 5; k++)
  28. wins[i][j+k][count] = true;
  29. //竖线赢法
  30. for(var i = 0; i < 15; i++)
  31. for(var j = 0; j < 11; j++,count++)
  32. for(var k = 0; k < 5; k++)
  33. wins[j+k][i][count] = true;
  34. //正斜线赢法
  35. for(var i = 0; i < 11; i++)
  36. for(var j = 0; j < 11; j++,count++)
  37. for(var k = 0; k < 5; k++)
  38. wins[i+k][j+k][count] = true;
  39. //反斜线赢法
  40. for(var i = 0; i < 11; i++)
  41. for(var j = 14; j > 3; j--,count++)
  42. for(var k = 0; k < 5; k++)
  43. wins[i+k][j-k][count] = true;
  44. for(var i = 0; i < count; i++)
  45. {
  46. myWin[i] = 0; //这个数组很精髓,记录下棋后我方每一个位置在每种赢法的得分
  47. computerWin[i] = 0;
  48. }
  49. chess.onclick = function(e) // 我,下棋
  50. {
  51. var i = Math.floor(e.offsetX / 30);
  52. var j = Math.floor(e.offsetY / 30);
  53. if(chressBord[i][j] == 0)
  54. {
  55. MoveStep(i,j,"red", 1, myWin);
  56. computerAI();
  57. }
  58. }
  59. // 计算机下棋,找玩家最容易赢的位置或者电脑最容易赢的位置
  60. var computerAI = function ()
  61. {
  62. var myScore = [];
  63. var computerScore = [];
  64. var max = 0;
  65. var u = 0, v = 0;
  66. for(var i = 0; i < 15; i++)
  67. {
  68. myScore[i] = [];
  69. computerScore[i] = [];
  70. for(var j = 0; j < 15; j++)
  71. {
  72. myScore[i][j] = 0;
  73. computerScore[i][j] = 0;
  74. }
  75. }
  76. //找落子赢的概率最大坐标
  77. for(var i = 0; i < 15; i++)
  78. {
  79. for(var j = 0; j < 15; j++)
  80. {
  81. for(var k = 0; k < count; k++) //遍历到i,j这个坐标时,计算谁的得分更高
  82. {
  83. if(chressBord[i][j] != 0 || !wins[i][j][k]) //当前i,j坐标还没落子
  84. continue;
  85. switch(myWin[k])
  86. {
  87. case 1: myScore[i][j] += 200; break;
  88. case 2: myScore[i][j] += 400; break;
  89. case 3: myScore[i][j] += 2000; break;
  90. case 4: myScore[i][j] += 10000; break;
  91. }
  92. switch(computerWin[k])
  93. {
  94. case 1: computerScore[i][j] += 220; break;
  95. case 2: computerScore[i][j] += 420; break;
  96. case 3: computerScore[i][j] += 2100; break;
  97. case 4: computerScore[i][j] += 20000; break;
  98. }
  99. }
  100. if(myScore[i][j] > max) //如果玩家落子的分数多,就替换
  101. {
  102. max = myScore[i][j];
  103. u = i;
  104. v = j;
  105. }
  106. else if(myScore[i][j] == max) //如果玩家落子的分数跟原来最多分数一样多
  107. {
  108. if(computerScore[i][j] > computerScore[u][v]) //如果电脑在i,j落子的分数比u,v的分数多,就替换
  109. {
  110. u = i;
  111. v = j;
  112. }
  113. }
  114. if(computerScore[i][j] > max) //如果电脑下棋新位置分数比原来的多,就替换
  115. {
  116. max = computerScore[i][j];
  117. u = i;
  118. v = j;
  119. }
  120. else if(computerScore[i][j] == max) //如果电脑下棋新位置分数跟原来的一样多
  121. {
  122. if(myScore[i][j] > myScore[u][v]) //如果玩家落子的分数多,就准备把玩家最好的位置占掉
  123. {
  124. u = i;
  125. v = j;
  126. }
  127. }
  128. }
  129. }
  130. MoveStep(u,v,"blue", 2, computerWin);
  131. }
  132. var CheckWin = function(i, j, Role, WinArray)
  133. {
  134. for(var k = 0; k < count; k++)
  135. if(wins[i][j][k]) // 将可能赢的情况都加1
  136. {
  137. WinArray[k]++;
  138. if(WinArray[k] >= 5)
  139. alert(Role + ': 恭喜,你赢了!')
  140. }
  141. }
  142. //绘画棋盘
  143. var drawChessBoard = function()
  144. {
  145. for(var i = 0; i < 15; i++)
  146. {
  147. context.moveTo(15 + i * 30 , 15);
  148. context.lineTo(15 + i * 30 , 435);
  149. context.moveTo(15 , 15 + i * 30);
  150. context.lineTo(435 , 15 + i * 30);
  151. context.stroke();
  152. }
  153. }
  154. drawChessBoard(); // 画棋盘
  155. var MoveStep = function(i,j,Role, ID, WinArray) //落子
  156. {
  157. context.beginPath();
  158. context.arc(15 + i * 30, 15 + j * 30, 13, 0, 2 * Math.PI);// 画圆
  159. context.closePath();
  160. context.fillStyle = Role;
  161. context.fill(); //填充颜色
  162. chressBord[i][j] = ID; //玩家ID棋盘位置占位
  163. CheckWin(i,j,Role, WinArray); //判断是否获胜,这里也很精髓,递归思想
  164. }
  165. </script>
  166. </body>
  167. </html>

附原来的代码

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

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号