数据结构-栈与队列--迷宫问题

问题分析

  • 用一个二维数组**map表示迷宫的信息,其中‘0’表示可以通过,‘1’表示不可通过,如下图:
    在这里插入图片描述
  • 对于在一个点上的移动方向,可能是东西南北4方向,或者8方向,如下图:
    移动方向
  • 用一种方法实现找到从出口的到入口的路径。

实现方法

方向设置

  • 我们可以先构建方向结构 o f f s e t s offsets offsets,用数组 o f f s e t s & m o v e [ 4 ] 或 o f f s e t s & m o v e [ 8 ] offsets\&move[4]或offsets\&move[8] offsets&move[4]offsets&move[8]来表示方向
qmove[q].amove[q].b
N-10
NE-11
E01
SE11
S10
SW1-1
W0-1
NW-1-1
  • 代码如下:
//方向枚举:东、西、南、北、东北、东南、西北、西南
enum directions{E,W,S,N,NE,SE,NW,SW};

//表示方向
struct offsets
{
	int a, b;
};

//构建移动方向move
//设置方向:选择4方向还是8方向
offsets *move_set(int num = 4)
{
 /*方向表示表
  ___________________________
 | q | move[q].a | move[q].b |
 -----------------------------
 | N |    -1     |     0     |
 | NE|    -1     |     1     |
 | E |     0     |     1     |
 | SE|     1     |     1     |
 | S |     1     |     0     |
 | SW|     1     |    -1     |
 | W |     0     |    -1     |
 | NW|    -1     |    -1     |
 -----------------------------
 */ 
	offsets* move = new offsets[num];
	if (num == 4||num==8)
	{

		move[N].a = -1;
		move[N].b = 0;

		move[E].a = 0;
		move[E].b = 1;

		move[S].a = 1;
		move[S].b = 0;

		move[W].a = 0;
		move[W].b = -1;
	}
	
	if (num == 8)
	{
		move[NE].a = -1;
		move[NE].b = 1;

		move[SE].a = 1;
		move[SE].b = 1;

		move[SW].a = 1;
		move[SW].b = -1;

		move[NW].a = -1;
		move[NW].b = -1;
	}
	return move;
}

路径记录和迷宫地图设置

  • 建立一个 I t e m s Items Items结构,它包括位置坐标 x 和 y x和y xy以及下一次该点的移动方向 d i r dir dir
  • 迷宫地图为二维数组,手动输入,代码如下:
//记录路径
struct Items
{
	int x, y, dir;
};

//设置地图
char** map_set(const int width, const int high)
{

	char** map = new char* [width];
	for (int i = 0; i < width; i++)
	{
		map[i] = new char[high];
	}
	for (int i = 0; i < width; i++)
	{
		for (int j = 0; j < high; j++)
		{
			cin >> map[i][j];
		}
	}
	return map;
}

寻找路径

  • 首先我们要用数据结构来记录路径信息 ( s t a c k < I t e m s > ∗ w a y s ) (stack<Items>*ways) (stack<Items>ways),这里之所以用指针是方便后续传参;
  • 同时我们构建一个全为零的二维数组 ( c h a r ∗ ∗ m a r k ) (char**mark) (charmark)来记录是否已经通过该点,比如通过 x = i , y = j x=i,y=j x=i,y=j的点,那么 m a r k [ i ] [ j ] = 1 mark[i][j]=1 mark[i][j]=1
  • 话不多说,直接上代码:
//寻找路径
stack<Items>* Path(const int width,const int high,char **map,const char can_pass,const int start_x,const int start_y, const char end_signal,const int move_kind)
{
	/*参数说明:
	* width:迷宫的长度
	* high:迷宫的宽度
	* **map:二维迷宫的信息
	* can_pass:*map[]中可通过字符
	* start_x:起点横坐标
	* start_y:起点纵坐标
	* end_signal:终点字符标志
	* move_kind:4方向移动或8方向移动
	*/

	//获取方向表示
	offsets* move;
	move = move_set(move_kind);

	//记录走过点的信息
	stack<Items>*ways=new stack<Items>;

	//记录该点是否走过
	int** mark = new int* [width];
	for (int i = 0; i < width; i++)
	{
		mark[i] = new int[high];
		for (int j = 0; j < high; j++)
		{
			mark[i][j] = 0;
		}
	}

	//获取起始点
	mark[start_x][start_y] = 1;
	Items temp;
	temp.x = start_x;
	temp.y = start_y;
	temp.dir = E;
	ways->push(temp);
	
	//开始寻找路径
	while (!ways->empty())
	{
		temp = ways->top();
		ways->pop();

		int i = temp.x, j = temp.y, d = temp.dir;
		while (d < move_kind)
		{
			int g = i + move[d].a, h = j + move[d].b;
			if ((g >= 0 && h >= 0) && (g < width && h < high))
			{
				if (map[g][h] == end_signal)
				{
					cout << "exist!" << endl;
					// 存储最后一次路径信息
					Items temp1;
					temp1.x = i;
					temp1.y = j;
					temp1.dir = E;
					ways->push(temp1);
					return ways;
				}
				//可以通过,存储该点
				if (map[g][h] == can_pass && mark[g][h]==0)
				{
					mark[g][h] = 1;
					temp.x = i;
					temp.y = j;
					temp.dir = d + 1;
					ways->push(temp);
					i = g;
					j = h;
					d = E;
				}
				else d++;
			}
			else d++;
		}
	}
	cout << "not exist!" << endl;
	return ways;
}

