Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何递归地运行一棵树,创建节点,调用函数,并深入研究?_Java_Loops_Recursion - Fatal编程技术网

Java 如何递归地运行一棵树,创建节点,调用函数,并深入研究?

Java 如何递归地运行一棵树,创建节点,调用函数,并深入研究?,java,loops,recursion,Java,Loops,Recursion,目前,我正在尝试开发一款类似于国际象棋的AI游戏,我基本上是先计算几步,然后通过alpha-beta获得可能的最佳回报 目前我的策略是,每走一步,做出4个最好的结果动作,暂时改变“棋盘”,然后对于这4个动作,再次调用4个,然后运行这些动作,每走4个 对于递归函数来说,这似乎很自然,我一直在尝试向下挖掘10步左右。但到目前为止,我已经写了3个步骤(轮到我了,你的,我的),我的代码已经爆炸了。我需要编码的部分,其中为每一个新的移动,计算新的移动。我是否可以截断下面的代码,使其类似于递归调用(…),并

目前,我正在尝试开发一款类似于国际象棋的AI游戏,我基本上是先计算几步,然后通过alpha-beta获得可能的最佳回报

目前我的策略是,每走一步,做出4个最好的结果动作,暂时改变“棋盘”,然后对于这4个动作,再次调用4个,然后运行这些动作,每走4个

对于递归函数来说,这似乎很自然,我一直在尝试向下挖掘10步左右。但到目前为止,我已经写了3个步骤(轮到我了,你的,我的),我的代码已经爆炸了。我需要编码的部分,其中为每一个新的移动,计算新的移动。我是否可以截断下面的代码,使其类似于递归调用(…),并以最大级别检查作为基本情况

这是我当前迭代的3步代码,假设有一个树结构,每个移动包含一个包含4个最佳计数器移动的数组列表

 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()){
推(儿童);
}
}
}
这两种算法有大量的优化,例如根据某些指标(启发式方法,例如)以不同顺序处理子代的算法,其他算法跟踪已访问的节点