C++进行迷宫问题求解

一. 迷宫问题的描述

有一张地图,0表示没有障碍物,1表示有障碍物,给你一幅地图、一个起始位置和一个目标位置,请判断是否能够从起始位置出发到达目标位置,可以的话将走过的路径用8进行标记

二. 迷宫问题求解

1.使用队列进行广度优先搜索

查找路径思路:

  1. 将起点位置存入队列中;
  2. 每次访问队头元素,让队头元素出队,标记队头元素已经访问过,并在地图中将队头位置标记为8;如果队头元素就是目标位置,查找结束返回;如果不是,同时进行上下左右四个方向的移动,如果移动到的新位置是可通的并且没有被访问,将这个新位置入队;
  3. 重复上一步直到队列为空,如果队列为空,说明到达不了目标位置;
C++代码实现
#include <iostream>
#include <vector>
#include <queue>

using namespace std;

//位置
struct PosType
{
	int _x, _y;

	PosType()
		:_x(0)
		,_y(0)
	{}

	PosType(int x, int y)
		:_x(x)
		, _y(y)
	{}
};

//判断两个位置是否相同,不能加const修饰,此处没有this指针
bool operator==(const PosType& pos1, const PosType& pos2)	//const
{
	return pos1._x == pos2._x && pos1._y == pos2._y;
}

//判断两个位置是否不同,不能加const修饰,此处没有this指针
bool operator!=(const PosType& pos1, const PosType& pos2)	//const
{
	return pos1._x != pos2._x || pos1._y != pos2._y;
}

//迷宫输入
void InitMaze(vector<vector<int>>& map)
{
	cout << "迷宫地图初始化开始,0表示没有障碍物,1表示有障碍物" << endl;
	int row = map.size(), col = map[0].size();
	for (int i = 0; i < row; ++i)
	{
		for (int j = 0; j < col; ++j)
		{
			cin >> map[i][j];
		}
	}
	cout << "初始化完毕!" << endl;
}

//打印地图
void PrintMap(const vector<vector<int>>& map)
{
	int row = map.size(), col = map[0].size();
	for (int i = 0; i < row; ++i)
	{
		for (int j = 0; j < col; ++j)
		{
			cout << map[i][j] << "\t";
		}
		cout << endl;
	}
	cout << endl;
}

//判断是否有从beginPos到endPos的路径,使用队列进行广度优先搜索
bool IsHasPath(vector<vector<int>>& map, PosType beginPos, PosType endPos)
{
	int rows = map.size(), cols = map[0].size();	//行数和列数

	//1.检查位置是否有效
	if (beginPos._x < 0 || beginPos._x >= rows
		|| beginPos._y < 0 || beginPos._y >= cols
		|| endPos._x < 0 || endPos._x >= rows
		|| endPos._y < 0 || endPos._y >= cols
		|| map[beginPos._x][beginPos._y] == 1 
		|| map[endPos._x][endPos._y] == 1)
	{
		return false;
	}

	int nextStep[4][2] = { { 0, 1 }, { 0, -1 }, { 1, 0 }, { -1, 0 } };	//四个移动方向
	vector<vector<bool>> visited(rows, vector<bool>(cols, false));		//标记位置是否已经访问过
	
	queue<PosType> q;
	q.push(beginPos);

	//进行广度优先搜索
	while (!q.empty())
	{
		PosType front = q.front();
		q.pop();
		visited[front._x][front._y] = true;
		map[front._x][front._y] = 8;
		
		if (front == endPos)
		{
			return true;
		}

		for (int i = 0; i < 4; ++i)
		{
			int curX = front._x + nextStep[i][0];
			int curY = front._y + nextStep[i][1];
			if (curX < 0 || curX >= rows || curY < 0 || curY >= cols)
			{
				continue;
			}
			if (!visited[curX][curY] && map[curX][curY] == 0)
			{
				q.push(PosType(curX, curY));
			}
		}
	}
	//遍历结束,没有找到目标位置
	return false;
}


//开始游戏
void GameStart(vector<vector<int>>& map)
{
	int row = map.size(), col = map[0].size();

	PosType beginPos, endPos;		//起始位置,目标位置
	cout << "请输入起始位置下标: ";
	cin >> beginPos._x >> beginPos._y;
	cout << "请输入目标位置下标: ";
	cin >> endPos._x >> endPos._y;

	//判断是否可以到达目标位置
	bool ret = IsHasPath(map, beginPos, endPos);
	if (ret)
	{
		//可以到达目标位置,打印路径
		cout << "可以到达目标位置,路径如下,走过的位置用8表示" << endl;
		PrintMap(map);
	}
	else
	{
		//不能到达目标位置
		cout << "这是一个无法到达的位置" << endl;
	}
}

int main()
{
	int row, col;
	cout << "请输入迷宫的行数和列数: ";
	cin >> row >> col;

	vector<vector<int>> matrix(row, vector<int>(col));

	cout << "请初始化迷宫" << endl;
	InitMaze(matrix);

	//打印迷宫
	PrintMap(matrix);

	//开始游戏
	GameStart(matrix);

	return 0;
}

