寻路:使用队列广度优先找到出口及最优路径

数据结构和C++小白的第一篇文章,记录一下自己学习过程中遇到的问题!...(* ̄0 ̄)ノ


前言

        这几天学了栈和队列,正所谓在实践中检验真理,我们这种小白当然得多敲代码才能成为我们身边的那些大佬,的跟班。

        回到正文,其实是使用队列进行广度优先遍历进行寻路时遇到了一个小问题,就是找到出口后该如何把最优路径和所有走过的路区别出来呢(⊙o⊙)?


一、思路

       队列寻路的思路我的理解就是创建一个队列存放位置(二维地图数组的下标),从入口入队开始,封装一个返回值为布尔型的函数去寻找周围的路。

        函数中当前点出队,然后判断这个点的上下左右四个方向是否有空地,有就入队(这里需要注意数组越界的情况,并且队列和点的位置记得传引用或指针),走到一个点就将其给一个固定的值,表明这个点已经走过了,不再把它当成空地,如果这四个方向中有出口点,那么返回true,否则函数执行完后返回false。

        用一个变量如s去接收这个值。这样我们就可以写一个while循环,条件是!s,即s为true时结束循环,循环体就把此函数赋值给s即可。  

二、最优路径

        所以我们理解了上述步骤后,就进入正题——找到出口后如何显示那条最优路径。

        我们其实可以通过计数来解决这个问题。这个步骤可以放到上面提到的那个函数中实现,不用某个固定的值去表明某个点已经走过。将起始点的值改变一下,让它的值后面不要有出口或墙这些元素,在四个方向中的某个入队时,给一个值比当前点的值多1,直到循环找到出口时,此时的坐标表示应该是出口的上一个点。

        创建一个栈存放位置(二维地图数组的下标),从那个点入栈开始,判断它的上下左右四个方向,找到值比它小一的点,然后将位置改到这个点,直到当前点的位置回到起始点(入口)。这个步骤也需封装成函数放入循环中执行。最后得到的栈存放的就是最优路径了,我们将其渲染出来即可。

三、代码

