五子棋人机对战

Posted gorgeousbankarian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了五子棋人机对战相关的知识,希望对你有一定的参考价值。

1.? 项目流程

UI界面部分

利用Java的图形界面工具swing和awt来绘制棋盘的框架,绘制了19X19的网格。然后在画布上增加监听器来监听鼠标点击的部分,然后在邻近的网格交点处绘制棋子,这样就实现了下棋的效果。

逻辑处理部分

19X19的棋盘,就用19X19的二维数组来存储棋盘的信息。每当玩家新增加一个棋子,后台部分就会遍历一遍数组,对每一个槽进行8个方向深度为5的DFS搜索,判断是否有五子相连的情况,这样就实现了输赢的判断。

人机对战原理

简而言之就是统计棋型累计评分,例如4个我方或对方的棋子相连,那么权重就是一个非常大的数,用来表示这个位置非常重要;如果是一个3个棋子相连也赋予一个对应权值。我把这种棋局用字符串表示,权重用整型数表示,以键值对的方式存储在一个HashMap中,那么这个哈希表就是电脑的判断棋局的依据。接着在电脑出手的时候,就遍历一遍二维数组,同样是对每一个槽进行8个方向的DFS搜索,之后查询哈希表累计该槽的权值。遍历完之后,权值最大的位置就是电脑下棋的位置。

人机对战进阶

极大值极小值搜索

初始版本的AI只能根据当前的局势判断下一步,而极大极小值算法可以自己先多走几步,预判未来的局势再决定当前的局势。过程是这样的:


先设定好一个搜索树层数 Depth?,即要模拟 Depth?步;因为每一方都想赢,所以每一步的模拟都是模拟当前角色的最优下法,那么从AI方计算的视角来看,AI下棋的时候应该要使得全局的权值最大,对方下棋的时候就应要使得全局的权值最小;其实双方的最优下法逻辑是一样的,只不过从我方来看对方要_加个负号_,也可以说是我要使我的分数尽量大,对方要使我的分数尽量小。最后,综合模拟的若干步累计权值,取其中权值最大的下法下棋。


但是这个算法的开销很大,因为假设棋盘有N个空位,那么这棵搜索树的第一层就有N个节点,第二层就有N-1个节点……这样下去时间复杂度和空间复杂度都是指数级的增长技术图片,所以为了优化我们需要剪枝来舍去不必要的搜索。

技术图片剪枝

这个算法就是给搜索树上的每一个节点维护一个下界为技术图片上界为技术图片的窗口。这个窗口从父亲到儿子直接传递,从儿子回溯到父亲就要进行相应变化,因为搜索树结果信息是自底向上传递的,所以更新也是自底向上更新。如果当前为对方节点,那么对方会尽量使可取值小,故下拉上界技术图片;若当前使我方,则会尽量使可取值大,故上推下界技术图片

如果发现技术图片那么就可以剪枝了,为什么呢?首先一个前提是,当前的每一步都是由AI来模拟对于每一个下棋这的最优走法。假设当前为MAX方,那么由某个子节点的信息MAX方更新了技术图片发现技术图片,说明当前MAX节点可获得一个值大于由对方约束的最大值,那么对方是肯定不会走这里的,所以本节点之后的其他子节点就没有继续搜索的必要了;同理,假设当前为MIN方,那么由某个子节点的信息MIN方更新了技术图片,若发现技术图片,说明当前的MIN节点可以获得一个值小于对方约束的最小值,那么对方是肯定不会走这里的,所以本节点的其他子节点可以剪掉。

项目中遇到的问题

技术图片剪枝算法的检查

2. 知识点涉及

HashMap

哈希表本质上就是一个数组,只不过是通过哈希函数映射某个关键码来获取数组的下标。正是利用了数组空间连续查询高效,所以哈希函数如果设计得好,能够在技术图片的复杂度下实现查找。
但是容易出现冲突,就是不同的关键码通过哈希函数映射出同一个值,这个时候就需要解决冲突的策略。大体上分为两种:

  • 一种是开散列,就是把冲突放到哈希表外部解决,例如拉链法,Java中的 HashMap?就是利用拉链法来解决冲突的;
    • 第二种是闭散列,就是在哈希表内部解决冲突,例如开放地址法,桶式散列等等。

DFS

本质上就是状态的转移。它从某一个初始状态开始,一直转移到状态无法转移为止。如果把搜索的过程看作一棵树,那么信息的传递就会是自下而上或者是自上而下,然后对应的最终的完整信息状态就会出现在根或者是叶子。对于我这个五子棋,信息的传递就是自上而下的,也即最终某个方向上棋局的状态是搜索到叶子处获得。

3. 亮点

当然就是能够人机对战啦,还有自认为令人舒适的UI界面。

4. 可改进之处

  • 剪枝后的效率还是不太高,3层的延时在2s左右

5. 我的收获



![image.png](https://cdn.nlark.com/yuque/0/2020/png/1125446/1585147512491-f6e7512d-ae31-492a-b9aa-0c56c11aea81.png#align=left&display=inline&height=753&name=image.png&originHeight=1506&originWidth=1972&size=1607301&status=done&style=none&width=986)
![image.png](https://cdn.nlark.com/yuque/0/2020/png/1125446/1585147552688-c3bf5c4f-33cb-43b5-bd30-1231277e1962.png#align=left&display=inline&height=753&name=image.png&originHeight=1506&originWidth=1972&size=1052362&status=done&style=none&width=986)
![image.png](https://cdn.nlark.com/yuque/0/2020/png/1125446/1585147601106-10d64f34-7b7c-4ec0-95d1-f6d46f67b301.png#align=left&display=inline&height=753&name=image.png&originHeight=1506&originWidth=1972&size=1306047&status=done&style=none&width=986)

以上是关于五子棋人机对战的主要内容,如果未能解决你的问题,请参考以下文章

Java Swing局域网对战五子棋(人人和人机对战)

python实现五子棋-人机对战/人人对战(动图演示+源码分享)

C语言实现五子棋三子棋人机对战,包含电脑人工智能对战(可攻可守)(非标题党)

QT vs2017《五子棋》人机对战项目

C#五子棋小游戏源码(人机对战)

Android 蓝牙对战五子棋项目实现(含人机对战功能)