【问题标题】:Exit completely from a recursive function完全退出递归函数
【发布时间】:2017-06-28 23:05:33
【问题描述】:

我有一个关于我制作的递归函数的问题。一旦我到达“return arraydenodes”行,有没有办法可以完全退出函数?因为我使用visual studio跟踪代码执行,一旦执行到上述行,它就会从while循环返回到堆栈(或者我相信)直接进入“else”。正因为如此,path.Add 行继续执行,给了我不同的结果。这是代码。

private Node[] checkTheOtherDude(Node start, Node endpadre, Node end, Node previousNodeTemp)
{

    //Debug.Log(previousNode);
    while(endpadre != null && !stop)
    {

        if (!Physics.Linecast(end.transform.position, endpadre.transform.position)) // end y endpadre se ven?
        {
            previousNode = endpadre;
            Node newParent = endpadre.padre;

            checkTheOtherDude(start, newParent, end, previousNode); // chequear n y n padre padre

        }
        else
        {
            //previousNode = endpadre;
            path.Add(end);
            path.Add(previousNode);
            end = endpadre;
            Node newParent = end.padre;
            checkTheOtherDude(start, newParent, endpadre, previousNode);
        }
    }       
        stop = true;
        path.Add(end);
        path.Add(start);
        path.Reverse();
        arraydeNodes = path.ToArray();
        return arraydeNodes;                  
}

看来我已经解决了问题,问题(或者至少我认为)是 while 条件,将其更改为 while (endpadre != null && !stop && endpadre != start) 我错过了 endpadre != start 以便循环在结束时结束节点与起始节点相同。

【问题讨论】:

  • 如果你的设计正确,那应该没关系。如果你遇到麻烦,你的递归方法做的太多(关注点分离)或者结构不正确。当最里面的调用退出时,它应该自然地返回到堆栈的顶部,即在方法的正确返回结构内。
  • 当你在方法结束时递归退出时,直到每个递归调用到达它的退出点,你才会退出。这意味着遍历所有内容。考虑将退出条件放在递归方法的开头
  • 由于我不确切知道该函数应该做什么,因此对于这种特定情况这可能是错误的,但通常您希望return递归调用的结果。
  • 首先我不确定你为什么需要返回 Node[]。它在参数列表中,因此它会自动更新。一旦您可以消除 Node[] 作为返回值,您就可以返回一个布尔停止以回到顶部。我不同意 Rory 的回答,因为我编写了很多递归代码,在某些情况下您需要返回一个变量来停止处理。
  • 在 while 循环之后执行的代码可以执行多次(与您的递归级别一样多)吗? path.Reverse(); 也会被多次调用,我不确定你是否真的想要

标签: c# recursion unity3d while-loop


【解决方案1】:

while 循环之后的代码将被执行多次(与您的递归级别一样多)是否可以?
此外,path.Reverse() 将被多次调用,我不确定你是否真的想要。

要阻止该代码执行,您可以执行以下操作:

if (!stop)
{
     stop = true;
     path.Add(end);
     path.Add(start);
     path.Reverse();
     arraydeNodes = path.ToArray();
}

return arraydeNodes;      

我已经用它玩了一点,我已经修改了你的代码。
试试这个:

private Node[] checkTheOtherDude(Node start, Node endpadre, Node end, Node previousNodeTemp)
{
    if (endpadre == null)
    {
        path.Add(end);
        path.Add(start);
        path.Reverse();
        arraydeNodes = path.ToArray();
        return arraydeNodes;   
    }
    else if (!Physics.Linecast(end.transform.position, endpadre.transform.position)) // end y endpadre se ven?
    {
        previousNode = endpadre;
        Node newParent = endpadre.padre;

        return checkTheOtherDude(start, newParent, end, previousNode); // chequear n y n padre padre

    }
    else
    {
        //previousNode = endpadre;
        path.Add(end);
        path.Add(previousNode);
        end = endpadre;
        Node newParent = end.padre;
        return checkTheOtherDude(start, newParent, endpadre, previousNode);
    }                   
}

尝试使用测试数据运行此程序(仅几个节点)。然后检查第一次单击后的路径,然后调试第二次单击。您应该能够看到问题点。可能存在无限递归(节点括号内循环)

【讨论】:

  • 每次点击,代码运行并生成路径。第一次单击效果很好,第二次单击(在同一程序运行期间)会引发堆栈溢出错误。
  • 还是一样,我开始认为问题可能来自代码中的另一个地方,即使错误在这些行中说明。
  • 尝试用测试数据运行它(只有几个节点)。然后检查第一次单击后的路径,然后调试第二次单击。您应该能够看到问题点。也许有infinite recursion(节点括号中的循环)
  • 我设法解决了它,这实际上是另一回事,请查看我上面编辑的帖子。无论如何感谢您的帮助。
  • 嗯,我确实做到了,哈哈,这正是你所说的。
【解决方案2】:

是的,只需更改这两行

checkTheOtherDude(start, newParent, end, previousNode);
checkTheOtherDude(start, newParent, endpadre, previousNode);

return checkTheOtherDude(start, newParent, end, previousNode);
return checkTheOtherDude(start, newParent, endpadre, previousNode);

这些会让它一直向上返回

【讨论】:

  • 每次点击,代码运行并生成路径。第一次单击效果很好,第二次单击(在同一程序运行期间)会引发堆栈溢出错误。
  • @JackBauer 你不应该让你的递归方法引起副作用。这是你的主要问题。您的递归方法应该计算一个值并返回它,将它们需要的任何数据作为参数并将其所有计算作为返回值返回。如您所见,过程中的变异状态会造成巨大的混乱。
猜你喜欢
  • 2012-10-27
  • 1970-01-01
  • 1970-01-01
  • 2020-04-28
  • 2021-11-18
  • 1970-01-01
  • 2018-07-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多