【数据结构 迷宫问题求解】栈的应用|c语言|迷宫问题

以下算法均是原创,未参考任何资料!请勿抄袭!欢迎交流。

亲测可行:

使用蓝桥杯比赛编译器:DEV C++ 


求迷宫中从入口到出口的路径是一个经典的程序设计问题,通常采用“穷举求解”的方法,即顺着某一方向向前探索,若能走通,则继续往前走;否则原路返回,换一个方向继续探索,直至所有可能的通路都探索到为止。

因此,在求解迷宫问题的时候应用“”也就是自然而然的事了。

对于程序来说:

1.我们需要规定一个方向作为主方向,使得“自己”的位置不断移动,直到“遇到走不通的地方”或者是“遇到之前走过的地方”。

方向定义:

东:1

南:2

西:3

北:4

2.我们需要直到我们经过哪些地方,在这里我们将除栈顶外的其他元素视为“经过的地方”!!!

3.我们需要一个二维数组存放“迷宫”,还需要一个二维数组存放“走过的地方”。

迷宫:

 走过的地方:(这里把所有地点初始化为0,代表尚未经过,经过的地方会被重新赋值为1)

 4.最后,当我们“走”到终点的时候,路径的每一个“点”都会存放到“栈”中,我们将其依次弹出即可得到最终路径。

 过程截图:

 


栈:

顺序栈,栈中每一个结构体对应一个点,x表示该点的横坐标,y表示该点的纵坐标,direction表示该点的方向。

代码实现: 

#include <stdio.h>
#include <stdlib.h>

#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;
} 

欢迎大家留言交流

结语:这不仅仅是一个算法,你把他加点功能(增删改查),他就变成了期末的课程设计。

  • 32
    点赞
  • 222
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

活成自己的样子啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值