maze/maze.cpp
2022-07-15 23:28:13 +08:00

476 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdio.h> //getchar()
#include <termios.h> //终端设置
#include <unistd.h> //延时函数
#include <cstdlib> //标准库
#include <ctime> //时间函数
#include <iostream> //输入输出流
using namespace std; //命名空间
#define MAX_X 20
#define MAX_Y 30
bool flag = false;
bool slow = false;
bool autogame = true;
int maze[MAX_X][MAX_Y]; //迷宫地图
class stack_of_maze {
private:
//记录迷宫坐标
struct node {
int x;
int y;
char direction; //上一步路径(如何来的)
node* next;
};
node* head;
public:
stack_of_maze() {
//初始化
head = NULL;
}
~stack_of_maze() {
node* p = head;
//逐个删除
while (head != NULL) {
head = head->next;
delete p;
p = head;
}
}
void push(int xx, int yy, char ddirection) {
//定义一个新节点
node* new_node = new node;
//赋值
if (new_node != NULL) {
new_node->x = xx;
new_node->y = yy;
new_node->direction = ddirection;
new_node->next = NULL;
//判断栈是否为空,如果为空则直接把新节点赋值给栈,否则添加到栈顶
if (head == NULL)
head = new_node;
else {
new_node->next = head;
head = new_node;
}
} else
cout << "内存分配失败" << endl;
}
node* pop(int& xx, int& yy) {
if (head != NULL) {
node* p = head;
head = head->next;
xx = p->x;
yy = p->y;
delete p;
}
return head;
}
void print() {
if (head != NULL) {
node* p = head;
while (p != NULL) {
cout << " " << p->x << " " << p->y << " " << p->direction << endl;
p = p->next;
}
} else
cout << "栈为空,打印失败" << endl;
}
};
void createMaze() {
int maxway = MAX_X * MAX_Y; //最大通路
int x, y;
//先填充迷宫
for (x = 0; x < MAX_X; x++)
for (y = 0; y < MAX_Y; y++) maze[x][y] = 1;
//随机函数种子,以时间为参数
srand((unsigned)time(NULL));
//随机构建迷宫通路
for (int i = 0; i < maxway; i++) {
x = rand() % (MAX_X - 2) + 1;
y = rand() % (MAX_Y - 2) + 1;
maze[x][y] = 0;
}
maze[1][1] = 0; //入口
maze[MAX_X - 2][MAX_Y - 2] = 0; //出口
maze[0][1] = 3;
maze[MAX_X - 1][MAX_Y - 2] = 0;
}
void printMaze() {
int x, y;
//清屏如果是windows环境使用system("cls")
system("clear");
//打印地图
for (x = 0; x < MAX_X; x++) {
for (y = 0; y < MAX_Y; y++) {
if (maze[x][y] == 0) {
cout << " ";
continue;
} //通路
if (maze[x][y] == 1) {
cout << "";
continue;
} //墙
if (maze[x][y] == 2) {
cout << "× ";
continue;
} //死胡同
if (maze[x][y] == 3) {
cout << "";
continue;
} //向下走
if (maze[x][y] == 4) {
cout << "";
continue;
}
if (maze[x][y] == 5) {
cout << "";
continue;
}
if (maze[x][y] == 6) {
cout << "";
continue;
}
if (maze[x][y] == 7) {
cout << "";
continue;
} //当前站立位置
}
cout << endl;
}
//是否慢速游戏
if (slow) {
sleep(1); //延时函数
}
}
void check(stack_of_maze& s) {
//备份地图
int temp[MAX_X][MAX_Y];
for (int x = 0; x < MAX_X; x++)
for (int y = 0; y < MAX_Y; y++) temp[x][y] = maze[x][y];
int x = 1, y = 1; //出发点
while (1) {
temp[x][y] = 2;
//向下
if (temp[x + 1][y] == 0) {
s.push(x, y, 'D');
//在当前位置做一个向下的标志
temp[x][y] = 3;
x = x + 1;
temp[x][y] = 7; //当前位置
//判断是否到达出口如果到达出口则flag标记为true下同
if ((x == MAX_X - 1) && (y == MAX_Y - 2)) {
flag = true;
return;
} else
continue;
}
//向右
if (temp[x][y + 1] == 0) {
s.push(x, y, 'R');
//在当前位置做一个向右的标志
temp[x][y] = 4;
y = y + 1;
temp[x][y] = 7;
if ((x == MAX_X - 1) && (y == MAX_Y - 2)) {
flag = true;
return;
} else
continue;
}
//向上
if (temp[x - 1][y] == 0) {
s.push(x, y, 'U');
//在当前位置做一个向上的标志
temp[x][y] = 6;
x = x - 1;
temp[x][y] = 7;
if ((x == MAX_X - 1) && (y == MAX_Y - 2)) {
flag = true;
return;
} else
continue;
}
//向左
if (temp[x][y - 1] == 0) {
s.push(x, y, 'L');
//在当前位置做一个向右的标志
temp[x][y] = 5;
y = y - 1;
temp[x][y] = 7;
if ((x == MAX_X - 1) && (y == MAX_Y - 2)) {
flag = true;
return;
} else
continue;
}
//上下左右不通,则回退到起点
if (s.pop(x, y) == NULL && temp[x - 1][y] != 0 && temp[x][y - 1] != 0 &&
temp[x][y + 1] != 0 && temp[x + 1][y] != 0) {
temp[0][1] = 7;
if (temp[1][1] != 1) temp[1][1] = 2;
return;
}
}
}
char getch() {
char ch;
//保存原有终端属性和新设置的终端属性
static struct termios oldt, newt;
//获得终端原有属性并保存在结构体oldt
tcgetattr(STDIN_FILENO, &oldt);
//设置新的终端属性
newt = oldt;
newt.c_lflag &= ~(ICANON);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
//取消回显
system("stty -echo");
ch = getchar();
system("stty echo");
//让终端恢复为原有的属性
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
return ch;
}
void move() {
int x = 1, y = 1; //出发点
//一直游戏,直到走出
while (1) {
//判断输入的命令
switch (getch()) {
case 's':
if (maze[x + 1][y] == 0) {
maze[x][y] = 0;
x = x + 1;
maze[x][y] = 7; //当前位置
printMaze();
if ((x == MAX_X - 1) && (y == MAX_Y - 2)) {
cout << "\n\n 成功走出" << endl;
return;
}
}
break;
case 'd':
if (maze[x][y + 1] == 0) {
if (maze[x][y + 1] == 0) {
maze[x][y] = 0;
y = y + 1;
maze[x][y] = 7;
printMaze();
if ((x == MAX_X - 1) && (y == MAX_Y - 2)) {
cout << "\n\n 成功走出" << endl;
return;
}
}
}
break;
case 'w':
if (maze[x - 1][y] == 0) {
maze[x][y] = 0;
x = x - 1;
maze[x][y] = 7;
printMaze();
if ((x == MAX_X - 1) && (y == MAX_Y - 2)) {
cout << "\n\n 成功走出" << endl;
return;
}
}
break;
case 'a':
if (maze[x][y - 1] == 0) {
maze[x][y] = 0;
y = y - 1;
maze[x][y] = 7;
printMaze();
if ((x == MAX_X - 1) && (y == MAX_Y - 2)) {
cout << "\n\n 成功走出" << endl;
return;
}
}
break;
}
}
}
void autoMove(stack_of_maze& s) {
int x = 1, y = 1; //出发点
while (1) {
maze[x][y] = 2;
//向下
if (maze[x + 1][y] == 0) {
s.push(x, y, 'D');
maze[x][y] = 3; //在当前位置做一个向下的标志
x = x + 1;
maze[x][y] = 7; //当前位置
if (slow) printMaze();
if ((x == MAX_X - 1) && (y == MAX_Y - 2)) {
s.push(x, y, '*');
cout << "\n\n 成功走出" << endl;
return;
} else
continue;
}
//向右
if (maze[x][y + 1] == 0) {
s.push(x, y, 'R');
maze[x][y] = 4; //在当前位置做一个向右的标志
y = y + 1;
maze[x][y] = 7;
if (slow) printMaze();
if ((x == MAX_X - 1) && (y == MAX_Y - 2)) {
s.push(x, y, '*');
cout << "\n\n 成功走出" << endl;
return;
} else
continue;
}
//向上
if (maze[x - 1][y] == 0) {
s.push(x, y, 'U');
maze[x][y] = 6; //在当前位置做一个向上的标志
x = x - 1;
maze[x][y] = 7;
if (slow) printMaze();
if ((x == MAX_X - 1) && (y == MAX_Y - 2)) {
s.push(x, y, '*');
cout << "\n\n 成功走出" << endl;
return;
} else
continue;
}
//向左
if (maze[x][y - 1] == 0) {
s.push(x, y, 'L');
maze[x][y] = 5; //在当前位置做一个向右的标志
y = y - 1;
maze[x][y] = 7;
if (slow) printMaze();
if ((x == MAX_X - 1) && (y == MAX_Y - 2)) {
s.push(x, y, '*');
cout << "\n\n 成功走出" << endl;
return;
} else
continue;
}
//上下左右不通,则回退
if (s.pop(x, y) == NULL && maze[x - 1][y] != 0 && maze[x][y - 1] != 0 &&
maze[x][y + 1] != 0 && maze[x + 1][y] != 0) {
cout << "\n\n 没有找到合适的路径" << endl;
maze[0][1] = 7;
if (maze[1][1] != 1) maze[1][1] = 2;
return;
}
}
}
void menu();
void gamestart() {
//初始化地图
flag = false;
while (!flag) {
stack_of_maze stack;
//创建地图
createMaze();
//检查地图是否创建成功
check(stack);
//模仿进度条
system("clear");
cout << "\t* loading. *" << endl;
system("clear");
cout << "\t* loading.. *" << endl;
system("clear");
cout << "\t* loading... *" << endl;
}
//输出当前迷宫的初始状态
printMaze();
cout << "\n\n 输入enter键继续" << endl;
getchar();
//自行游戏
if (!autogame) {
move();
cout << "\n\n 输入enter键继续" << endl;
getchar();
menu();
}
//自动游戏
else {
stack_of_maze stack1;
autoMove(stack1); //行走中……
}
printMaze(); //输出迷宫的最终状态
cout << "\n\n 输入enter键继续" << endl;
getchar();
menu();
}
void menu() {
system("clear");
int num;
cout << "\t****************************************" << endl;
cout << "\t* *" << endl;
cout << "\t* 1.查看路径 *" << endl;
cout << "\t* *" << endl;
cout << "\t* 2.自动进行 *" << endl;
cout << "\t* *" << endl;
cout << "\t* 3.自行游戏 *" << endl;
cout << "\t* *" << endl;
cout << "\t* 4.退出游戏 *" << endl;
cout << "\t* *" << endl;
cout << "\t****************************************" << endl;
slow = false;
//选择模式
switch (getch()) {
case '1':
autogame = true;
gamestart();
break;
case '2':
autogame = true;
slow = true;
gamestart();
break;
case '3':
autogame = false;
gamestart();
break;
case '4':
exit(1);
break;
default:
cout << "\n\n 错误操作输入enter返回" << endl;
getchar();
menu();
}
getchar();
}
int main(int argc, char** argv) {
menu();
return 0;
}