C++老鼠迷宫

#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;
}




    以上是程序的截图,我们可以手动控制键盘的方向键来控制老鼠的移动
评论 32
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值