最近,实训课上老师布置了若干题目,其中有一个题目是:
提供一个迷宫,用非递归的方法求出一条走出迷宫的路径。
我的想法是:在一个点上,只有上下左右四个方向,只要有规律的探索,就可以找到一条合适的路径了,这里没有要求最佳路径,难度更为低了。
方向的顺序可以自己定,我的顺序就是:从上到下,从左到右。
假定一个点开始,往上走,如果能通过,则把上面的位置的方向定为“上往左”;
以往上面走一步的位置为中心,如果不能往左,就改成“直往上”;
如果不能往上,就改成“上往右”;
如果不能往右,此时,就已经无路可走了,只能回退一步了。
这种情况就如下图所示(图片中的起点在左上角,此时焦点在右上角):
很奇怪的,为什么为什么要叫“上往左”、“上往右”这么奇怪的名字呢?
实际上,这是有很大影响的。假如只有上下左右四种记录方向,如果全路程没有死路的话,是可以这么用的,但是在遇到死路的时候,往回走的路到底在哪里?这就无法解决了。
这里的“上往左”可能有读者不理解,这里做个说明:前面的“上”代表上一步走的是哪个方向,这样就可以知道当遇到死路时,怎么往回走,后面的“左”代表当前要往哪个方向走。
到什么时候需要回退呢?
如下面图片所示,当都转了一圈的时候,就往回走:
上面的图片怎么理解?以下为例:
下面有路时,就从“下往左”、“直往下”、“下往右”按顺序搜索,如果能找到路就继续走下去;如果“下往右”时,依然走不了,就回退。
我写了一个简单的过程,代码如下:
#include<stdio.h>
#include<Windows.h>
#define N 10
int x = 1, y = 1, back
= 0;
int image[N][N] = {
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 2, 0, 1, 0, 0, 0, 1, 0, 1 },
{ 1, 0, 0, 1, 0, 0, 0, 1, 0, 1 },
{ 1, 0, 0, 0, 0, 1, 1, 0, 0, 1 },
{ 1, 0, 1, 1, 1, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
{ 1, 0, 1, 0, 0, 0, 1, 0, 0, 1 },
{ 1, 0, 1, 1, 1, 0, 1, 1, 0, 1 },
{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
};
HANDLE hOutput;
COORD coord = { 0, 0 };
void change()
{
//2直往上,3直往下,4直往左,5直往右
//11左往上,12左往下,13右往上,14右往下,15上往左,16上往右,17下往左,18下往右
//直往上
if (image[x][y] == 2)
{
//如果回退了
if (back == 1)
{
image[x][y] = 16;
back = 0;
}
else
{
//如果上面的位置为空
if (image[x - 1][y] == 0)
{
image[x - 1][y] = 15;
x--;
}
//如果不为空
else
{
//改成上往右
image[x][y] = 16;
}
}
}
//直往下
else if (image[x][y] == 3)
{
//如果回退了
if (back == 1)
{
image[x][y] = 18;
back = 0;
}
else
{
//如果下面的位置为空
if (image[x + 1][y] == 0)
{
image[x + 1][y] = 17;
x++;
}
//如果不为空
else
{
//改成下往右
image[x][y] = 18;
}
}
}
//直往左
else if (image[x][y] == 4)
{
//如果回退了
if (back == 1)
{
image[x][y] = 12;
back = 0;
}
else
{
//如果左面的位置为空
if (image[x][y - 1] == 0)
{
image[x][y - 1] = 11;
y--;
}
//如果不为空
else
{
//改成左往下
image[x][y] = 12;
}
}
}
//直往右
else if (image[x][y] == 5)
{
//如果回退了
if (back == 1)
{
image[x][y] = 14;
back = 0;
}
else
{
//如果右面的位置为空
if (image[x][y + 1] == 0)
{
image[x][y + 1] = 13;
y++;
}
//如果不为空
else
{
//改成右往下
image[x][y] = 14;
}
}
}
//左往上
else if (image[x][y] == 11)
{
//如果回退了
if (back == 1)
{
image[x][y] = 4;
back = 0;
}
else
{
//如果上面的位置为空
if (image[x - 1][y] == 0)
{
image[x - 1][y] = 15;
x--;
}
//如果不为空
else
{
//改成往左
image[x][y] = 4;
}
}
}
//左往下
else if (image[x][y] == 12)
{
//如果回退了
if (back == 1)
{
image[x][y] = 0;
y++;
}
else
{
//如果下面的位置为空
if (image[x + 1][y] == 0)
{
image[x + 1][y] = 17;
x++;
}
//如果不为空
else
{
back = 1;
image[x][y] = 0;
y++;
}
}
}
//右往上
else if (image[x][y] == 13)
{
//如果回退了
if (back == 1)
{
image[x][y] = 5;
back = 0;
}
else
{
//如果上面的位置为空
if (image[x - 1][y] == 0)
{
image[x - 1][y] = 15;
x--;
}
//如果不为空
else
{
//改成往右
image[x][y] = 5;
}
}
}
//右往下
else if (image[x][y] == 14)
{
//如果回退了
if (back == 1)
{
image[x][y] = 0;
y--;
}
else
{
//如果下面的位置为空
if (image[x + 1][y] == 0)
{
image[x + 1][y] = 17;
x++;
}
//如果不为空
else
{
back = 1;
image[x][y] = 0;
y--;
}
}
}
//上往左
else if (image[x][y] == 15)
{
//如果回退了
if (back == 1)
{
image[x][y] = 2;
back = 0;
}
else
{
//如果左面的位置为空
if (image[x][y - 1] == 0)
{
image[x][y - 1] = 11;
y--;
}
//如果不为空
else
{
//改成往上
image[x][y] = 2;
}
}
}
//上往右
else if (image[x][y] == 16)
{
//如果回退了
if (back == 1)
{
image[x][y] = 0;
x++;
}
else
{
//如果右面的位置为空
if (image[x][y + 1] == 0)
{
image[x][y + 1] = 13;
y++;
}
//如果不为空
else
{
back = 1;
image[x][y] = 0;
x++;
}
}
}
//下往左
else if (image[x][y] == 17)
{
//如果回退了
if (back == 1)
{
image[x][y] = 3;
back = 0;
}
else
{
//如果左面的位置为空
if (image[x][y - 1] == 0)
{
image[x][y - 1] = 11;
y--;
}
//如果不为空
else
{
//改成往下
image[x][y] = 3;
}
}
}
//下往右
else if (image[x][y] == 18)
{
//如果回退了
if (back == 1)
{
image[x][y] = 0;
x--;
}
else
{
//如果右面的位置为空
if (image[x][y + 1] == 0)
{
image[x][y + 1] = 13;
y++;
}
//如果不为空
else
{
back = 1;
image[x][y] = 0;
x--;
}
}
}
}
void show()
{
//以下四行,隐藏光标
CONSOLE_CURSOR_INFO cci;
cci.bVisible = 0;
cci.dwSize = 1;
SetConsoleCursorInfo(hOutput, &cci);
//以下两行,防闪屏
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOutput, coord);
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
switch (image[i][j])
{
case 0:
printf(" ");
break;
case 1:
printf("■");
break;
case 2:
case 11:
case 13:
printf("↑");
break;
case 3:
case 12:
case 14:
printf("↓");
break;
case 4:
case 15:
case 17:
printf("←");
break;
case 5:
case 16:
case 18:
printf("→");
break;
default:
printf("出现错误!");
break;
}
}
printf("\n");
}
}
int main()
{
for (; !(x == 8 && y == 8);)
{
change();
show();
Sleep(100);
system("cls");
}
return 0;
}
出发点在左上角,终点在右下角,最终路径如下: