二维迷宫最短路径问题--广度优先--演示程序

#include <stdio.h>
#include <iostream>
#include <vector>
#include <map>
#include <windows.h>
#include <cstdlib>
#include <iostream>
#include <ctime>
#include <tuple>
#include <queue>
#include <list>
enum struct MAZE_DATA_TYPE : uint8_t
{
	WALL = 0,
	ROAD,
	VISITED,
	ANSWER,
	TRY_VISITE
};

typedef struct ShowColorChar
{
	char ch = '\0';
	WORD color = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN;
};
const std::map<MAZE_DATA_TYPE, ShowColorChar> G_STATIC_DATA =
{
	{MAZE_DATA_TYPE::WALL, {'#',FOREGROUND_RED | FOREGROUND_BLUE}},
	{MAZE_DATA_TYPE::ROAD, {'.',FOREGROUND_GREEN}},
	{MAZE_DATA_TYPE::VISITED, {'V', FOREGROUND_BLUE}},
	{MAZE_DATA_TYPE::ANSWER, {'A', FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN}},
	{MAZE_DATA_TYPE::TRY_VISITE, {'T', FOREGROUND_RED}}
};
auto GetTypeChar(MAZE_DATA_TYPE type)
{
	return G_STATIC_DATA.find(type)->second.ch;
}
auto GetTypeColor(MAZE_DATA_TYPE type)
{
	return G_STATIC_DATA.find(type)->second.color;
}
typedef struct point
{
	int x = 0;
	int y = 0;
	MAZE_DATA_TYPE type;
	bool operator < (const point& _point) const {
		return true;
	}
};
typedef struct direct
{
	int x = 0;
	int y = 0;
};
const std::vector<direct> G_DIRECT_LIST =
{
	{1,0},		// 右
	{0,1},		// 下
	{-1,0},		// 左
	{0,-1}		// 上
};
using mapdataType = std::vector<std::vector<point>>;
using wayType = std::vector<point>;
typedef struct mazeMap
{
	int row = 0;
	int colum = 0;
	mapdataType data;
};
typedef struct answerRoad
{
	wayType way;
};

template<typename T>
void EnumratemapData(mazeMap& mazemap, T op);
void ResetMap(mazeMap& mazemap);

void ResetMap(mazeMap& mazemap)
{
	EnumratemapData(mazemap, [](auto& data) {data.type = MAZE_DATA_TYPE::WALL; });
}

void RandomSetRoads(mazeMap& mazemap)
{
	EnumratemapData(mazemap, [](auto& data) {if(std::rand() % 2) data.type = MAZE_DATA_TYPE::ROAD ; });
}
void GenerateMap(mazeMap& mazemap,int row = 10,int colum = 10)
{
	mazemap.colum = colum;
	mazemap.row = row;
	mazemap.data.resize(row);
	for (int i = 0; i < row; ++i)
	{
		mazemap.data[i].resize(colum);
		for (int j = 0; j < colum; ++j)
		{
			mazemap.data[i][j].x = i;
			mazemap.data[i][j].y = j;
		}
	}
	ResetMap(mazemap);

	// 随机的设置一些墙
	RandomSetRoads(mazemap);
}
void gotoxy(int x, int y)
{
	COORD C;
	C.X = x;
	C.Y = y;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), C);
}
void SetStdConsoleTextAttribute(WORD color)
{
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
}
class CCurPoseReset
{
public:
	CCurPoseReset()
	{
		GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &m_preInfo);
	}
	~CCurPoseReset()
	{
		gotoxy(m_preInfo.dwCursorPosition.X, m_preInfo.dwCursorPosition.Y);
	}

private:
	CONSOLE_SCREEN_BUFFER_INFO m_preInfo = {};
};
class AutoChangeConsoleColor
{
public:
	AutoChangeConsoleColor() {
		CONSOLE_SCREEN_BUFFER_INFO info = {};
		GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
		preColor = info.wAttributes;
	}
	~AutoChangeConsoleColor() {
		SetStdConsoleTextAttribute(preColor);
	}
private:
	WORD preColor = 0;
};
class CColorOutput : public CCurPoseReset,public AutoChangeConsoleColor
{
public:
	CColorOutput(int x, int y, char ch, WORD color) {
		gotoxy(x, y);
		SetStdConsoleTextAttribute(color);
		putchar(ch);
	}
};

void ShowPosColorChar(int x, int y, char ch, WORD color)
{
	CColorOutput _obj(x, y, ch, color);
}
void ShowPoint(const point& _point)
{
	ShowPosColorChar(_point.x, _point.y, GetTypeChar(_point.type), GetTypeColor(_point.type));
}
template<typename T>
void EnumratemapData(mazeMap& mazemap,T op)
{
	for (auto& rows : mazemap.data) {
		for (auto& _point : rows) {
			op(_point);
		}
	}
}
void ShowMap(mazeMap& mazemap)
{
	EnumratemapData(mazemap, [](const auto& data) {ShowPoint(data); });
}
auto movePoint(const point& currentPos, const direct& _direct)
{
	auto result = currentPos;
	result.x += _direct.x;
	result.y += _direct.y;
	return result;
}
bool validPoint(const mazeMap& mazemap, const point& pose)
{
	if (pose.x < 0 || pose.y < 0) return false;
	if (pose.x >= mazemap.colum) return false;
	if (pose.y >= mazemap.row) return false;

	return true;
}
bool isEqualPoint(const point& _p1,const point& _p2)
{
	return _p1.x == _p2.x && _p1.y == _p2.y;
}
auto GetMazeDataReference(mazeMap& mazemap, point _point)
{
	return &mazemap.data[_point.x][_point.y].type;
}
auto GetMazeDataType(mazeMap& mazemap, point _point)
{
	return *GetMazeDataReference(mazemap, _point);
}
void SetMazeDataType(mazeMap& mazemap, point _point, MAZE_DATA_TYPE _type)
{
	*GetMazeDataReference(mazemap, _point) = _type;
}
void SetMapDataVisited(mazeMap& mazemap, point _point)
{
	*GetMazeDataReference(mazemap, _point) = MAZE_DATA_TYPE::VISITED;
}

