P&D 过河游戏智能帮助
本次作业基本要求是三选一,我选择了P&D 过河游戏智能帮助实现
3、P&D 过河游戏智能帮助实现,程序具体要求:
- 实现状态图的自动生成
- 讲解图数据在程序中的表示方法
- 利用算法实现下一步的计算
- 参考:P&D 过河游戏智能帮助实现
状态图
以下状态图摘自上面的参考博客,主要表示了3个牧师与3个魔鬼的游戏所有可能出现的状况。而如果要实现智能游戏帮助,则需要用代码的形式自动生成以下状态图。
实现方法
刚好在结束的实训中学习到了两大类搜索算法(盲目式搜索与启发式搜索),这两大搜索方法都能以较快的速率遍历状态图的所有状态,这样就可以找到一条通往游戏结束状态的路径。由于此游戏状态比较少,经过测试速度也还可以,所以我就使用了广度优先搜索的方法寻找路径(使用启发式搜索的A*算法会更加趋向于终点)。
图的表示方法
要实现路径的搜索,首先要将状态图抽象为一个数据结构。我选择使用邻接表表示图,所以每个状态就用一个自定义节点PAndDNode
来表示。
以下是实现这个状态节点的PAndDNode
类,首先需要解释一下PAndDNode
的一些属性:
- priestsNum:用于记录还未转移到目的地的牧师个数
- devilsNum:用于记录还未转移到目的地的魔鬼的个数
- parent:相当于指针,指向发展到这个状态的状态父节点
除了上面的属性,我还未这个状态节点定义了一些行为,以方便后面BFS算法的实现:
public bool IsValid()
:判断该状态是否合法,也就是判断此状态是否导致游戏失败public bool Move(int path)
:将此状态转移到下一状态,在图论中就是访问邻接点。这里每种状态都会有5个邻接状态可以转移(当然实际种不是每个状态都能有5个,所以会在实现的5个Move函数中判断是否能够执行该转移),所以根据输入的int数来指引到相应的Move函数中。- 其他的还有构造函数以及属性的get函数,还有需要重写节点的比较函数Equals及其绑定在一起的函数。
public class PAndDNode
{
private const int maxPriests = 3;
private const int maxDevils = 3;
int priestsNum;
int devilsNum;
private PAndDNode parent;
public PAndDNode(int priestsNum, int devilsNum)
{
if (priestsNum <= maxPriests && devilsNum <= maxDevils)
{
this.priestsNum = priestsNum;
this.devilsNum = devilsNum;
this.parent = null;
}
else