返回函数返回main而不是调用者

时间:2013-09-12 23:19:23

标签: arrays recursion parameters return main

只是想知道......

void mazeTraversal(char maze[12][12], int x, int y)
{
if (maze[x + 1][y] == '.')
    mazeTraversal(maze, ++x, y);
if (maze[x][y + 1] == '.')
    mazeTraversal(maze, x, ++y);
if (maze[x - 1][y] == '.')
    mazeTraversal(maze, --x, y);
if (maze[x][y - 1] == '.')
    mazeTraversal(maze, x, --y);
   return;
}

当我遇到死胡同时,我是否应该恢复到之前的呼叫实例,而不是直接回到主要功能?如果我有问题请告诉我。

2 个答案:

答案 0 :(得分:2)

以下地址使用返回值捕获“正确路径”信息以及提供base case condition。但是,使用原始代码的另一个关键问题是使用++/--导致副作用对各自的变量。由于这个原因,下面的代码避开了这些运算符。


执行此操作的主要方法是返回一个值 - 例如, true 如果此路径导致并结束,否则 false

非常原始的转换将如下所示。注意添加基本情况 - 这意味着我们可以停止递归。返回True,以便之前的调用者也知道他们可以停止查看,并且函数堆栈将很快退回到“main”。

bool mazeTraversal(char maze[12][12], int x, int y) {
  // This is the BASE CASE and means WE ARE DONE LOOKING
  if (maze[x][y] == 'X') return true; // found end!

  if (maze[x + 1][y] == '.')
    if (mazeTraversal(maze, x + 1, y)) return true;

  if (maze[x][y + 1] == '.')
     if (mazeTraversal(maze, x, y + 1)) return true;

  if (maze[x - 1][y] == '.')
     if (mazeTraversal(maze, x - 1, y)) return true;

  if (maze[x][y - 1] == '.')
     if (mazeTraversal(maze, x, y - 1)) return true;

  return false; // didn't find any valid path from here
}

请注意我删除++/--以避免出现奇怪的副作用

但是,我们可以做得更好并清理一些代码。关键的区别是每个递归调用检查当前位置 - 而不是其邻居的位置。

bool mazeTraversal(char maze[12][12], int x, int y) {
  if (maze[x][y] == 'X')
    return true; // found end!

  if (maze[x][y] == '.') {
    // we are still on a path - see where exploration leads!
    if (mazeTraversal(maze, x + 1, y)) return true;
    if (mazeTraversal(maze, x, y + 1)) return true;
    if (mazeTraversal(maze, x - 1, y)) return true;
    if (mazeTraversal(maze, x, y - 1)) return true;
  }

  // Didn't find any valid path from here -
  // maybe "here" is a wall!
  return false;
}

最终,您可能希望在找到的路径上做其他事情(即在其中显示“return true”),例如记录当前位置。

另请注意,根据语言,if (mazeTraversal..) return true内容也可以“清理”。在C中,请考虑使用短路 ||运算符。然后我们可以将结束案例简化为:

int leadsToEnd =
       (maze[x][y] == 'X')      // at end
    || (maze[x][y] == '.')      // or not end ..
       && (mazeTraversal(maze, x + 1, y)   // but may lead to end
           || mazeTraversal(maze, x, y + 1)
           || mazeTraversal(maze, x - 1, y) 
           || mazeTraversal(maze, x, y - 1));

因此整个函数有效地变为return leadsToEnd(根据需要替换上述表达式)。当然,你必须决定采用哪种方法 - 后一个例子可以说是过于聪明 - 或者这种方式的混合对你来说最有意义。

答案 1 :(得分:0)

正如你现在所拥有的那样,当你遇到死胡同时,你就会回来。这是正确的,因为您将备份到上一个调用,然后选择下一个路径。当您遍历所有可能的路径时,您的顶级呼叫将返回。