课程设计之迷宫问题求解

/**
2019年6月数据结构课程设计
迷宫问题求解(三维)
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <windows.h>
#include <queue>
#define MAX_SIZE 100
using namespace std;
struct Node
{
    int x;      //当前坐标
    int y;
    int z;
    int prex;   //前置坐标
    int prey;
    int prez;
    int step;   //步数
};
char Map[MAX_SIZE][MAX_SIZE][MAX_SIZE];     //存迷宫图
int Vis[MAX_SIZE][MAX_SIZE][MAX_SIZE];      //标记迷宫是否走过
Node Path[MAX_SIZE][MAX_SIZE][MAX_SIZE];    //记录最短路径
class Maze  //迷宫类
{
    private:    //迷宫参数
        int L;//层数
        int R;//行数
        int C;//列数v
        int strx; //"S"坐标位置
        int stry;
        int strz;
        int endx;//“E”坐标位置
        int endy;
        int endz;
        int FLAG;//标记是否能通过
        int Minstep;//最小步数
    public:
        int Deposit;//判断是否存图
        bool BFS();//广度优先遍历
        void Ret_Maze();//初始化迷宫
        void Show_Maze();//显示迷宫
        void Get_Point(int &x, int &y, int &z);//获取终点“E”坐标位置
        void Print_Path(int x, int y, int z);//输出路径
};
void Maze::Get_Point(int &x, int &y, int &z)//以引用为变量赋值
{
    x = this->endx;
    y = this->endy;
    z = this->endz;
}
bool Maze::BFS()//广度优先遍历算法
{
    if (Deposit){
    int next[6][3] = {{0, 0, 1}, {0, 0, -1}, {0, 1, 0}, {0, -1, 0}, {1, 0, 0}, {-1, 0, 0}};//每六个为一组,对应x,y,z轴
    Node head,tail;//队头,队尾
    head.x = strx;//队头初始化为“S”坐标位置
    head.y = stry;
    head.z = strz;
    head.step = 0;
    Path[strx][stry][strz].x = strx;
    Path[strx][stry][strz].y = stry;
    Path[strx][stry][strz].z = strz;
    queue<Node> q;//创建队列
    q.push(head);//初始队头进队
    while(!q.empty()) {//循环队列
        head = q.front();//队头等于第组元素
        q.pop();//出队
        if (head.x == endx && head.y == endy && head.z == endz){//若到达终点
            FLAG = 1;//标记更新
            Minstep = head.step;//最短步数更新
            break;
        }
        for (int i = 0; i < 6; i++){//遍历六个方向
            tail.x = head.x + next[i][0];
            tail.y = head.y + next[i][1];
            tail.z = head.z + next[i][2];
            if (Map[tail.x][tail.y][tail.z] == '#' || tail.x < 0 || tail.x >= L || tail.y < 0 || tail.y >= R || tail.z < 0 || tail.z >= C){//判断是否越界
                continue;
            }
            if ((Map[tail.x][tail.y][tail.z] == '.' || Map[tail.x][tail.y][tail.z] == 'E') && Vis[tail.x][tail.y][tail.z] == 0){//可行进
                Path[tail.x][tail.y][tail.z].x = tail.x;//更新当前坐标和前置坐标
                Path[tail.x][tail.y][tail.z].y = tail.y;
                Path[tail.x][tail.y][tail.z].z = tail.z;
                Path[tail.x][tail.y][tail.z].prex = head.x;
                Path[tail.x][tail.y][tail.z].prey = head.y;
                Path[tail.x][tail.y][tail.z].prez = head.z;
                Vis[tail.x][tail.y][tail.z] = 1;//标记更新
                tail.step = head.step + 1;//步数更新
                q.push(tail);//此点入队
            }
        }
    }
    if (FLAG){//迷宫可连通
        cout << "You can make it through the maze, the shortest path is " << Minstep << " steps" << endl;
        return true;
    } else {
        cout << "This maze has no access!\n" << endl;
        return false;
    }
    }
    else {
        cout << "未存入迷宫!" << endl;
    }
}
void Maze::Ret_Maze()//初始化迷宫
{
    cout << "请输入迷宫数据(层数 行数 列数,有效数据均大于0,起点:“S” 终点:“E” 障碍:“#” 通路:“.”)\n";
    cin >> L >> R >> C;//层行列
    FLAG = 0;
    Minstep = 0;
    memset(Map, 0, sizeof(Map));//每次初始化必须重置
    memset(Vis, 0, sizeof(Vis));
    if (L == 0 || R == 0 || C == 0){//数据为0无意义
        cout << "数据错误!\n" ;
        return ;
    } else {//存图
        cout << "请输入存图方式:1.手动存图     2.随机存图\n";
        int number;
        cin >> number;
        if (number == 1){
        for (int i = 0; i < L; i++){
            for (int j = 0; j < R; j++){
                for (int k = 0; k < C; k++){
                    cin >> Map[i][j][k];
                    if (Map[i][j][k] == 'S'){
                        this->strx = i;
                        this->stry = j;
                        this->strz = k;
                    }
                    if (Map[i][j][k] == 'E'){
                        this->endx = i;
                        this->endy = j;
                        this->endz = k;
                    }
                }
            }
        }
    }
    else {
        int random;
        for (int i = 0; i < L; i++){
            for (int j = 0; j < R; j++){
                for (int k = 0; k < C; k++){
                    random = rand() % 2;
                    if (random){
                        Map[i][j][k] = '#';
                    } else {
                        Map[i][j][k] = '.';
                    }

                }
            }
        }
        cout << "请输入起点和终点坐标:" << endl;
        int x, y, z;
        cin >> x >> y >> z;
        this->strx = x;
        this->stry = y;
        this->strz = z;
        Map[x][y][z] = 'S';
        cin >> x >> y >>z;
        this->endx = x;
        this->endy = y;
        this->endz = z;
        Map[x][y][z] = 'E';
    }
    }
    Vis[strx][stry][strz] = 1;
    cout << "存图成功!\n";
    Deposit = 1;
}
void Maze::Show_Maze()//显示迷宫
{
    if (Deposit){
    int L = this->L;//获取层、行、列数目
    int R = this->R;
    int C = this->C;
    for (int i = 0; i < L; i++){//遍历输出图
        for (int j = 0; j < R; j++){
            for (int k = 0; k < C; k++){
                if (Map[i][j][k] == '#'){
                    cout << "■";
                } else if (Map[i][j][k] == '.'){
                    cout << "□";
                } else{
                    cout << Map[i][j][k];
                }
            }
                cout << endl;
        }
        cout << "第" << i+1 << "层" << endl << endl;
    }
    }
    else {
        cout << "未存入迷宫!\n";
    }
}
void Maze::Print_Path(int x, int y, int z)//路径输出
{
    if(Deposit){
    if(x == strx && y == stry && z == strz){//到达起点
        cout << "(" << Path[strx][stry][strz].y << "," << Path[strx][stry][strz].z << "," << Path[strx][stry][strz].x << ")" << endl;
        return ;
    }
    int px = Path[x][y][z].prex;//倒序输出
    int py = Path[x][y][z].prey;
    int pz = Path[x][y][z].prez;
    Print_Path(px, py, pz);//回溯
    cout << "(" << Path[x][y][z].y << "," << Path[x][y][z].z << "," << Path[x][y][z].x << ")" << endl;
    }
    else {
        cout << "未存入迷宫!" << endl;
    }
}
void Menu()//界面函数
{
    Maze text;
    text.Deposit = 0;//初始化为未存图
    while (1){
    int Lastx;    //终点坐标用于路径输出
    int Lasty;
    int Lastz;
    text.Get_Point(Lastx, Lasty, Lastz);  //提取终点坐标
    int number;
    system("color 78");
    system("date/t");
    system("time/t");
	printf("■■■■■■■■■■■■■■■■■■■■  \n");
	printf("■                                    ■  \n");
	printf("■  ■■■■■■■■■■■■■■■■  ■  \n");
	printf("■  ■欢迎使用迷宫问题求解系统■  ■  \n");
	printf("■  ■■■■■■■■■■■■■■■■  ■  \n");
	printf("■                                    ■  \n");
	printf("■■■■■■■■■■■■■■■■■■■■  \n");
	printf("\n");
	printf("请输入您的选择:\n");
	printf("1.存入迷宫   2.显示迷宫   3.输出最短路径   4.退出系统\n");
	scanf("%d", &number);
	switch(number){
	    case 1 :system("CLS");text.Ret_Maze();system("pause");break;
	    case 2 :system("CLS");text.Show_Maze();system("pause");break;
	    case 3 :system("CLS");text.Show_Maze();printf("以第一个点为坐标原点建立右手直角坐标系(x, y, z):\n");if(text.BFS()){text.Print_Path(Lastx, Lasty, Lastz);}system("pause");break;
	    case 4 :exit(0);
	}
    }
}
int main()
{
    Menu();
    return 0;
}
/*
样例
3 4 5
1
S....
.###.
.##..
###.#
#####
#####
##.##
##...
#####
#####
#.###
####E

3 4 5
1
.....
S###.
.##..
###.#
#####
#####
##.##
##...
#####
#####
#.###
####E

1 3 3
1
S##
#E#
###*/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值