Java 如何递归地运行一棵树,创建节点,调用函数,并深入研究?
目前,我正在尝试开发一款类似于国际象棋的AI游戏,我基本上是先计算几步,然后通过alpha-beta获得可能的最佳回报 目前我的策略是,每走一步,做出4个最好的结果动作,暂时改变“棋盘”,然后对于这4个动作,再次调用4个,然后运行这些动作,每走4个 对于递归函数来说,这似乎很自然,我一直在尝试向下挖掘10步左右。但到目前为止,我已经写了3个步骤(轮到我了,你的,我的),我的代码已经爆炸了。我需要编码的部分,其中为每一个新的移动,计算新的移动。我是否可以截断下面的代码,使其类似于递归调用(…),并以最大级别检查作为基本情况 这是我当前迭代的3步代码,假设有一个树结构,每个移动包含一个包含4个最佳计数器移动的数组列表Java 如何递归地运行一棵树,创建节点,调用函数,并深入研究?,java,loops,recursion,Java,Loops,Recursion,目前,我正在尝试开发一款类似于国际象棋的AI游戏,我基本上是先计算几步,然后通过alpha-beta获得可能的最佳回报 目前我的策略是,每走一步,做出4个最好的结果动作,暂时改变“棋盘”,然后对于这4个动作,再次调用4个,然后运行这些动作,每走4个 对于递归函数来说,这似乎很自然,我一直在尝试向下挖掘10步左右。但到目前为止,我已经写了3个步骤(轮到我了,你的,我的),我的代码已经爆炸了。我需要编码的部分,其中为每一个新的移动,计算新的移动。我是否可以截断下面的代码,使其类似于递归调用(…),并
for (i = 0; i < root.children.size(); i++) {
root.children.get(i).runStrat();
root.children.get(i).printNode();
for (int lvl1 : root.children.get(i).currOtherPieces) {
root.children.get(i).addChild(lvl1,root.children.get(i).level + 1);
}
for (j = 0; j < root.children.get(i).children.size(); j++) {
root.children.get(i).children.get(j).runStrat();
System.out.print(" ");
root.children.get(i).children.get(j).printNode();
for (int lvl2 : root.children.get(i).children.get(j).currSelfPieces) {
root.children.get(i).children.get(j).addChild(lvl2, root.children.get(i).children.get(j).level + 1);
}
for (k = 0; k < root.children.get(i).children.get(j).children.size(); k++) {
root.children.get(i).children.get(j).children.get(k).runStrat();
System.out.print(" ");
root.children.get(i).children.get(j).children.get(k).printNode();
}
}
}
for(i=0;i
正如您所见,我可以继续编写7层for循环,但也许有一种聪明的方法可以递归地将其放入。有什么帮助吗?谢谢
(带空格的sys.out只供我调试,可以省略…您正在做的是所谓的“行为树遍历”或“解决方案空间搜索”,即枚举所有可能的下一步操作并对其进行评估。行为树遍历只是一个应用程序 虽然我建议您充分了解广度优先树遍历和深度优先树遍历策略,但我可以快速回答您的问题 在处理树遍历时,您可能更喜欢迭代算法而不是递归算法,因为如果不进行尾部递归优化,您可能会遇到堆栈溢出问题 在遍历树时,您应该使用一个名为“边缘”的队列,该队列包含要访问的下一个节点
Queue<Node> fringe = new LinkedList<Node>();
然后,可以通过以下方式在条纹上迭代:
while(fringe.isEmpty() == false) {
Node current = fringe.poll();
// Evaluate the current move, e.g. if it leads to an improvement of your gameplay
boolean result = doSomething(current);
if(result && !current.getChildren().isEmpty()) {
fringe.addAll(current.getChildren();
}
}
此算法是BST(广度优先遍历)的一个简单实现,这意味着您在移动到下一个树级别之前访问给定树级别的所有子级。DFS(深度优先遍历)版本对边缘使用FIFO数据结构
Stack<Node> fringe = new LinkedList<Node>();
fringe.push(root);
while(fringe.isEmpty() == false) {
Node current = fringe.pop();
// Evaluate the current move, e.g. if it leads to an improvement of your gameplay
boolean result = doSomething(current);
if(result && !current.getChildren().isEmpty()) {
for(Node child: current.getChildren()) {
fringe.push(child);
}
}
}
Stack-borge=new-LinkedList();
推(根);
while(marge.isEmpty()==false){
节点电流=条纹.pop();
//评估当前的移动,例如,它是否会提高您的游戏性
布尔结果=剂量测量(当前);
if(result&!current.getChildren().isEmpty()){
对于(节点子节点:current.getChildren()){
推(儿童);
}
}
}
这两种算法有大量的优化,例如根据某些指标(启发式方法,例如)以不同顺序处理子代的算法,其他算法跟踪已访问的节点以避免循环,等等
为了更好地了解解决方案空间访问,我建议您阅读
为了计算搜索的深度,可以使用名为level的字段扩展节点对象,root的字段为0。在探索节点的子节点时,在将其插入边缘之前,只需将其级别设置为父节点的级别+1,如果该级别大于最大级别,则避免将其放入边缘。您所做的是所谓的“行为树遍历”或“解决方案空间搜索”,即枚举所有可能的下一步操作并对其进行评估。行为树遍历只是一个应用程序
Stack<Node> fringe = new LinkedList<Node>();
fringe.push(root);
while(fringe.isEmpty() == false) {
Node current = fringe.pop();
// Evaluate the current move, e.g. if it leads to an improvement of your gameplay
boolean result = doSomething(current);
if(result && !current.getChildren().isEmpty()) {
for(Node child: current.getChildren()) {
fringe.push(child);
}
}
}
虽然我建议您充分了解广度优先树遍历和深度优先树遍历策略,但我可以快速回答您的问题
在处理树遍历时,您可能更喜欢迭代算法而不是递归算法,因为如果不进行尾部递归优化,您可能会遇到堆栈溢出问题
在遍历树时,您应该使用一个名为“边缘”的队列,该队列包含要访问的下一个节点
Queue<Node> fringe = new LinkedList<Node>();
然后,可以通过以下方式在条纹上迭代:
while(fringe.isEmpty() == false) {
Node current = fringe.poll();
// Evaluate the current move, e.g. if it leads to an improvement of your gameplay
boolean result = doSomething(current);
if(result && !current.getChildren().isEmpty()) {
fringe.addAll(current.getChildren();
}
}
此算法是BST(广度优先遍历)的一个简单实现,这意味着您在移动到下一个树级别之前访问给定树级别的所有子级。DFS(深度优先遍历)版本对边缘使用FIFO数据结构
Stack<Node> fringe = new LinkedList<Node>();
fringe.push(root);
while(fringe.isEmpty() == false) {
Node current = fringe.pop();
// Evaluate the current move, e.g. if it leads to an improvement of your gameplay
boolean result = doSomething(current);
if(result && !current.getChildren().isEmpty()) {
for(Node child: current.getChildren()) {
fringe.push(child);
}
}
}
Stack-borge=new-LinkedList();
推(根);
while(marge.isEmpty()==false){
节点电流=条纹.pop();
//评估当前的移动,例如,它是否会提高您的游戏性
布尔结果=剂量测量(当前);
if(result&!current.getChildren().isEmpty()){
对于(节点子节点:current.getChildren()){
推(儿童);
}
}
}
这两种算法有大量的优化,例如根据某些指标(启发式方法,例如)以不同顺序处理子代的算法,其他算法跟踪已访问的节点