标签:查找 alpha 延时 xeon 子节点 cdn 玩家 car 出现
利用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节点可以获得一个值小于对方约束的最小值,那么对方是肯定不会走这里的,所以本节点的其他子节点可以剪掉。
哈希表本质上就是一个数组,只不过是通过哈希函数映射某个关键码来获取数组的下标。正是利用了数组空间连续查询高效,所以哈希函数如果设计得好,能够在的复杂度下实现查找。
但是容易出现冲突,就是不同的关键码通过哈希函数映射出同一个值,这个时候就需要解决冲突的策略。大体上分为两种:
本质上就是状态的转移。它从某一个初始状态开始,一直转移到状态无法转移为止。如果把搜索的过程看作一棵树,那么信息的传递就会是自下而上或者是自上而下,然后对应的最终的完整信息状态就会出现在根或者是叶子。对于我这个五子棋,信息的传递就是自上而下的,也即最终某个方向上棋局的状态是搜索到叶子处获得。
标签:查找 alpha 延时 xeon 子节点 cdn 玩家 car 出现
原文地址:https://www.cnblogs.com/GorgeousBankarian/p/12590343.html