最近做了五子棋,记录下自己完成五子棋的人机对战的思路。
首先,思路是这样的:每当人手动下一颗棋子(黑子)的时候,应当遍历它周围棋子的情况,并赋予周围棋子一定的权值,当在机器要下棋子(白子)守护之前,会遍历整个棋盘的权值情况(棋盘的权值存在一个二维数组中),从中找出权值最大的点坐标,并下子(白子)。
这样的话,问题就集中在两个方面了,一个是:如何遍历黑子周围的棋子情况? 另一个是:如何设定权值?
首先,是设定权值。这个没有固定的设定方案,可以先试着设定,然后,尝试效果后(主要是白子的攻防情况是否合理),再调整。
以下是我的设定方案:
接着,是相对困难的部分,就是如何遍历黑子周围的棋子情况。 从之前权值方案中可以看到,设置权值的一个很重要的目的是为了进行防守,所以应当在连续黑子的两端(下面图中的橙色区域)设置权值,这样就有利于白子填充在连续黑子的两端,从而达到防守的目的,下面这张图可以说明:
中心的黑子:表示当前所下的黑子,周围的棋子表示是之前下的。
红色箭头:表示需要遍历的八个方向,因为中心黑子的坐标(i, j)是已知的,所以很容易得到周围的棋子坐标(i+n, j+m)。
橙色方框:表示连续黑子的末端,可能是空白(表示还没有棋子填充),也可能是白子。
接着是算法思想:
首先,应当先判断敌方棋子(黑子)第一次下的时候(敌方棋子先下),此时,周围八个棋子都是空的,于是应当对周围八个点赋予相同的权值(活一),当遍历整个棋盘后,便在这八个点中随机选择一个(用随机数),填上黑子。
接着,敌方继续下子,如果敌方当前所下棋子与之前的棋子连续,则会构成活二或者眠二(以此类推,会构成活三眠三~~),这时,根据权值表,会赋予周围棋子更大的权值(权值应当是累加的,也就是说,当前权值 += 之前权值),最后遍历后,下白子。