void SetMapDataAnswer(mazeMap& mazemap, point _point)
{
	*GetMazeDataReference(mazemap, _point) = MAZE_DATA_TYPE::ANSWER;
}
void VisitAndShowNewMazeAndSleepForAWhile(mazeMap& mazemap,const point _point)
{
	std::cout << "show road" << std::endl;
	SetMapDataVisited(mazemap, _point);
	ShowMap(mazemap);// 每步改变都输出一下
	Sleep(200);
}
void AnswerAndShowNewMazeAndSleepForAWhile(mazeMap& mazemap, const point _point)
{
	//std::cout << "show answer" << std::endl;
	SetMapDataAnswer(mazemap, _point);
	ShowMap(mazemap);// 每步改变都输出一下
	Sleep(200);
}
void TryVisitAndShowNewMazeForAWhile(mazeMap& mazemap, const point _point)
{
	auto preType = GetMazeDataType(mazemap, _point);
	auto targetPoint = _point;
	targetPoint.type = MAZE_DATA_TYPE::TRY_VISITE;
	for (int i = 0; i < 5; ++i)
	{
		ShowPoint(targetPoint);
		Sleep(100);
		targetPoint.type = preType;

		ShowPoint(targetPoint);
		Sleep(100);
	}
}
typedef struct answerData
{
	point currentPoint;
	direct fromWhere;
};
using answerType = std::list< answerData>;
auto ReverseDirect(direct _direct)
{
	auto result = _direct;
	result.x = -_direct.x;
	result.y = -_direct.y;
	return result;
}
void ShowAnswer(answerType& answer, mazeMap& mazemap, const point& begin, const point& end)
{
	auto _movePoint = end;
	do 
	{
		AnswerAndShowNewMazeAndSleepForAWhile(mazemap, _movePoint);
		if (isEqualPoint(_movePoint, begin)) break;

		_movePoint = movePoint(_movePoint, ReverseDirect(std::find_if(answer.begin(), answer.end(), [&_movePoint](auto data) {return isEqualPoint(data.currentPoint,_movePoint); })->fromWhere));
		
	} while (1);
	
}
bool FindAnswerWay(mazeMap& mazemap,const point& begin,const point& end, answerType& answer)
{
	std::queue<point> visitedList;
	visitedList.push(begin);
	VisitAndShowNewMazeAndSleepForAWhile(mazemap, begin);
	while (visitedList.size())
	{
		auto currentPos = visitedList.front();
		visitedList.pop();

		for (auto& _direct : G_DIRECT_LIST)
		{
			auto nextPoint = movePoint(currentPos, _direct);
			if (validPoint(mazemap, nextPoint)) {
				TryVisitAndShowNewMazeForAWhile(mazemap, nextPoint);
				switch (GetMazeDataType(mazemap, nextPoint))
				{
				case MAZE_DATA_TYPE::WALL:
					break;
				case MAZE_DATA_TYPE::ROAD:
					VisitAndShowNewMazeAndSleepForAWhile(mazemap, nextPoint);
					answer.push_back({ nextPoint, _direct });
					if (isEqualPoint(nextPoint, end)) {
						return true;
					}
					else
					{
						visitedList.push(nextPoint);
					}
					break;
				case MAZE_DATA_TYPE::VISITED:
					break;
				case MAZE_DATA_TYPE::ANSWER:
					break;
				default:
					std::cout << "error type " << std::endl;
					return false;
					break;
				}
			}
		}
	}
	return false;
}
auto ChoosePoint()
{
	point begin;
	point end;

	std::cout << "intput begin(x,y)" << std::endl;
	std::cin >> begin.x >> begin.y;

	std::cout << "input end(x,y)" << std::endl;
	std::cin >> end.x >> end.y;

	return std::tuple<point,point>(begin, end);
}
int main()
{
	std::srand(std::time(nullptr));

	mazeMap mazemap;
	answerRoad road;
	GenerateMap(mazemap);

	ShowMap(mazemap);
	gotoxy(0, mazemap.row);
	auto [begin, end] = ChoosePoint();
	answerType answer;
	if (FindAnswerWay(mazemap, begin, end, answer))
	{
		std::cout << "find answer" << std::endl;
		ShowAnswer(answer, mazemap, begin, end);
	}
	else
	{
		std::cout << "can not find answer" << std::endl;
	}

	//ShowMap(mazemap);
	getchar();
	return 0;
}

在这里插入图片描述

作为参考代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值