C++ solves the maze problem

1. Description of the maze problem

There is a map, 0 means there is no obstacle, 1 means there is an obstacle, give you a map, a starting position and a target position, please judge whether you can reach the target position from the starting position, if possible, pass through Paths are marked with 8

2. Maze problem solving

1. Breadth-first search using queues

Find the path idea:

  1. Store the starting position in the queue;
  2. Every time you visit the head element of the team, let the head element out of the queue, mark the head element has been visited, and mark the position of the head of the team as 8 in the map; if the head element is the target position, return after the search; if not, at the same time Move in the four directions of up, down, left, and right. If the new location you move to is accessible and has not been visited, put this new location into the queue;
  3. Repeat the previous step until the queue is empty, if the queue is empty, it means that the target position cannot be reached;

C++ code implementation

#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. Depth-first search using a stack

Find ideas:

  1. Push the starting position onto the stack;
  2. Get the top element of the stack and judge whether the top element has been visited:
    if it is to let the top element out of the stack,
    if it is not in the four directions of the top, bottom, left, and right directions of the corresponding position of the top element, check whether it has been visited and is feasible position, if there is one, put it on the stack;
  3. Repeat the previous step until the stack is empty or the top element of the stack is the target position;
    if the top element of the stack is the target position, the return search is successful;
    if the stack is empty, it means that there is no feasible path, and the search fails;

C++ code implementation

#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. Code running results

The first set of test data:
insert image description here
the second set of test data:
insert image description here
the third set of test data
insert image description here

3. Summary of the labyrinth problem experiment

At the beginning of this problem, I knew that depth-first search should be used to realize the search, but I didn't know how to use the stack to realize it. I started writing code when the idea was not clear, and wasted an afternoon.
I am familiar with implementing depth-first search with recursion, but I am a little confused about using stack to simulate recursion, mainly because the use of data structures is not flexible enough.
After using the queue for breadth-first search to solve the problem successfully, I was inspired: when using the stack for depth-first search, there must be a suitable end condition to simulate the recursive exit, so I thought that the stack is not empty and the top element of the stack is not Equal to the loop end condition of the target position, after the loop ends, make further judgments, you can use the stack to solve the maze problem

Guess you like

Origin blog.csdn.net/m0_51765966/article/details/121423044