#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <windows.h>
using namespace std;
/*
利用队列搜索路径	
*/
//色彩函数的声明
void COLOR(const char* s, int color);
//用二维数组创建一个地图
int GameMap[10][10] = {
	{ 1, 10, 1, 1, 1, 1, 1, 1, 1, 1 },
	{ 1, 0, 0, 0, 1, 1, 1, 1, 0, 1 },
	{ 1, 0, 1, 0, 0, 0, 0, 0, 0, 1 },
	{ 1, 0, 0, 1, 0, 1, 0, 1, 1, 1 },
	{ 1, 0, 1, 1, 1, 1, 0, 0, 0, 1 },
	{ 1, 0, 1, 1, 0, 1, 0, 1, 4, 1 },
	{ 1, 0, 0, 0, 0, 1, 0, 1, 0, 1 },
	{ 1, 0, 1, 0, 1, 1, 0, 1, 0, 1 },
	{ 1, 0, 1, 0, 0, 0, 0, 0, 0, 1 },
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
};
//渲染地图
void RenderMap(int GameMap[10][10])
{
	for (int i = 0; i < 10; i++)
	{
		for (int j = 0; j < 10; j++)
		{
			switch (GameMap[i][j])
			{
			case 0:
				cout << "  ";
				break;
			case 1:
				COLOR("■", 4);
				break;
			case 2:
				COLOR("♀",1);
				break;
			case 10:
				cout << "入";
				break;
			case 4:
				cout << "出";
				break;
			default:
				cout << "♀";
				break;
			}

		}
		cout << endl;
	}
}
//位置结构体的定义
struct  Pos
{
	int x;
	int y;
};
//1.显示搜索的整个过程;
bool FindRoad1(int GameMap[10][10], Pos &MyPos, queue<Pos> &s)
{
	MyPos = s.front();
	s.pop();
	if (MyPos.x - 1 >= 0 && MyPos.x - 1 <= 9 && (0 == GameMap[MyPos.x - 1][MyPos.y] || 4 == GameMap[MyPos.x - 1][MyPos.y]))//上
	{
		Pos NewPos = { MyPos.x - 1, MyPos.y };
		s.push(NewPos);
		if (4 == GameMap[MyPos.x - 1][MyPos.y])
			return true;
		GameMap[MyPos.x - 1][MyPos.y] = GameMap[MyPos.x][MyPos.y]+1;
	}
	if (MyPos.x + 1 >= 0 && MyPos.x + 1 <= 9 && (0 == GameMap[MyPos.x + 1][MyPos.y] || 4 == GameMap[MyPos.x + 1][MyPos.y]))//下
	{
		Pos NewPos = { MyPos.x + 1, MyPos.y };
		s.push(NewPos);
		if (4 == GameMap[MyPos.x + 1][MyPos.y])
			return true;
		GameMap[MyPos.x + 1][MyPos.y] = GameMap[MyPos.x][MyPos.y]+1;
	}
	if (MyPos.y - 1 >= 0 && MyPos.y - 1 <= 9 && (0 == GameMap[MyPos.x][MyPos.y - 1] || 4 == GameMap[MyPos.x][MyPos.y - 1]))//左
	{
		Pos NewPos = { MyPos.x, MyPos.y - 1 };
		s.push(NewPos);
		if (4 == GameMap[MyPos.x][MyPos.y - 1])
			return true;
		GameMap[MyPos.x][MyPos.y - 1] = GameMap[MyPos.x][MyPos.y]+1;
	}
	if (MyPos.y + 1 >= 0 && MyPos.y + 1 <= 9 && (0 == GameMap[MyPos.x][MyPos.y + 1] || 4 == GameMap[MyPos.x][MyPos.y + 1]))//右
	{
		Pos NewPos = { MyPos.x, MyPos.y + 1 };
		s.push(NewPos);
		if (4 == GameMap[MyPos.x][MyPos.y + 1])
			return true;
		GameMap[MyPos.x][MyPos.y + 1] = GameMap[MyPos.x][MyPos.y]+1;
	}
	return false;
}
//寻找最优路径
void FindFast(stack<Pos>& s1, Pos& MyPos)
{
	s1.push(MyPos);
	if (MyPos.x - 1 >= 0 && MyPos.x - 1 <= 9 &&
		GameMap[MyPos.x][MyPos.y]-1 == GameMap[MyPos.x - 1][MyPos.y])
		MyPos.x --;
	else if (MyPos.x + 1 >= 0 && MyPos.x + 1 <= 9 &&
		GameMap[MyPos.x][MyPos.y] - 1 == GameMap[MyPos.x + 1][MyPos.y])
		MyPos.x--;
	else if (MyPos.y - 1 >= 0 && MyPos.y - 1 <= 9 &&
		GameMap[MyPos.x][MyPos.y] - 1 == GameMap[MyPos.x][MyPos.y - 1])
		MyPos.y--;
	else if (MyPos.y + 1 >= 0 && MyPos.y + 1 <= 9 &&
		GameMap[MyPos.x][MyPos.y] - 1 == GameMap[MyPos.x][MyPos.y + 1])
		MyPos.y++;
}
int main()
{
	RenderMap(GameMap);
	//创建存放位置的队列
	queue<Pos> s;
	Pos MyPos = { 0, 1 };
	s.push(MyPos);
	bool isfind = false;
	//循环找到出口
	while (!isfind)
	{
		isfind = FindRoad1(GameMap, MyPos, s);
		system("CLS");
		RenderMap(GameMap);
		Sleep(200);
	}
	//创建存放位置的栈
	stack<Pos> s1;
	//循环找最优路径
	while (10 != GameMap[MyPos.x][MyPos.y])
	{
		FindFast(s1, MyPos);
	}
	//渲染出最优路径
	while (!s1.empty())
	{
		GameMap[s1.top().x][s1.top().y] = 2;
		s1.pop();
		system("CLS");
		RenderMap(GameMap);
		Sleep(200);
	}
	cout << "蓝色路径即为为最短路径!" << endl;
	return 0;
}

//色彩函数
void COLOR(const char* s, int color)
{
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | color);
	printf(s);
	SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | 7);
}

四、结果图

 

总结       

        第一次写文章还有很多不足,表达描述肯定也有很多不清楚的地方,以后我会多多锻炼,如果有什么错误或者问题还请大佬们指出哈!

  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值