代码总览

#include<iostream>
#include<stack>
using namespace std;

//方向枚举:东、西、南、北、东北、东南、西北、西南
enum directions{E,W,S,N,NE,SE,NW,SW};

//表示方向
struct offsets
{
	int a, b;
};

//构建移动方向move
//设置方向:选择4方向还是8方向
offsets *move_set(int num = 4)
{
 /*方向表示表
  ___________________________
 | q | move[q].a | move[q].b |
 -----------------------------
 | N |    -1     |     0     |
 | NE|    -1     |     1     |
 | E |     0     |     1     |
 | SE|     1     |     1     |
 | S |     1     |     0     |
 | SW|     1     |    -1     |
 | W |     0     |    -1     |
 | NW|    -1     |    -1     |
 -----------------------------
 */ 
	offsets* move = new offsets[num];
	if (num == 4||num==8)
	{

		move[N].a = -1;
		move[N].b = 0;

		move[E].a = 0;
		move[E].b = 1;

		move[S].a = 1;
		move[S].b = 0;

		move[W].a = 0;
		move[W].b = -1;
	}
	
	if (num == 8)
	{
		move[NE].a = -1;
		move[NE].b = 1;

		move[SE].a = 1;
		move[SE].b = 1;

		move[SW].a = 1;
		move[SW].b = -1;

		move[NW].a = -1;
		move[NW].b = -1;
	}
	return move;
}

//记录路径
struct Items
{
	int x, y, dir;
};

//设置地图
char** map_set(const int width, const int high)
{

	char** map = new char* [width];
	for (int i = 0; i < width; i++)
	{
		map[i] = new char[high];
	}
	for (int i = 0; i < width; i++)
	{
		for (int j = 0; j < high; j++)
		{
			cin >> map[i][j];
		}
	}
	return map;
}

//寻找路径
stack<Items>* Path(const int width,const int high,char **map,const char can_pass,const int start_x,const int start_y, const char end_signal,const int move_kind)
{
	/*参数说明:
	* width:迷宫的长度
	* high:迷宫的宽度
	* **map:二维迷宫的信息
	* can_pass:*map[]中可通过字符
	* start_x:起点横坐标
	* start_y:起点纵坐标
	* end_signal:终点字符标志
	* move_kind:4方向移动或8方向移动
	*/

	//获取方向表示
	offsets* move;
	move = move_set(move_kind);

	//记录走过点的信息
	stack<Items>*ways=new stack<Items>;

	//记录该点是否走过
	int** mark = new int* [width];
	for (int i = 0; i < width; i++)
	{
		mark[i] = new int[high];
		for (int j = 0; j < high; j++)
		{
			mark[i][j] = 0;
		}
	}

	//获取起始点
	mark[start_x][start_y] = 1;
	Items temp;
	temp.x = start_x;
	temp.y = start_y;
	temp.dir = E;
	ways->push(temp);
	
	//开始寻找路径
	while (!ways->empty())
	{
		temp = ways->top();
		ways->pop();

		int i = temp.x, j = temp.y, d = temp.dir;
		while (d < move_kind)
		{
			int g = i + move[d].a, h = j + move[d].b;
			if ((g >= 0 && h >= 0) && (g < width && h < high))
			{
				if (map[g][h] == end_signal)
				{
					cout << "exist!" << endl;
					// 存储最后一次路径信息
					Items temp1;
					temp1.x = i;
					temp1.y = j;
					temp1.dir = E;
					ways->push(temp1);
					return ways;
				}
				//可以通过,存储该点
				if (map[g][h] == can_pass && mark[g][h]==0)
				{
					mark[g][h] = 1;
					temp.x = i;
					temp.y = j;
					temp.dir = d + 1;
					ways->push(temp);
					i = g;
					j = h;
					d = E;
				}
				else d++;
			}
			else d++;
		}
	}
	cout << "not exist!" << endl;
	return ways;
}

//打印地图且在地图中显示路径
void Show_path(const int width,const int high,char** map, stack<Items>* ways)
{
	if (ways->empty())return;
	while (!ways->empty())
	{
		int x = ways->top().x, y = ways->top().y;
		map[x][y] = '@';
		ways->pop();
	}
	for (int i = 0; i < width; i++)
	{
		for (int j = 0; j < high; j++)
		{
			cout << map[i][j] << "\t";
		}
		cout << "\n";
	}
}

int main()
{
	/*测试数据:(
	10 10
	#S######.#
	......#..#
	.#.##.##.#
	.#........
	##.##.####
	....#....#
	.#######.#
	....#.....
	.####.###.
	....#...G#
	*/
	int width, high;
	cout << "输入迷宫的长和宽:" << endl;
	cin >> width >> high;

	char** map;
	cout << "输入迷宫信息:" << endl;
	map = map_set(width, high);

	stack<Items>* ways;
	ways = Path(width, high, map, '.', 0, 1, 'G', 4);

	Show_path(width, high, map, ways);

	return 0;
}

上一节:数据结构-栈与队列–队列

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一棵___大树

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

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

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

打赏作者

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

抵扣说明:

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

余额充值