2. 使用栈进行深度优先搜索

查找思路:

  1. 将起始位置入栈;
  2. 拿到栈顶元素,判断栈顶元素是否已经访问过:
    如果是让栈顶元素出栈,
    如果不是在栈顶元素对应位置的上下左右四个方向进行查找是否有没有被访问过的并且可行的位置,如果有将其入栈;
  3. 重复上一步,直到栈为空或者栈顶元素就是目标位置;
    如果栈顶元素就是目标位置,返回查找成功;
    如果栈为空,说明没有可行的路径,查找失败;
C++代码实现
#include <iostream>
#include <vector>
#include <stack>

using namespace std;

//位置
struct PosType
{
	int _x, _y;

	PosType()
		:_x(0)
		,_y(0)
	{}

	PosType(int x, int y)
		:_x(x)
		, _y(y)
	{}
};

//判断两个位置是否相同,不能加const修饰,此处没有this指针
bool operator==(const PosType& pos1, const PosType& pos2)	//const
{
	return pos1._x == pos2._x && pos1._y == pos2._y;
}

//判断两个位置是否不同,不能加const修饰,此处没有this指针
bool operator!=(const PosType& pos1, const PosType& pos2)	//const
{
	return pos1._x != pos2._x || pos1._y != pos2._y;
}

//迷宫输入
void InitMaze(vector<vector<int>>& map)
{
	cout << "迷宫地图初始化开始,0表示没有障碍物,1表示有障碍物" << endl;
	int row = map.size(), col = map[0].size();
	for (int i = 0; i < row; ++i)
	{
		for (int j = 0; j < col; ++j)
		{
			cin >> map[i][j];
		}
	}
	cout << "初始化完毕!" << endl;
}

//打印地图
void PrintMap(const vector<vector<int>>& map)
{
	int row = map.size(), col = map[0].size();
	for (int i = 0; i < row; ++i)
	{
		for (int j = 0; j < col; ++j)
		{
			cout << map[i][j] << "\t";
		}
		cout << endl;
	}
	cout << endl;
}

//判断是否有从beginPos到endPos的路径,使用栈进行深度优先搜索
bool IsHasPath(vector<vector<int>>& map, PosType beginPos, PosType endPos)
{
	int rows = map.size(), cols = map[0].size();

	//判断位置是否有效
	if (beginPos._x < 0 || beginPos._x >= rows
		|| beginPos._y < 0 || beginPos._y >= cols
		|| endPos._x < 0 || endPos._x >= rows
		|| endPos._y < 0 || endPos._y >= cols
		|| map[beginPos._x][beginPos._y] == 1 || map[endPos._x][endPos._y] == 1)
	{
		return false;
	}

	int nextStep[4][2] = { { 0, 1 }, { 0, -1 }, { -1, 0 }, { 1, 0 } };		//四个移动方向
	vector<vector<bool>> visited(rows, vector<bool>(cols, false));	//标记数组
	stack<PosType> st;
	st.push(beginPos);

	while (!st.empty() && st.top() != endPos)
	{
		PosType top = st.top();
		//栈顶元素如果已经访问过,就让栈顶元素出栈
		if (visited[top._x][top._y])
		{
			st.pop();
		}

		visited[top._x][top._y] = true;
		map[top._x][top._y] = 8;

		//在上下左右四个方向没有访问过的,可以通过的位置
		for (int i = 0; i < 4; ++i)
		{
			int curX = top._x + nextStep[i][0];
			int curY = top._y + nextStep[i][1];
			if (curX < 0 || curX >= rows || curY < 0 || curY >= cols)
			{
				continue;
			}

			//新位置没有被访问过,而且是可通的,将其入栈
			if (!visited[curX][curY] && map[curX][curY] == 0)
			{
				st.push(PosType(curX, curY));
			}
		}
	}

	//栈顶元素就是目标位置,返回查找成功
	if (!st.empty() && st.top() == endPos)
	{
		map[st.top()._x][st.top()._y] = 8;
		return true;
	}
	//栈顶元素不是目标位置,返回查找失败
	else
	{
		return false;
	}
}

//开始游戏
void GameStart(vector<vector<int>>& map)
{
	int row = map.size(), col = map[0].size();

	PosType beginPos, endPos;		//起始位置,目标位置
	cout << "请输入起始位置下标: ";
	cin >> beginPos._x >> beginPos._y;
	cout << "请输入目标位置下标: ";
	cin >> endPos._x >> endPos._y;

	//判断是否可以到达目标位置
	bool ret = IsHasPath(map, beginPos, endPos);
	if (ret)
	{
		//可以到达目标位置,打印路径
		cout << "可以到达目标位置,路径如下,走过的位置用8表示" << endl;
		PrintMap(map);
	}
	else
	{
		//不能到达目标位置
		cout << "这是一个无法到达的位置" << endl;
	}
}

