完成时间:2018-11-12
编译器:Visual Studio 2017 或 Dev-cpp v5.11
运行环境:Windows系统
主要是锻炼一下自己写程序的能力,再配合老师在课堂上讲解,顺便装个13(逃) ,于是制作出了这个适合演示的程序,欢迎各位提建议
PS:我真的懒 ,就不写太多注释了……
PPS:迷宫是通过递归算法生成的,思路如下图(这张图是别人的博客上截下来的,非原创)所示,只不过我最后还随机挖掉了16%的墙,以便于产生不止一条通路…算法原链接:https://blog.csdn.net/juzihongle1/article/details/73135920/
PPPS:有想法欢迎讨论,我的QQ:1783952099,目前南航本科大二
代码如下:
#include
#include
#include
#include
#include
using namespace std;
#pragma warning(disable:4996) //这一行是为了能在 Visual Studio 2017内使用getch()函数
#define WALLSTR "█"
#define UPSTR "∧"
#define DOWNSTR "∨"
#define LEFTSTR "<"
#define RIGHTSTR ">"
//以上特殊符号是在手心输入法的特殊符号表里面找到的,因为不会写真的图形界面……(菜哭)
#define BLANKSTR "·"//就是个全角的点
#define DEADSTR "X"//全角的大写的英文字母x
#define DEAD -1
#define DELAY 50
#define UP 10
#define DOWN 20
#define LEFT 30
#define RIGHT 40
#define ORIGINAL 0
#define WALL 1
#define ROAD 2
//以上用来标记地图
struct POSITION
{
int x, y;
};
struct QUEUE
{
int x, y;
int PreSub;
};
HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);
int MaxLine = 38, MaxColume = 38;//不建议修改这个
int map[50][50] = { 0 };
POSITION Stack[2500] = { {0,0} };
QUEUE Queue[2500] = { {0,0,0} };
int head = -1, tail = -1, top = -1;
void SetPosition(int line, int col)//更改光标的位置
{
static COORD coord;
coord.X = col * 2;
coord.Y = line;
SetConsoleCursorPosition(hout, coord);
}
void MakeMap()//制作地图
{
int i, j, top = 0, ttt;
POSITION s[2500] = { {0,0} };
POSITION sss[6] = { {0,0} };
bool vis[50][50] = { false };
memset(map, ORIGINAL, sizeof(map));
for (i = 0; i <= MaxLine + 3; i++)
{
vis[i][0] = vis[i][MaxColume + 1] = vis[i][1] = vis[i][MaxColume + 2] = true;
map[i][0] = map[i][MaxColume + 1] = map[i][1] = map[i][MaxColume + 2] = WALL;
}
for (i = 0; i <= MaxColume + 3; i++)
{
vis[0][i] = vis[MaxLine + 1][i] = vis[1][i] = vis[MaxLine + 2][i] = true;
map[0][i] = map[MaxLine + 1][i] = map[1][i] = map[MaxLine + 2][i] = WALL;
}
map[2][1] = WALL;
map[MaxLine][MaxColume + 1] = ROAD;
s[0].x = s[0].y = 2;
while (top >= 0)
{
vis[s[top].x][s[top].y] = true;
map[s[top].x][s[top].y] = ROAD;
for (i = s[top].x - 1; i <= s[top].x + 1; i++)
for (j = s[top].y - 1; j <= s[top].y + 1; j++)
if (map[i][j] == ORIGINAL)
{
vis[i][j] = true;
map[i][j] = WALL;
}
i = s[top].x;
j = s[top].y;
if (!(vis[i - 2][j] && vis[i + 2][j] && vis[i][j - 2] && vis[i][j + 2]))
{
ttt = -1;
if (!vis[i - 2][j])
{
ttt++;
sss[ttt].x = i - 2;
sss[ttt].y = j;
}
if (!vis[i + 2][j])
{
ttt++;
sss[ttt].x = i + 2;
sss[ttt].y = j;
}
if (!vis[i][j - 2])
{
ttt++;
sss[ttt].x = i;
sss[ttt].y = j - 2;
}
if (!vis[i][j + 2])
{
ttt++;
sss[ttt].x = i;
sss[ttt].y = j + 2;
}
ttt = rand() % (ttt + 1);
top++;
s[top].x = sss[ttt].x;
s[top].y = sss[ttt].y;
map[(i + s[top].x) / 2][(j + s[top].y) / 2] = ROAD;
}
else
{
top--;
}
}
//下面开始随机……挖墙
for (i = 2; i <= MaxLine; i++)
for (j = 2; j <= MaxColume; j++)
if (map[i][j] == WALL)
if (rand() % 100 < 16)
map[i][j] = ROAD;
}
void PrintMap()//输出迷宫
{
SetConsoleTextAttribute(hout, 8);
SetPosition(0, 0);
int i, j;
for (i = 0; i <= MaxLine + 2; i++)
{
for (j = 0; j <= MaxColume + 2; j++)
{
cout << (map[i][j] == WALL ? WALLSTR : BLANKSTR);
}
if (i < MaxLine + 2) cout << endl;
}
SetConsoleTextAttribute(hout, 14);
SetPosition(2, 1);
cout << "S";
SetPosition(MaxLine, MaxColume + 1);
cout << "E";
SetConsoleTextAttribute(hout, 7);
}
void ChangeConsoleSize(int line, int col)//改变控制台窗口大小
{
char LINE[10], COL[10], FINAL[50] = { '\0' };
sprintf(LINE, "%d", line);
sprintf(COL, "%d", col * 2);
strcpy(FINAL, "mode con cols=");
strcat(FINAL, COL);
strcat(FINAL, " lines=");
strcat(FINAL, LINE);
system(FINAL);
//函数最后的结果就相当于cmd命令:mode con lines=123 cols=123
}
void ClearMap()//清除所有搜索时留下的标记,只留下墙和路
{
int i, j;
for (i = 0; i <= MaxLine + 2; i++)
for (j = 0; j <= MaxColume + 2; j++)
if (map[i][j] != WALL)
map[i][j] = ROAD;
map[2][1] = WALL;
map[MaxLine][MaxColume + 1] = ROAD;
}
void ChangeCursor(int a) // 设置光标是否可见 a=0不可见,a=1可见
{
CONSOLE_CURSOR_INFO cursor_info = { 1, a };
SetConsoleCursorInfo(hout, &cursor_info);
}
void DepthFirstSearch(int x = 2, int y = 2, int dir = 0)
{
memset(Stack, 0, sizeof(Stack));
top = -1;
while (top > -2 && (x != MaxLine || y != MaxColume + 1))
{
top++;
Stack[top].x = x;
Stack[top].y = y;
SetConsoleTextAttribute(hout, 14);
SetPosition(x, y);
cout << RIGHTSTR;
Sleep(DELAY);
if (map[x][y + 1] == ROAD)
{
map[x][y] = RIGHT;
y++;
}
else
{
SetPosition(x, y);
cout << DOWNSTR;
Sleep(DELAY);
if (map[x + 1][y] == ROAD)
{
map[x][y] = DOWN;
x++;
}
else
{
SetPosition(x, y);
cout << LEFTSTR;
Sleep(DELAY);
if (map[x][y - 1] == ROAD)
{
map[x][y] = LEFT;
y--;
}
else
{
SetPosition(x, y);
cout << UPSTR;
Sleep(DELAY);
if (map[x - 1][y] == ROAD)
{
map[x][y] = UP;
x--;
}
else
{
map[x][y] = DEAD;
SetPosition(x, y);
cout << DEADSTR;
Sleep(DELAY / 2);
top -= 2;
x = Stack[top + 1].x;
y = Stack[top + 1].y;
}
}
}
}
if (kbhit())
if (getch() == '3')
return;//万一不想看了,直接停掉
}
ClearMap();
PrintMap();
SetConsoleTextAttribute(hout, 28);
while (top >= 0)
{
SetPosition(Stack[top].x, Stack[top].y);
cout << BLANKSTR;
top--;
}
SetConsoleTextAttribute(hout, 7);
}
void WidthFirstSearch()
{
int x, y, PreSub;
tail = head = 0;
memset(Queue, 0, sizeof(Queue));
Queue[head].PreSub = -1;
Queue[head].x = 2;
Queue[head].y = 1;
SetConsoleTextAttribute(hout, 14);
while (tail <= head)
{
x = Queue[tail].x;
y = Queue[tail].y;
PreSub = Queue[tail].PreSub;
if (map[x - 1][y] == ROAD)
{
map[x - 1][y] = UP;
SetPosition(x - 1, y);
cout << UPSTR;
head++;
Queue[head].x = x - 1;
Queue[head].y = y;
Queue[head].PreSub = tail;
if (Queue[head].x == MaxLine && Queue[head].y == MaxColume + 1) break;
}
if (map[x + 1][y] == ROAD)
{
SetPosition(x + 1, y);
cout << DOWNSTR;
map[x + 1][y] = DOWN;
head++;
Queue[head].x = x + 1;
Queue[head].y = y;
Queue[head].PreSub = tail;
if (Queue[head].x == MaxLine && Queue[head].y == MaxColume + 1) break;
}
if (map[x][y + 1] == ROAD)
{
SetPosition(x, y + 1);
cout << RIGHTSTR;
map[x][y + 1] = RIGHT;
head++;
Queue[head].x = x;
Queue[head].y = y + 1;
Queue[head].PreSub = tail;
if (Queue[head].x == MaxLine && Queue[head].y == MaxColume + 1) break;
}
if (map[x][y - 1] == ROAD)
{
SetPosition(x, y - 1);
cout << LEFTSTR;
map[x][y - 1] = LEFT;
head++;
Queue[head].x = x;
Queue[head].y = y - 1;
Queue[head].PreSub = tail;
if (Queue[head].x == MaxLine && Queue[head].y == MaxColume + 1) break;
}
Sleep(DELAY / 2);
tail++;
if (kbhit())
if (getch() == '3')
return;//万一不想看了,直接停掉
}
ClearMap();
PrintMap();
tail = Queue[head].PreSub;
SetConsoleTextAttribute(hout, 28);
if (Queue[head].x == MaxLine && Queue[head].y == MaxColume + 1)
while (tail != -1)
{
SetPosition(Queue[tail].x, Queue[tail].y);
cout << BLANKSTR;
tail = Queue[tail].PreSub;
}
SetConsoleTextAttribute(hout, 14);
SetPosition(MaxLine, MaxColume + 1);
cout << "E";
SetPosition(2, 1);
cout << "S";
SetConsoleTextAttribute(hout, 7);
}
void PrintMenu()
{
SetConsoleTextAttribute(hout, 14);
SetPosition(2, MaxColume + 5);
cout << "按 1 进行深搜演示";
SetPosition(4, MaxColume + 5);
cout << "按 2 进行广搜演示";
SetPosition(6, MaxColume + 5);
cout << "按 3 去除所有路径";
SetPosition(8, MaxColume + 5);
cout << "按 4 重新生成迷宫";
SetPosition(10, MaxColume + 5);
cout << "按 5 开始编辑迷宫";
SetPosition(12, MaxColume + 4);
cout << "=====================";
SetPosition(14, MaxColume + 5);
cout << "在进行演示时按3";
SetPosition(15, MaxColume + 5);
cout << "可以立刻终止演示";
SetPosition(17, MaxColume + 4);
cout << "=====================";
SetPosition(19, MaxColume + 5);
cout << "编辑迷宫操作方法:";
SetPosition(21, MaxColume + 5);
cout << "·按方向键移动所选方块";
SetPosition(22, MaxColume + 5);
cout << " 所选方块以红色标记";
SetPosition(23, MaxColume + 5);
cout << "·按空格键切换路或墙";
SetPosition(24, MaxColume + 5);
cout << "·按回车键退出编辑";
SetPosition(26, MaxColume + 4);
cout << "=====================";
SetPosition(28, MaxColume + 5);
cout << "图标解释:";
SetPosition(30, MaxColume + 5);
cout << "S:起点";
SetPosition(31, MaxColume + 5);
cout << "E:终点";
SetPosition(32, MaxColume + 5);
cout << BLANKSTR << ":可行走的路";
SetPosition(33, MaxColume + 5);
cout << WALLSTR << ":墙壁";
SetPosition(34, MaxColume + 5);
cout << RIGHTSTR << ":向右行走";
SetPosition(35, MaxColume + 5);
cout << DOWNSTR << ":向下行走";
SetPosition(36, MaxColume + 5);
cout << LEFTSTR << ":向左行走";
SetPosition(37, MaxColume + 5);
cout << UPSTR << ":向上行走";
SetConsoleTextAttribute(hout, 7);
}
void EditMap()
{
int x = 19, y = 19;
bool KeepWhile = true;
SetPosition(x, y);
SetConsoleTextAttribute(hout, 4);
cout << (map[x][y] == WALL ? WALLSTR : BLANKSTR);
while (KeepWhile)
{
switch (getch())
{
case 224: //0xE0 方向键
SetPosition(x, y);
SetConsoleTextAttribute(hout, 8);
cout << (map[x][y] == WALL ? WALLSTR : BLANKSTR);
switch (getch())
{
case 0x48: //↑
if (x > 2) x--;
break;
case 0x50: //↓
if (x < MaxLine) x++;
break;
case 0x4b: //←
if (y > 2) y--;
break;
case 0x4d: //→
if (y < MaxColume) y++;
break;
}
SetPosition(x, y);
SetConsoleTextAttribute(hout, 4);
cout << (map[x][y] == WALL ? WALLSTR : BLANKSTR);
break;
case ' ':
if (map[x][y] == WALL)
map[x][y] = ROAD;
else
map[x][y] = WALL;
SetPosition(x, y);
cout << (map[x][y] == WALL ? WALLSTR : BLANKSTR);
break;
case 13: //回车键
SetPosition(x, y);
SetConsoleTextAttribute(hout, 8);
cout << (map[x][y] == WALL ? WALLSTR : BLANKSTR);
KeepWhile = false;
break;
}
}
}
int main()
{
int i, j;
ChangeConsoleSize(MaxLine + 3, MaxColume + 17);
ChangeCursor(0);
srand(time(0));
MakeMap();
PrintMap();
PrintMenu();
while (1)
{
switch (getch())
{
case '1':
ClearMap();
PrintMap();
DepthFirstSearch();
fflush(stdin);
break;
case '2':
ClearMap();
PrintMap();
WidthFirstSearch();
fflush(stdin);
break;
case '3':
ClearMap();
PrintMap();
break;
case '4':
MakeMap();
PrintMap();
break;
case '5':
EditMap();
break;
}
}
return 0;
}
End Of File