#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;
}
作为参考代码