int main()
{
	int row, col;
	cout << "请输入迷宫的行数和列数: ";
	cin >> row >> col;

	vector<vector<int>> matrix(row, vector<int>(col));

	cout << "请初始化迷宫" << endl;
	InitMaze(matrix);

	//打印迷宫
	PrintMap(matrix);

	//开始游戏
	GameStart(matrix);

	return 0;
}

3.代码运行结果

第1组测试数据:
在这里插入图片描述
第2组测试数据:
在这里插入图片描述
第3组测试数据
在这里插入图片描述

三.迷宫问题小实验总结

这个问题最初我知道应该使用深度优先搜索实现查找,但是不知道用栈如何实现,在思路不清晰的时候就开始写代码,浪费了一个下午的时间。
用递归实现深度优先搜索我是熟悉的,但是用栈来模拟递归,我就有些懵,主要是对数据结构的使用不够灵活。
在使用队列进行广度优先搜索求解问题成功之后,我得到了启发:用栈进行深度优先搜索的时候,要有一个合适的结束条件来模拟递归出口,于是想到了栈不为空并且栈顶元素不等于目标位置的循环结束条件,在循环结束之后,进行更进一步地判断,就可以使用栈求解迷宫问题

  • 27
    点赞
  • 256
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
根提供的引用内容,程序中定义了一个名为boos的类,其中包括了栈的基本方法和走迷宫的方法。栈的基本方法包括InitStack(创建栈)、StackEmpty(判断是否空栈)、GetTop(获得栈顶)、Push(入栈)、Pop(出栈)以及free_Stack(释放栈空间)。走迷宫的方法是利用顺序栈求解迷宫中从入口到出口的一条路径,并输出结果。 迷宫的表示使用了一个二维数组maze,其中1表示路不通,0表示可以通过。具体的迷宫规模和初态可以自行定义。通过调用boos类的findMaze方法,可以找到迷宫中从入口到出口的一条路径。 以下是一个示例的C++代码,演示了如何利用栈求解迷宫问题: ```cpp #include <iostream> #include <cstdlib> #define STACK_INIT_SIZE 100 #define STACKINCREMENT 10 typedef struct { int x; // 坐标 int y; // 坐标 int di; // 方向 } position; typedef struct { position *base; position *top; int stacksize; } Stack; class boos { private: Stack sq_stack; public: void InitStack() { // 创建栈 sq_stack.base = new position[STACK_INIT_SIZE]; sq_stack.top = sq_stack.base; sq_stack.stacksize = STACK_INIT_SIZE; } bool StackEmpty() { // 判断是否空栈 return sq_stack.top == sq_stack.base; } bool GetTop(position &temp) { // 获得栈顶 if (sq_stack.top == sq_stack.base) { return false; } temp = *(sq_stack.top - 1); return true; } bool Push(position &temp) { // 入栈 if (sq_stack.top - sq_stack.base >= sq_stack.stacksize) { sq_stack.base = (position *)realloc(sq_stack.base, (sq_stack.stacksize + STACKINCREMENT) * sizeof(position)); if (!sq_stack.base) { return false; } sq_stack.top = sq_stack.base + sq_stack.stacksize; sq_stack.stacksize += STACKINCREMENT; } *sq_stack.top++ = temp; return true; } bool Pop(position &temp) { // 出栈 if (sq_stack.top == sq_stack.base) { return false; } temp = *--sq_stack.top; return true; } void free_Stack() { // 释放栈空间 delete[] sq_stack.base; } bool findMaze(int start_x, int start_y, int end_x, int end_y) { // 迷宫的入口和出口坐标 position curpos; curpos.x = start_x; curpos.y = start_y; curpos.di = -1; Push(curpos); while (!StackEmpty()) { GetTop(curpos); if (curpos.x == end_x && curpos.y == end_y) { while (!StackEmpty()) { Pop(curpos); std::cout << "(" << curpos.x << "," << curpos.y << ") "; } return true; } int i = curpos.x; int j = curpos.y; int di = curpos.di + 1; while (di < 4) { switch (di) { case 0: // 向右 i = curpos.x; j = curpos.y + 1; break; case 1: // 向下 i = curpos.x + 1; j = curpos.y; break; case 2: // 向左 i = curpos.x; j = curpos.y - 1; break; case 3: // 向上 i = curpos.x - 1; j = curpos.y; break; } if (Maze[i][j] == 0) { Maze[i][j] = -1; position nextpos; nextpos.x = i; nextpos.y = j; nextpos.di = 0; Push(nextpos); break; } else { di++; } } if (di == 4) { Maze[curpos.x][curpos.y] = -1; Pop(curpos); } } return false; } }; int main() { int start_x = 1; int start_y = 1; int end_x = 8; int end_y = 8; boos L1; L1.InitStack(); L1.findMaze(start_x, start_y, end_x, end_y); L1.free_Stack(); return 0; } ``` 以上代码实现了利用栈求解迷宫问题。在示例中,迷宫的入口坐标为(1, 1),出口坐标为(8, 8)。程序通过调用boos类的findMaze方法,找到了从入口到出口的一条路径,并将路径输出到控制台。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值