#include<iostream>//输入输出流
#include<fstream>//文件头文件
#include<conio.h>
#include<time.h>//时间的头文件
#include<windows.h>//使用系统头文件
#include<string>//字符串头文件
#include<stack>//栈头文件
#include<math.h>//数学函数头文件
#include<ctype.h>//命名函数
#define TIME 12//规定的游戏时间
#define maxsize 1000 //栈最多的元素个数
using namespace std;
int **map;//迷宫二维动态数组
int M, N;//迷宫行与列数
int start_x, start_y, end_x, end_y, x, y;//老鼠的开始位置,最终位置等全局变量
int g;
int h;//老鼠的原位置
ofstream out;//将输入的数组写入文件
bool victory = false;//bool变量开始为假,为真时结束
//求最短路径和所有路径
struct MazeRoute {
int i; //路径横坐标
int j; //路径纵坐标
int d; //方向
}Stack[maxsize], path[maxsize]; //定义栈和存放最短路径的数组
int top = -1; //栈顶指针
int count = 1; //路径数计数
int minlen = maxsize; //最短路径长度
void mazeframe(int x1, int y1, int x2, int y2) {//起始坐标与终点坐标
int i, j, d, find, k, m, n;
int count = 1;
top++;//栈不空,初始结点入栈
Stack[top].i = x1;
Stack[top].j = y1;
Stack[top].d = -1;
map[x1][y1] = -1;//初始结点入栈
while (top>-1) {//栈不空时循环
i = Stack[top].i;
j = Stack[top].j;
d = Stack[top].d;
if (i == x2&&j == y2) {
cout << "路径:" << count++;//找到出口,输出路径
cout << endl;
for (k = 0; k <= top; k++) {
cout << "(" << Stack[k].i << "," << Stack[k].j << ")";
if ((k + 1) % 7 == 0)//输出每7个结点时换行
cout << endl;
}
cout << endl;
cout << "按回车键继续···\n";
cout << endl;
if (top + 1<minlen) {//比较输出最短路径
for (k = 0; k <= top; k++)
path[k] = Stack[k];//将最短路径存入path[]中
minlen = top + 1;
}
map[Stack[top].i][Stack[top].j] = 0;//让该位置变为其他路径的可走结点
i = Stack[top].i;
j = Stack[top].j;
d = Stack[top].d;
}
find = 0;
while (d<4 && find == 0) {//找下一个可走结点
d++;
switch (d) {
case 0:i = Stack[top].i - 1; j = Stack[top].j; break; //上面路可以移动时移动执行
case 1:i = Stack[top].i; j = Stack[top].j + 1; break; //右面路可以移动时移动执行
case 2:i = Stack[top].i + 1; j = Stack[top].j; break; //下面路可以移动时移动执行
case 3:i = Stack[top].i; j = Stack[top].j - 1; break; //左面路可以移动时移动执行
}
if (map[i][j] == 0 && map[i][j] != -1)
find = 1;
}
if (find == 1) {//找到了下一个可走的结点
Stack[top].d = d;//修改原栈顶元素的d值
top++;//下一个可走结点进栈
Stack[top].i = i;
Stack[top].j = j;
Stack[top].d = -1;
map[i][j] = -1;//避免重复走到该结点
}
else {
map[Stack[top].i][Stack[top].j] = 0;//让该位置变为其他路径的可走结点
top--;
}
}
cout << "最短路径:";
cout << endl;
for (k = 0; k<minlen; k++)
cout << "(" << path[k].i << "," << path[k].j << ")";
{
if ((k + 1) % 7 == 0)
cout << endl;
}
cout << endl;
}
// 改变迷宫的函数
void change() {
if (map[x][y] == 3) {//如果到达粮仓处就是获得胜利
victory = true;//因为初始化的victory为false
}
map[x][y] = 2;//原来的路为人
map[g][h] = 0;//原来的人变为路
}
//画图以及移动函数
//画图函数
void draw() {
for (int val = 0; val<M; val++) {//行
for (int flag = 0; flag<N; flag++) {//列
if (map[val][flag] == 1) {//1为墙
cout << "■";//就是墙
}
else if (map[val][flag] == 0) {//0为路
cout << " ";
}
else if (map[val][flag] == 2) {//2为老鼠
cout << '\001' << " ";
}
else if (map[val][flag] == 3) {//3为粮仓
cout << '\003' << " ";
}
}
cout << endl;//换行
}
}
//改变迷宫的墙与路
void ChangeMaze(int i, int j) {
int p;
if (i == 0 || j == 0 || (i == 1 && j == 1) || (i == M - 2 && j == N - 2)) {//围墙与老鼠以及粮仓的位置不能改变
cout << "这些位置是不能改变的";
}
else {
cout << "将墙变为路请输入0,将路变为墙请输入1:";
cin >> p;
switch (p) {
case 0:
map[i][j] = 0; break;//将其变为路
case 1:
map[i][j] = 1; break;//将其变为墙
}
}
}
//向上的函数
void up() {
if (map[x - 1][y] != 1) {//如果向上有通路
g = x;//将老鼠的原位置赋给g h,在change函数中变为路
h = y;
x = x - 1;//改变老鼠的新位置,在change函数中实现
}
}
//向下的函数
void down() {
if (map[x + 1][y] != 1) {//如果向下有通路
g = x;//将老鼠的原位置赋给g h,在change函数中变为路
h = y;
x = x + 1;//改变老鼠的新位置,在change函数中实现
}
}
//向右的函数
void right() {
if (map[x][y + 1] != 1) {//如果向右有通路
g = x;//将老鼠的原位置赋给g h,在change函数中变为路
h = y;
y = y + 1;//改变老鼠的新位置,在change函数中实现
}
}
//向左的函数
void left() {
if (map[x][y - 1] != 1) {//如果向左有通路
g = x;//将老鼠的原位置赋给g h,在change函数中变为路
h = y;
y = y - 1;//改变老鼠的新位置,在change函数中实现
}
}
int CountLinesh(char *filename) {//统计迷宫数组的行数
ifstream in;
int n = 0;
string temp;
in.open(filename, ios::in);//ios::in 表示以只读的方式读取文件
if (in.fail()) {//文件打开失败:返回0
return 0;
}
else {//文件存在
while (getline(in, temp)) {
n++;
}
return n;
}
in.close();//关闭文件
}
int CountLinesz(char *filename) {
ifstream in;
int n = 0;
int i;
in.open(filename, ios::in);//ios::in 表示以只读的方式读取文件
while (!in.eof()) {//判断是否到达文件尾
i = in.get();
if (in.fail()) {
break;
}
if (isdigit(i)) {
n++;//总数加一
}
}
return n;
in.close();
}
int main() {
char choice;
cout << "您是否想要自己构建迷宫呢?Y OR N: ";
cin >> choice;
switch (choice) {
case 'Y':char sd[50];//文件路径字符数组
cout << "请输入你要保存的文件路径:";
cin >> sd;
out.open(sd);
cout << "请输入二维数组迷宫的行数与列数: ";
int vb, vn, ch;
cin >> vb >> vn;
cout << "请输入二维数组表示的迷宫,其中0表示路,1表示墙,2表示老鼠,3表示粮仓:" << endl;
int ql, qk;
for (ql = 0; ql<vb; ql++) {
for (qk = 0; qk<vn; qk++) {
cin >> ch;
out << ch << " ";
}
out << '\n';
}
out.close();
break;
case 'N':break;
default:break;
}
int count = 0;//字符总数
int hang = 0;//数组行数
char p[50];
ifstream in;
int i;
cout << "请输入要打开文件的路径:";
cin >> p;
count = CountLinesz(p);
hang = CountLinesh(p);
M = hang;
N = count / M;//N为列数
start_x = (M - 1) / 2;//老鼠的初始位置
start_y = (N - 1) / 2;
end_x = M - 2;//粮仓的位置
end_y = N - 2;
x = start_x;
y = start_y;
g = 0;
h = 0;
map = (int**)malloc(sizeof(int*)*M);
for (int l = 0; l<M; l++) {
map[l] = (int*)malloc(sizeof(int)*N);
} //创建动态数组
in.open(p);
for (int n = 0; n<M; n++) {
for (int m = 0; m<N; m++) {
in >> i;//将文件中的数字写入内存
map[n][m] = i;//将内存中的数据写入到数组中
}
}
//接下来是初始化
for (int sx = 0; sx<N; sx++) {
map[0][sx] = 1;
}
for (int sc = 1; sc<M; sc++) {
map[sc][0] = 1;
}
for (int sv = 1; sv<N; sv++) {
map[M - 1][sv] = 1;
}
for (int sb = 1; sb<M - 1; sb++) {
map[sb][N - 1] = 1;
}
map[(M - 1) / 2][(N - 1) / 2] = 2;
map[M - 2][N - 2] = 3;
map[M - 3][N - 2] = 1;
in.close();
draw();//先画原图
char ch;//输入字符是否要改变墙与路
cout << "是否要改变墙与路?Y OR N :";
cin >> ch;
while (ch == 'Y') {
switch (ch) {
case 'Y':int pa, pb;
cout << "请输入你要改变的位置:";
cin >> pa >> pb;
ChangeMaze(pa, pb);
break;
case 'N':break;
}
cout << "是否要改变墙与路?Y OR N :";
cin >> ch;
}
draw();
clock_t start, finish;//即使开始和结束
double totaltime;//程序执行的总时间
start = clock();//计时开始
while (!victory) {//victory为false时开始执行
unsigned short k;//定义一个获取键盘消息的反映机制整型数
Sleep(100);//将进程挂起100毫秒,也就是0.1秒
k = _getch();
if (27 == k) break;//?Esc???
if (0 == k || 0xe0 == k) k |= _getch() << 8;//????
switch (k) {
case 0x48e0: up(); change(); system("cls"); draw(); break;//向上,改变位置,清屏,再画图,结束
case 0x4be0: left(); change(); system("cls"); draw(); break;//向左,改变位置,清屏,再画图,结束
case 0x50e0: down(); change(); system("cls"); draw(); break;//向下,改变位置,清屏,再画图,结束
case 0x4de0: right(); change(); system("cls"); draw(); break;//向右,改变位置,清屏,再画图,结束
default:break;
}
}
finish = clock();//计时结束
totaltime = (double)(finish - start) / CLOCKS_PER_SEC;
cout << "\n此程序运行的总时间是" << totaltime << "秒!" << endl;
if (totaltime<TIME) cout << "小于规定的时间12秒,恭喜你,你赢了!" << endl;
else cout << "大于规定的时间12秒,很抱歉,你输了!" << endl;
map[start_x][start_y] = 0;
map[end_x][end_y] = 0;
mazeframe(start_x, start_y, end_x, end_y);
//删除动态数组
for (int z = 0; z<M; z++) {
delete[]map[z];//先撤销指针元素所指向的数组
}
delete[]map;
system("pause");
return 0;
}