亲测可行:
使用蓝桥杯比赛编译器:DEV C++
求迷宫中从入口到出口的路径是一个经典的程序设计问题,通常采用“穷举求解”的方法,即顺着某一方向向前探索,若能走通,则继续往前走;否则原路返回,换一个方向继续探索,直至所有可能的通路都探索到为止。 因此,在求解迷宫问题的时候应用“栈”也就是自然而然的事了。 对于程序来说:
1.我们需要规定一个方向作为主方向,使得“自己”的位置不断移动,直到“遇到走不通的地方”或者是“遇到之前走过的地方”。
方向定义:
东:1
南:2
西:3
北:4
2.我们需要直到我们经过哪些地方,在这里我们将除栈顶外的其他元素视为“经过的地方”!!!
3.我们需要一个二维数组存放“迷宫”,还需要一个二维数组存放“走过的地方”。
迷宫:
走过的地方:(这里把所有地点初始化为0,代表尚未经过,经过的地方会被重新赋值为1)
4.最后,当我们“走”到终点的时候,路径的每一个“点”都会存放到“栈”中,我们将其依次d出即可得到最终路径。
过程截图:
栈: 顺序栈,栈中每一个结构体对应一个点,x表示该点的横坐标,y表示该点的纵坐标,direction表示该点的方向。 代码实现:
#include
#include
#define MAXSIZE 10
//定义迷宫
int arr[MAXSIZE][MAXSIZE] = {
1,1,1,1,1,1,1,1,1,1,
1,0,0,1,1,1,1,1,1,1,
1,1,0,1,0,0,0,0,1,1,
1,1,0,1,0,1,1,0,1,1,
1,1,0,0,0,1,1,0,1,1,
1,1,0,1,0,1,1,0,1,1,
1,1,0,1,0,1,1,0,1,1,
1,1,0,1,0,1,1,0,1,1,
1,1,0,0,0,0,1,0,2,1,
1,1,1,1,1,1,1,1,1,1
};
//行走过的标志
int arr_tar[MAXSIZE][MAXSIZE] = {0};
//栈的数据域
typedef struct Stack
{
int x;
int y;
int direction;
}Stack;
//顺序栈
typedef struct SqStack
{
Stack* base;
int top;
}SqStack;
//初始化
void InitStack(SqStack* stack)
{
stack->base = (Stack*)malloc(MAXSIZE * MAXSIZE * sizeof(Stack));
stack->top = 0;
}
//入栈
void InsertStack(SqStack* stack, Stack data)
{
stack->base[stack->top] = data;
stack->top++;
printf("arr[%d][%d]成功入栈!\n", data.x, data.y);
}
//出栈
Stack PopStack(SqStack* stack)
{
stack->top--;
printf("arr[%d][%d]成功出栈!\n", stack->base[stack->top].x, stack->base[stack->top].y);
return stack->base[stack->top];
}
//判栈空
int StackEmpty(SqStack* stack)
{
if (stack->top == 0)
{
return 1;
}
else
{
return 0;
}
}
//取栈顶元素
Stack GetTop(SqStack* stack)
{
int q = stack->top - 1;
return stack->base[q];
}
//判断该位置是否为墙和之前是否经过
int CanPass(Stack data)
{
if (arr[data.x][data.y] == 1 || arr_tar[data.x][data.y] == 1)
{
return 1;
}
else
{
return 0;
}
}
//判断该位置是否为出口
int IsEnd(Stack data)
{
if (arr[data.x][data.y] == 2)
{
printf("发现出口!!!\n");
return 1;
}
else
{
return 0;
}
}
//移动
void move(SqStack* stack)
{
Stack data = GetTop(stack);
Stack new_data;
if (data.direction == 1)//东
{
printf("向东走了一格\n");
new_data.direction = 1;
new_data.x = data.x;
new_data.y = data.y + 1;
}
else if (data.direction == 2)//南
{
printf("向南走了一格\n");
new_data.direction = 1;
new_data.x = data.x + 1;
new_data.y = data.y;
}
else if (data.direction == 3)//西
{
printf("向西走了一格\n");
new_data.direction = 1;
new_data.x = data.x;
new_data.y = data.y - 1;
}
else if (data.direction == 4)//北
{
printf("向北走了一格\n");
new_data.direction = 1;
new_data.x = data.x - 1;
new_data.y = data.y;
}
InsertStack(stack, new_data);
}
//更新走过的路径
void AddPath(Stack data)
{
arr_tar[data.x][data.y] = 1;
}
void PopPath(Stack data)
{
arr_tar[data.x][data.y] = 0;
}
int main()
{
SqStack* stack = (SqStack*)malloc(sizeof(SqStack));
//遍历迷宫
int i, j;
for (i = 0;i < MAXSIZE; i++)
{
for (j = 0;j < MAXSIZE; j++)
{
printf("%d\t", arr[i][j]);
}
printf("\n");
}
printf("--------------------破译中--------------------\n");
//初始化
InitStack(stack);
//设置初始点
int x = 1, y = 1;
Stack data = {x, y, 1};
InsertStack(stack, data);
do
{
if(!CanPass(GetTop(stack)))//不是墙并且从未走过
{
if (IsEnd(GetTop(stack)))//检测出口
{
break;
}
else
{
AddPath(GetTop(stack));
move(stack);//添加下一个块到栈中
}
}
else//是墙
{
PopStack(stack);
PopPath(GetTop(stack));//栈顶元素的路径不算入经过地点
if (!StackEmpty(stack))
{
if (GetTop(stack).direction == 4 && !StackEmpty(stack))
{
AddPath(GetTop(stack));
PopStack(stack);
PopPath(GetTop(stack));
}
if (GetTop(stack).direction < 4)
{
//更新栈顶坐标的方向
stack->base[stack->top - 1].direction++;
}
}
}
//getchar();
}while(!StackEmpty(stack));
printf("--------------------破译完毕--------------------\n");
//输出结果
while (!StackEmpty(stack))
{
data = PopStack(stack);
arr[data.x][data.y] = 3;
}
//遍历迷宫
for (i = 0;i < MAXSIZE; i++)
{
for (j = 0;j < MAXSIZE; j++)
{
printf("%d\t", arr[i][j]);
}
printf("\n");
}
return 0;
}
欢迎大家留言交流
结语:这不仅仅是一个算法,你把他加点功能(增删改查),他就变成了期末的课程设计。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)