在 C++ 递归错误中找到一条迷宫路径
Find a path through a maze in C++ recursion error
我正在尝试编写一个函数来寻找穿过迷宫的路径。还有另一个函数从文本文件中读取迷宫。现在,当迷宫为 20 行和 20 列时,我编写的用于查找路径的函数可以正常工作,但它不适用于任何其他变体。这是我为该函数编写的代码:
void find_paths(maze m, int r, int c, int rows, int cols) {
if (r == rows - 1)
display(m, rows, cols);
else {
if (r > 0 && m[r - 1][c] == space) // UP
{
m[r - 1][c] = path;
find_paths(m, r - 1, c, rows, cols);
m[r - 1][c] = space;
}
if (m[r + 1][c] == space) // DOWN
{
m[r + 1][c] = path;
find_paths(m, r + 1, c, rows, cols);
m[r + 1][c] = space;
}
if (m[r][c - 1] == space) // LEFT
{
m[r][c - 1] = path;
find_paths(m, r, c - 1, rows, cols);
m[r][c - 1] = space;
}
if (m[r][c + 1] == space) // RIGHT
{
m[r][c + 1] = path;
find_paths(m, r, c + 1, rows, cols);
m[r][c + 1] = space;
}
}
}
space 是一个 char =' '
路径是一个 char ='.'
这是程序读取的迷宫文件的屏幕截图。
这是程序执行的屏幕截图。
我是 C++ 的新手,希望你能帮助我。
正如 Benjamin Barrois 在评论中提到的那样,您需要一种方法来了解您是否检查过一条路线,如果是,则不要再次使用。
我建议使用“.”以外的其他字符。 (路径)以区分死胡同和实际解决方案,尽管这还不够。
所以我会添加一个名为 visited = 'x';
的变量并将其用于 return。
此外,您在第一个测试 (UP) 中检查了 r > 0
,但在另一个 if()
(DOWN、LEFT、RIGHT)中没有检查任何此类限制。虽然如果你在那里有正确的字符,它会起作用(即它会先撞到墙上)但如果不是这样,你就会开始碰到错误的字符。
void find_paths(maze m, int r, int c, int rows, int cols) {
if (r == rows - 1)
display(m, rows, cols);
else {
if (r > 0 && m[r - 1][c] == space) // UP
{
m[r - 1][c] = path;
find_paths(m, r - 1, c, rows, cols);
m[r - 1][c] = visited;
}
if (r + 1 < rows && m[r + 1][c] == space) // DOWN
{
m[r + 1][c] = path;
find_paths(m, r + 1, c, rows, cols);
m[r + 1][c] = visited;
}
if (c > 0 && m[r][c - 1] == space) // LEFT
{
m[r][c - 1] = path;
find_paths(m, r, c - 1, rows, cols);
m[r][c - 1] = visited;
}
if (c + 1 < cols && m[r][c + 1] == space) // RIGHT
{
m[r][c + 1] = path;
find_paths(m, r, c + 1, rows, cols);
m[r][c + 1] = visited;
}
}
}
也就是说,您当前的算法不会在找到解决方案时停止,因为它是递归的,它将永远继续下去。如果您希望能够摆脱困境,您的函数需要 return true(成功!)或 false(继续搜索)。
虽然使用递归机制的想法对于找到所有解决方案很有用,尤其是(如果你要计算的话)解决方案的长度,所以你 return 只有较短的解决方案(这是通常是关于迷宫搜索的内容。)
bool find_paths(maze m, int r, int c, int rows, int cols) {
if (r == rows - 1) {
display(m, rows, cols);
return true;
}
else {
if (r > 0 && m[r - 1][c] == space) // UP
{
m[r - 1][c] = path;
if(find_paths(m, r - 1, c, rows, cols)) {
return true;
}
m[r - 1][c] = visited;
}
if (r + 1 < rows && m[r + 1][c] == space) // DOWN
{
m[r + 1][c] = path;
if(find_paths(m, r + 1, c, rows, cols) {
return true;
}
m[r + 1][c] = visited;
}
if (c > 0 && m[r][c - 1] == space) // LEFT
{
m[r][c - 1] = path;
if(find_paths(m, r, c - 1, rows, cols) {
return true;
}
m[r][c - 1] = visited;
}
if (c + 1 < cols && m[r][c + 1] == space) // RIGHT
{
m[r][c + 1] = path;
if(find_paths(m, r, c + 1, rows, cols) {
return true;
}
m[r][c + 1] = visited;
}
}
return false;
}
附带说明一下,这并非特定于 C++。
没有太大的错误(尽管可以更有效地完成)。它很可能不起作用,因为您缺少列的边界检查。
由于您允许列获取任何值,因此您可能会超出迷宫的范围。
您的另一个问题是,当您找到解决方案时,您仍然采用所有其他递归路径。
这只是对您的代码的一个小改动,应该可以工作:
bool done = false;
void find_paths(maze m, int r, int c, int rows, int cols) {
if(done) {
return;
}
if (r == rows - 1) {
display(m, rows, cols);
done = true;
} else {
if (r > 0 && m[r - 1][c] == space) // UP
{
m[r - 1][c] = path;
find_paths(m, r - 1, c, rows, cols);
m[r - 1][c] = space;
}
if (m[r + 1][c] == space) // DOWN
{
m[r + 1][c] = path;
find_paths(m, r + 1, c, rows, cols);
m[r + 1][c] = space;
}
if (c > 0 && m[r][c - 1] == space) // LEFT
{
m[r][c - 1] = path;
find_paths(m, r, c - 1, rows, cols);
m[r][c - 1] = space;
}
if (c < cols && m[r][c + 1] == space) // RIGHT
{
m[r][c + 1] = path;
find_paths(m, r, c + 1, rows, cols);
m[r][c + 1] = space;
}
}
}
我正在尝试编写一个函数来寻找穿过迷宫的路径。还有另一个函数从文本文件中读取迷宫。现在,当迷宫为 20 行和 20 列时,我编写的用于查找路径的函数可以正常工作,但它不适用于任何其他变体。这是我为该函数编写的代码:
void find_paths(maze m, int r, int c, int rows, int cols) {
if (r == rows - 1)
display(m, rows, cols);
else {
if (r > 0 && m[r - 1][c] == space) // UP
{
m[r - 1][c] = path;
find_paths(m, r - 1, c, rows, cols);
m[r - 1][c] = space;
}
if (m[r + 1][c] == space) // DOWN
{
m[r + 1][c] = path;
find_paths(m, r + 1, c, rows, cols);
m[r + 1][c] = space;
}
if (m[r][c - 1] == space) // LEFT
{
m[r][c - 1] = path;
find_paths(m, r, c - 1, rows, cols);
m[r][c - 1] = space;
}
if (m[r][c + 1] == space) // RIGHT
{
m[r][c + 1] = path;
find_paths(m, r, c + 1, rows, cols);
m[r][c + 1] = space;
}
}
}
space 是一个 char =' ' 路径是一个 char ='.'
这是程序读取的迷宫文件的屏幕截图。
这是程序执行的屏幕截图。
我是 C++ 的新手,希望你能帮助我。
正如 Benjamin Barrois 在评论中提到的那样,您需要一种方法来了解您是否检查过一条路线,如果是,则不要再次使用。
我建议使用“.”以外的其他字符。 (路径)以区分死胡同和实际解决方案,尽管这还不够。
所以我会添加一个名为 visited = 'x';
的变量并将其用于 return。
此外,您在第一个测试 (UP) 中检查了 r > 0
,但在另一个 if()
(DOWN、LEFT、RIGHT)中没有检查任何此类限制。虽然如果你在那里有正确的字符,它会起作用(即它会先撞到墙上)但如果不是这样,你就会开始碰到错误的字符。
void find_paths(maze m, int r, int c, int rows, int cols) {
if (r == rows - 1)
display(m, rows, cols);
else {
if (r > 0 && m[r - 1][c] == space) // UP
{
m[r - 1][c] = path;
find_paths(m, r - 1, c, rows, cols);
m[r - 1][c] = visited;
}
if (r + 1 < rows && m[r + 1][c] == space) // DOWN
{
m[r + 1][c] = path;
find_paths(m, r + 1, c, rows, cols);
m[r + 1][c] = visited;
}
if (c > 0 && m[r][c - 1] == space) // LEFT
{
m[r][c - 1] = path;
find_paths(m, r, c - 1, rows, cols);
m[r][c - 1] = visited;
}
if (c + 1 < cols && m[r][c + 1] == space) // RIGHT
{
m[r][c + 1] = path;
find_paths(m, r, c + 1, rows, cols);
m[r][c + 1] = visited;
}
}
}
也就是说,您当前的算法不会在找到解决方案时停止,因为它是递归的,它将永远继续下去。如果您希望能够摆脱困境,您的函数需要 return true(成功!)或 false(继续搜索)。
虽然使用递归机制的想法对于找到所有解决方案很有用,尤其是(如果你要计算的话)解决方案的长度,所以你 return 只有较短的解决方案(这是通常是关于迷宫搜索的内容。)
bool find_paths(maze m, int r, int c, int rows, int cols) {
if (r == rows - 1) {
display(m, rows, cols);
return true;
}
else {
if (r > 0 && m[r - 1][c] == space) // UP
{
m[r - 1][c] = path;
if(find_paths(m, r - 1, c, rows, cols)) {
return true;
}
m[r - 1][c] = visited;
}
if (r + 1 < rows && m[r + 1][c] == space) // DOWN
{
m[r + 1][c] = path;
if(find_paths(m, r + 1, c, rows, cols) {
return true;
}
m[r + 1][c] = visited;
}
if (c > 0 && m[r][c - 1] == space) // LEFT
{
m[r][c - 1] = path;
if(find_paths(m, r, c - 1, rows, cols) {
return true;
}
m[r][c - 1] = visited;
}
if (c + 1 < cols && m[r][c + 1] == space) // RIGHT
{
m[r][c + 1] = path;
if(find_paths(m, r, c + 1, rows, cols) {
return true;
}
m[r][c + 1] = visited;
}
}
return false;
}
附带说明一下,这并非特定于 C++。
没有太大的错误(尽管可以更有效地完成)。它很可能不起作用,因为您缺少列的边界检查。 由于您允许列获取任何值,因此您可能会超出迷宫的范围。 您的另一个问题是,当您找到解决方案时,您仍然采用所有其他递归路径。
这只是对您的代码的一个小改动,应该可以工作:
bool done = false;
void find_paths(maze m, int r, int c, int rows, int cols) {
if(done) {
return;
}
if (r == rows - 1) {
display(m, rows, cols);
done = true;
} else {
if (r > 0 && m[r - 1][c] == space) // UP
{
m[r - 1][c] = path;
find_paths(m, r - 1, c, rows, cols);
m[r - 1][c] = space;
}
if (m[r + 1][c] == space) // DOWN
{
m[r + 1][c] = path;
find_paths(m, r + 1, c, rows, cols);
m[r + 1][c] = space;
}
if (c > 0 && m[r][c - 1] == space) // LEFT
{
m[r][c - 1] = path;
find_paths(m, r, c - 1, rows, cols);
m[r][c - 1] = space;
}
if (c < cols && m[r][c + 1] == space) // RIGHT
{
m[r][c + 1] = path;
find_paths(m, r, c + 1, rows, cols);
m[r][c + 1] = space;
}
}
}