关于本文:
这是本蒟蒻的第一篇博客,介绍了我5升6暑假用一周时间做的作品
语言: Html5, JavaScript
成品:五子棋AI
正文:
摘要 :
阿尔法狗对战柯洁围棋大赛很热门,那只是人工智能中的一个方向,展示了机器能代替人做某些事情。而围棋是很讲究智力的游戏,所以实现起来也是很难的,我用JS写了一个小程序——五子棋,五子棋相对来讲简单很多。
关键词 :
人工智能;网页编程;HTML5/JavaScript;
制作背景 :
现在,人工智能技术突飞猛进,许多职业已被机器取代,那么怎样用简单的算法实现五子棋ai呢?
制作材料 :
电脑
设计思路 :
棋盘的实现:
通过循环画直线
棋子的实现:
画出你想要的棋子,渐变填充颜色,封装成一个函数供调用。
落子的实现:
用数组存放每一个落子点,满足条件就落下对应的子
赢法数组:
用一个二维的数组记录五子棋的所有赢法。每种赢法都有一个值,值达到5就结束游戏。
确定计算机落子点:
这是难点,我们通过为某种赢法附一个权值,权值最大的就是落子价值最大的。
实现计算机落子:
通过上一步计算机找到了权值最大的落子坐标后,我们就可以实现落子了。
制作过程:
第一步:写H5框架:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <!doctype html> <html > <head > <meta charset ="utf-8" > <title > Wu Zi Qi--AI</title > <style type ="text/css" > </style > </head > <body > <script type ="text/javascript" > </script > </body > </html >
第二步:
本程序主要使用canvas检测鼠标点击返回
值来进行落子,创建canvas对象:
1 2 document .body.innerHTML = '<canvas id="chess" width="450" height="450"> </canvas>' ;var chess = document .getElementById('chess' );
第三步:
创建赢法数组,统计数组等
1 2 3 4 5 6 7 8 var wins = [];var count = 0 ;var myWin = [];var computerWin = [];
第四步:
创建并初始化数组显示棋盘
1 2 3 4 5 6 7 var chessBoard = []; for (var i = 0 ; i < 15 ; i++) { chessBoard[i] = []; for (var j = 0 ; j < 15 ; j++) { chessBoard[i][j] = 0 ; }
第五步:
画棋盘
1 2 3 4 5 6 7 8 9 10 11 12 var context = chess.getContext('2d' ); for (var i = 0 ; i < 15 ; i++) { context.strokeStyle = '#00000' ; context.beginPath(); context.moveTo(15 , 15 + i * 30 ); context.lineTo(435 , 15 + i * 30 ); context.moveTo(15 + i * 30 , 15 ); context.lineTo(15 + i * 30 , 435 ); context.stroke(); }
第六步:
对赢法数组进行初始化和赋值
1 2 3 4 5 6 7 8 9 10 11 for (var i = 0 ; i < 15 ; i++) { for (var j = 0 ; j < 11 ; j++) { for (var k = 0 ; k < 5 ; k++) { wins[i][j+k][count] = true ; } count++; } }
第七步:
初始化玩家和ai数组(略
第八步:
画棋子,为了使棋子更加逼真,可以在棋子的脚上加一点渐变色,比如黑色棋子的右上角有白色渐变,从而模仿真实棋子反光(图一)。同时获取鼠标点击的位置,进行落子。
最后检查玩家获胜(即五子相连)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 chess.onclick = function (e ) { var i = Math .floor(e.offsetX / 30 ); var j = Math .floor(e.offsetY / 30 ); if (chessBoard[i][j] != 0 ) { return ; } context.beginPath(); context.arc(15 + i * 30 , 15 + j * 30 , 13 , 0 , 2 * Math .PI); var grd = context.createRadialGradient(15 + i * 30 , 15 + j * 30 , 13 , 15 + i * 30 + 2 , 15 + j * 30 - 2 , 0 ); grd.addColorStop(0 , 'black' ); grd.addColorStop(1 , 'white' ); context.fillStyle = grd; context.fill(); context.stroke(); chessBoard[i][j] = 1 ; for (var k = 0 ; k < count; k++) { if (wins[i][j][k]) { myWin[k]++; } if (myWin[k] == 5 ) { alert("you win!" ); } } setTimeout ("computerAI()" ,5000 ); }
第九步:
这是本程序最核心的部分–ai算法。
这里主要是运用了二维数组进行存储每个点上的危险指数,比如玩家在中心位置下了一颗棋子,那么ai就会对这个棋子周围一圈通过计算,加上相对应的值。例:图二,玩家为黑方,控制台中第六行第八列(经过反转处理)为黑子的落子点,周围对应的点加上了对应的值。
那么现在可以分两种ai,一种是进攻类,一种是防守类,两者的区别在于ai的分数和玩家的分数加的多少。
1.进攻类ai
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 function computerAI ( ) { var myScore = []; var computerScore = []; var max = 0 ; var u = 0 , v = 0 ; for (var i = 0 ; i < 15 ; i++) { myScore[i] = []; computerScore[i] = []; for (var j = 0 ; j < 15 ; j++) { myScore[i][j] = 0 ; computerScore[i][j] = 0 ; } } for (var i = 0 ; i < 15 ; i++) { for (var j = 0 ; j < 15 ; j++) { if (chessBoard[i][j] == 0 ) { for (var k = 0 ; k < count; k++) { if (wins[i][j][k]) { switch (myWin[k]) { case 1 : myScore[i][j] += 10 ; break ; case 2 : myScore[i][j] += 200 ; break ; } if (myScore[i][j] > max) { max = myScore[i][j]; u = i; v = j; } else if (myScore[i][j] == max) { if (computerScore[i][j]>computerScore[u][v]){ u = i; v = j; } } } } } } }
2.防守型 :
防守型为myscore加分大于ai,故为防守型(代码大致相似,略)
第十步:
画白色棋子,检查ai获胜(与玩家代码相似,略)
最终效果图:
[作者简介]
X3B0A1,女,北京市昌平区中山实验学校
主要研究方向:人工智能,c++、python、HTML5/JavaScript
1 2 3 4 5 6 7 8 9 10 参考资料: [1]JavaScript - 人工智能 五子棋AI篇 https://edu.csdn.net/course/detail/8660? [2]五子棋AI设计心得 https://zhuanlan.zhihu.com/p/42811904 [3]jS实现五子棋——AI篇 https://www.jianshu.com/p/83fa8cc31a38 [4]jS实现五子棋——UI篇 https://www.jianshu.com/p/b178be0fbec3
欢迎各位大佬提出意见awa
本蒟蒻目前只会这样一种方法,有其他思路的欢迎提供嘿嘿。