所有。我正在尝试获得一个minimax算法的版本,以便在学校项目的c#中运行。我们正试图制作一个简单的Mancala AI。
为此,我设置了一个由包含所有子值的节点组成的树以及有关该板的其他信息,以模拟未来的移动。
最初,我希望树有一个可变的根 - 而不是每次电路板改变时重做树,我希望找到与当前电路板匹配的子节点,从那时起完成所有工作,扩展它,并从那里开始工作。
当我更新我的树时,我正在尝试一个简单的for循环:
for(int i = 0; i < 6; i++) {
...
if(bCopy.stonesAt(myPits[i]) == (myPits[myPits.Length-i-1]))
myChildren[i]= new MaxNode(...);
else
myChildren[i] = new MinNode(...);
}
} else {
myChildren[i].addChildren(board, depth);
}
}
省略号代替代码或参数,以使其可读。
这就是给我带来这么多麻烦的原因。由于Mancala有一些允许你再次移动的移动,因此无法知道给定的子节点是MinNode还是MaxNode。我已将MinNodes和MaxNodes都设置为抽象类DecisionNode的子类。
我希望最后一行(myChildren [i] .addChildren(board,depth))会降到最低级别,并使用MaxNode addChildren或MinNode addChildren,具体取决于哪个是合适的。但是,它使用DecisionNode addChildren方法。
我想将代码保存在单独的类中,因为它太乱了。有没有办法这样做?
编辑:我应该提一下,我已经将DecisionNode.addChildren设置为虚拟和MinNode&amp; MaxNode addChildren设置为覆盖。但是,似乎因为myChildren [i]的类型在编译时是未知的,所以它默认为父类。方法调用转到
public virtual bool addChildren(Board b, int depth) {
return true;
}
而不是其中一个子类。
答案 0 :(得分:2)
对myChildren [i] .addChildren的调用应该导致调用MinNode.addChildren或MaxNode.addChildren,只要在基类DecisionNode中标记方法virtual
,并且override
in派生类。
例如,在您的抽象基类中,您应该:
public abstract class DecisionNode
{
public virtual void addChildren(...)
{
...
}
}
在你的派生类中,你应该有:
public class MinNode : DecisionNode
{
public override void addChildren(...)
{
...
}
}
答案 1 :(得分:2)
更新:
我最近遇到过类似的问题,我写了一个递归后代语言解析器。抽象语法树是解析器用来表示语言的结构。我强烈建议您使用访客设计模式进行调查。基本上,您创建一个由所有树节点实现的IVisitable接口。然后,实现实现一个Accept方法,并将自身的实例传递给任何调用它的IVisitor实例。
一旦你实现了这个模式,你可以随意遍历你的树,做任何你想做的事情,而不会影响你的基本代码。当您希望某些节点实现某个行为而其他节点不实现时,它尤其有用。它的功能与派生类相反。
无论如何,对于之前的倒退答案感到抱歉。
答案 2 :(得分:0)
我找到了答案!或者,如果不是答案,至少有一个会起作用。使AddChildren的DecisionNode方法抽象似乎已经成功了。