我正在尝试解决这个问题:
鉴于迷宫,它希望找到从给定起始位置到奶酪位置的路径(目标 位置)。迷宫可视化为包含墙(表示为1)或自由方式的矩形网格 (表示为0)。程序必须打印从起始位置到结束位置的路径。 目标位置将存储值9。在该程序中,假设循环路径不是 可能在网格中。 (您无需检查循环路径。)
这就是我在做的事情:
#include<stdio.h>
typedef struct Maze
{
int ** values;
int size;
} Maze;
int traverse (Maze M, int n, int posi, int posj, char **path_so_far,
int past_i, int past_j)
{
int k;
printf("Hello\n");
int i=0;
int temp;
if (M.values[posi][posj] == 9)
{
path_so_far[i][0] = posi + '0';
path_so_far[i][1] = posj + '0';
path_so_far[i][2] = '\0';
printf("%s\n", path_so_far[i]);
i++;
return 1;
}
else if (posi - 1 >= 0 && M.values[posi - 1][posj] != 1
&& posi - 1 != past_i)
{
temp = traverse(M, n, posi - 1, posj, path_so_far, past_i, past_j);
if (temp == 1)
{
path_so_far[i][0] = posi + '0';
path_so_far[i][1] = posj + '0';
path_so_far[i][2] = '\0';
printf("%s\n", path_so_far[i]);
i++;
return 1;
}
}
else if (posi + 1 < n && M.values[posi + 1][posj] != 1 && posi + 1 != past_i)
{
temp = traverse(M, n, posi + 1, posj, path_so_far, past_i, past_j);
if (temp == 1)
{
path_so_far[i][0]=posi+'0';
path_so_far[i][1]=posj+'0';
path_so_far[i][2]='\0';
printf("%s\n",path_so_far[i]);
i++;
return 1;
}
}
else if(posj - 1 >=0 && M.values[posi][posj - 1] !=1 && posj - 1 != past_j)
{
temp = traverse(M, n, posi, posj - 1, path_so_far, past_i, past_j);
if(temp==1)
{
path_so_far[i][0] = posi + '0';
path_so_far[i][1] = posj + '0';
path_so_far[i][2] = '\0';
printf("%s\n", path_so_far[i]);
i++;
return 1;
}
}
else if (posj + 1 < n && M.values[posi][posj + 1] != 1 && posj + 1 != past_j)
{
temp = traverse(M, n, posi, posj + 1, path_so_far, past_i, past_j);
if(temp == 1)
{
path_so_far[i][0] = posi + '0';
path_so_far[i][1] = posj + '0';
path_so_far[i][2] = '\0';
printf("%s\n", path_so_far[i]);
i++;
return 1;
}
}
else
{
return 0;
}
}
迷宫M已被照顾,即它在另一个功能中初始化,这里未示出。我使用参数traverse
调用(M, 0, 0, 0, path, 0, 0)
,但它会产生分段错误。我尝试添加printf("Hello\n")
,如我的代码的第10行所示,以查看错误发生的位置;它大量打印“Hello”,最后给出segmentation fault
。我做错了什么?
答案 0 :(得分:2)
您的代码设计中存在一些重要错误。其中一个是i
变量使用(参见我的评论)。另一种是打印路径步骤的方法:首先,在从递归traverse
返回之后打印第i步是错误的(因为所有后续步骤都已打印在递归里面!);但是,在递归之前你也无法打印(因为你不知道你是否在正确的道路上)。那么,怎么做呢?
好吧,你应该在path_so_far[i]
标记下一步,然后进入递归。您还需要将递增的步骤编号i+1
传递给递归步骤,以便该函数始终知道它正在执行哪个步骤,以及它应填充的path_so_far
项。
当您到达目标点时,您只需打印整个累积的path_so_far
,此刻为最终路径,然后返回1
以获得成功。这个结果渗透了最终导致计算结束的递归。
另一方面,如果您发现无法进一步移动,则会因失败而返回0
。递归traverse
的结果应该会导致您在当前级别测试另一种可能性。
所以:
int traverse(Maze M, int n, int posi, int posj,char **path_so_far, int i)
{
int temp;
if(M.values[posi][posj]==9) // target found
{
int j; // print the complete path
for(j=0; j<i; j++)
printf("%s\n",path_so_far[j]);
return 1;
}
// mark the current position as 'visited'
M.values[posi][posj] = 2;
// try next possible move
// test if adjacent cell is empty or is target
if(posi-1>=0 && (M.values[posi-1][posj]==0 || M.values[posi-1][posj]==9))
{
path_so_far[i][0]=posi-1+'0';
path_so_far[i][1]=posj+'0';
path_so_far[i][2]='\0';
temp=traverse(M,n,posi-1,posj,path_so_far,i+1);
if(temp==1)
return 1;
}
if(posi+1<n && (M.values[posi+1][posj]==0 || M.values[posi+1][posj]==9))
{
path_so_far[i][0]=posi+1+'0';
path_so_far[i][1]=posj+'0';
path_so_far[i][2]='\0';
temp=traverse(M,n,posi+1,posj,path_so_far,i+1);
if(temp==1)
return 1;
}
// similary for posj-1 and posj+1...
if(posj-1>=0 && (M.values[posi][posj-1]==0 || M.values[posi][posj-1]==9))
{
...
}
if(posj+1<n && (M.values[posi][posj+1]==0 || M.values[posi][posj+1]==9))
{
...
}
// none of the tested paths returned success...
// mark the current position as no longer 'visited'
M.values[posi][posj] = 0;
//return the failure status
return 0;
}
答案 1 :(得分:1)
您似乎使用参数past_i
和past_j
来避免加倍,但是当您递归时,您不会传递前一个位置的坐标,因为这样的方案有效。例如,看来这......
temp = traverse(M, n, posi - 1, posj, path_so_far, past_i, past_j);
......应该......
temp = traverse(M, n, posi - 1, posj, path_so_far, posi, posj);
。如果不这样做,你可以(并且确实)在两个位置之间来回(看起来可能在0,1和1,1之间)。您的代码还有其他问题,例如没有正确记录路径,但分段错误可能是由于递归深度足以耗尽堆栈空间。
答案 2 :(得分:1)
并非traverse()
中的所有路径都返回值。包含
if(temp == 1)
{
...
return 1;
}
时,将无法返回任何函数值
(temp != 1)
您必须在编译器上启用所有警告...尤其是当事情不起作用时。