关于本文:

这是本蒟蒻的第一篇博客,介绍了我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) {
//鼠标点击容差再30以内(只要点击范围在以交叉点为中心的30*30的正方形状内,都算该交叉点)
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]++;
}
//如果玩家赢了,则弹出警告框显示 you win!
if (myWin[k] == 5) {
alert("you win!");
}

}
//调用ai算法
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
//ai 算法
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++) {
//for循环嵌套,遍历棋盘
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;
//case 3和4只是增加的分数不同,略
}
//ai加分大于myscore,故为攻击型,即case 1中加的分数>10,略
//判断落子点
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

本蒟蒻目前只会这样一种方法,有其他思路的欢迎提供嘿嘿。