目前,我正在用Erlang开发一个国际象棋在线游戏服务器(一款手机游戏)。我遇到了关于AI方法的问题(是使用极小极大算法、遗传算法还是其他方法)。同时,我也遇到了定义合适的启发式函数的问题。我需要的是一个如何开始实现的思路,同时考虑到语言、有限的资源和服务器响应时间(超时),因为这是一个在线手机游戏。
需要一些关于算法和启发式函数的想法。
回答:
正如我的AI教授常说的:在游戏AI中,程序性能的主要差异在于细节,而不是所使用的算法。用于这些棋盘游戏的算法通常只有20-30行代码,使AI引擎强大或弱小的关键是开发者通过利用游戏细节来减少搜索空间的能力。这只能通过对特定游戏的深入了解来有效实现。
跳棋的搜索空间适中(事实上它已经被完全解决),但它是开始棋盘游戏AI编程的一个好起点。因此,我建议你从经典的alpha-beta剪枝算法开始。
但是,正如我之前所说,选择算法只是工作的10%。细节更为重要,所以让我们来看看这些细节:
-
启发式函数:这是关键点。一个启发式函数必须是:计算快速且简单,并且能很好地描述给定状态的价值。通常,启发式函数只是一个特征集的加权和。在这篇文章中,你可以找到一个简单的启发式函数(以及调整它的遗传方法),它使用了如棋子数量、王数量和移动值(每个玩家的合法移动数量)等特征。另一个提示:启发式函数应返回整数值:仅因0.0003的差异而偏好一个分支是愚蠢的,因此最好将启发式函数四舍五入为整数值。
-
利用对称性:如果你能在棋盘位置中找到对称性,你必须考虑到这一点!在跳棋中,对称性不多,但我认为你仍然可以做一些事情。
-
预计算:这就是跳棋被解决的方式。:) 但显然你不需要存储所有东西。国际象棋AI通常有一个开局库和一个残局库。这些是预计算的动作(或基于规则的动作),允许你的软件在开始和结束阶段避免大量计算。
-
探索放松(作弊)问题:这是一个非常有用的技巧。例如,你可以假设你可以连续走两步,而你的对手什么也不做。如果你不能通过作弊达到一个好的位置,那么在正常游戏中(对手试图反击你)你也无法达到一个好的位置,你可以简单地丢弃那条路径。
这些只是我能给你的关于这个问题的几个小建议。我无法完整覆盖,因为这是一个非常大的领域,但我希望你能明白我的意思。你将通过经验找到新的和更好的想法。:)
关于时间相关的问题:时间有限的AI引擎使用alpha-beta剪枝算法的迭代加深版本(在这篇文章中有详细信息和进一步的资料)。这种方法有两个主要优点:你可以在任何时候停止计算,并且可以利用前几次迭代来改进下一次的搜索启发式。如果你不得不多次重新开始搜索,这绝对优于传统的alpha-beta剪枝算法。
希望你能发现这些有用。