迷宫求解路径:数据结构课设(c++)版

题目

1、问题描述: 
以一个m×n的长方阵表示迷宫,01分别表示迷宫中的道路和障碍.设计一个程序,对任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论.
2、基本要求: 
首先实现一个以链表做存储结构的栈类型,然后编写一个求解迷宫的非递归程序.求得的通路以三元组(i,j,d)的形式输出,其中:(i,j)指示迷宫中的一个坐标,d表示走到下一坐标的方向.如:对于下列数据的迷宫,输出的一条通路为(1,1,1),(1,1,2),(2,2,2),(3,2,3),(3,1,2),….
3、测试数据:
迷宫测试数据如下:左上角(1,1)为入口,右下角(8,9)为出口
                    1    2    3    4    5    6    7    8
0
0   1   0   0   0   1   0
0   0   1   0   0   0   1   0
0   0   0   0   1   1   0   1
0   1   1   1   0   0   1   0
0   0   0   1   0   0   0   0
0   1   0   0   0   1   0   1
0   1   1   1   1   0   0   1
1   1   0   0   0   1   0   1
1   1   0   0 
0   0   0   0

4、实现提示:
计算机解迷宫通常用的是“穷举求解”方法,即从入口出发,顺着某一个方向进行探索,若能走通,则继续往前进;否则沿着原路退回,换一个方向继续探索,直至出口位置,求得一条通路。假如所有可能的通路都探索到而未能到达出口,则所设定的迷宫没有通路。
可以二维数组存储迷宫数据,通常设定入口的下标为(11),出口点的下标为(n,n)。为处理方便起见,可在迷宫的四周加一圈障碍。对于迷宫中任一位置,均可约定有东、南、西、北四个方向可通。
5、选做内容 :
(1)编写递归形式的算法,求得迷宫中所有可能的通路;
(2)以方阵形式输出迷宫及其通路。

链表结点

#include
using namespace std;
template<typename Type>class LinkStack;
template<typename Type>class StackNode{
    private:
        friend class LinkStack;
        StackNode(Type dt,StackNode *next=NULL):m_data(dt),m_pnext(next){}
    private:
        Type m_data;
        StackNode *m_pnext; 
};

链表存储的栈结构实现

#include
#include "StackNode.h" 
template<typename Type> class LinkStack{ 
    public: 
        LinkStack():m_ptop(NULL){}//构造 
        ~LinkStack(){MakeEmpty();} //析构 
    public:
        void MakeEmpty();//make the stack empty
        void Push(const Type item); //push the data
        Type Pop();//pop the data
        Type GetTop() const;//get the data
        void Print();//print the stack
        bool IsEmpty()const{ 
            return m_ptop==NULL;
        }
        private:
            StackNode *m_ptop; 
};
template<typename Type> void LinkStack::MakeEmpty(){
    StackNode *pmove;
    while(m_ptop!=NULL){
        pmove=m_ptop;
        m_ptop=m_ptop->m_pnext;
        delete pmove;
    }
}
template<typename Type>void LinkStack::Push(const Type item){
    m_ptop=new StackNode(item,m_ptop);
}
template<typename Type>Type LinkStack::GetTop()const{
    if(IsEmpty()){
        cout<<"There is no elements\n";
        exit(1);
    }
    return m_ptop->m_data; 
}
template<typename Type>Type LinkStack::Pop(){
    if(IsEmpty()){
        cout<<"there is no element\n";
        exit(1);
    }
    StackNode*pdel=m_ptop;
    m_ptop=m_ptop->m_pnext;
    Type temp=pdel->m_data;
    delete pdel;
    return temp;
}
template<typename Type>void LinkStack::Print(){
    StackNode*pmove=m_ptop;
    printf("\n\n\t\t*****************************************\n");
    printf("\t\t*            迷宫通路输出               *\n");
    printf("\t\t*\t\t start \t\t\t*\n");
    while(pmove!=NULL){
        printf("\t\t*\t\t  ↓ \t\t\t*\n");
        printf("\t\t*\t       (%d,%d",pmove->m_data.x,pmove->m_data.y);
        switch(pmove->m_data.z){
            case 1:{
                printf(",东)                 *\n");
                break;
            }
            case 2:{
                printf(",南)                 *\n");
                break;
            }
            case 3:{
                printf(",西)                 *\n");
                break;
            }
            case 4:{
                printf(",北)                 *\n");
                break;
            }
            default:{
                printf(")                    *\n");
                break;
            }
        }
        pmove=pmove->m_pnext;
    }
    printf("\t\t*\t\t end \t\t\t*\n");
    printf("\t\t*****************************************\n");
} 

求解的代码(包括选做)

#include
#include 
#include"LinkStack.h" 
#include
using namespace std;
const int maxn=60;
int xto[5]={0,1,0,-1,0};//东,南,西,北 
int yto[5]={0,0,1,0,-1};
int tu[65][65];
bool vis[65][65];
char maze[65][65];
int sx,sy,ex,ey,n=1,m=1,t,q,fff=1;
//x,y,方向 
struct messege{
    int x,y,z;
    //messege(int &_x,int &_y):x(_x),y(_y){}
};
LinkStackpath;
//判断字符或者数值 
int panshu(){
    string c;
    int ten=1,sum=0,i=0,flag=1;
    cin>>c;
    int l=c.size();
    if(c[0]=='-'){
        flag=-1;
        i++;
    }
    while(iif(c[i]>='0'&&c[i]<='9'){
            sum=ten*sum+(c[i]-'0');
            ten*=10; 
        }
        else return -2;
        i++; 
    }
    sum*=flag;
    //printf("sum=%d\n",sum);
    return sum;
}

//非递归找一条路并输出 
bool dfs(){
    path.MakeEmpty();
    struct messege nex,now;//走到这个点了
    now.x=sx;
    now.y=sy; 
    now.z=0;
    path.Push(now);
    //cout<<"hell0\n";
    while(!path.IsEmpty()){
        now=path.GetTop();
        int i; 
        for(i=1;i<=4;i++){  
            nex.x=now.x+xto[i];
            nex.y=now.y+yto[i];//下一个点 
            //下一个可以走 
            if(nex.x>0&&nex.x<=n&&nex.y>0&&nex.y<=m&&!vis[nex.x][nex.y]){
                path.Pop();
                now.z=i;
                path.Push(now);//确定now这个点
                //printf("get(%d,%d,%d)\n",now.x,now.y,now.z);
                vis[now.x][now.y]=1;
                nex.z=0;
                path.Push(nex);
                if(nex.x==ex&&nex.y==ey)return true;
                break;
            }
        }
        //下一个不可以走,且绕了一周,证明now这个点不行的 
        if(i>4){
            vis[now.x][now.y]=1;
            path.Pop();
            //printf("return \n");
        }
    }
    return 0;
}

//输出路径 
void pri(){
printf("\n\n\t\t**************************************************************\n");
    printf("\t\t*                  #:障碍           .:通路                 *\n");
    printf("\t\t**************************************************************\n"); 

    for(int i=1;i<=60;i++){// 行m
        printf("\t\t*"); 
        for(int j=1;j<=60&&i<=m+2;j++){//列 n
            if(j<=n&&i<=m){
                printf("%c",maze[j][i]);
            }
            else if(j>n+3&&j<=60)printf("#");
            else printf(" ");
        }
        if(i<=m+2)printf("*\n");
        else if(i>m+2&&i<=60)printf("############################################################*\n");
        //else printf("                                                            *\n");
    }
    printf("\t\t**************************************************************\n");
}

//菜单选择进入或退出 
int menu(){
    printf("\t\t*****************************************\n");
    printf("\t\t*             迷宫求解程序              *\n");
    printf("\t\t*                 菜单                  *\n");
    printf("\t\t*         1.进入程序  0.退出程序        *\n");
    printf("\t\t*****PS.输入-1可以快速退出整个程序*******\n");
    printf("\t\t*****************************************\n");
    printf("\t\t请输入你的选择:");
    t=panshu();
    getchar();
    if(t==1)return 1;
    else if(t==-1||t==0)return -1;
    else return 0;
}

//再见结束 
void bye(){
    printf("\n\n\t\t*****************************************\n");
    printf("\t\t*             迷宫求解程序              *\n");
    printf("\t\t*             欢迎下次来玩              *\n");
    printf("\t\t*****************************************\n");
}

//递归输出路径 
void huisu(messege &now,int &flag){
    if(now.x==ex&&now.y==ey){
        flag=0;
        printf("\n\n\n");
        pri();
        return;
    } 
    messege nex;
    for(int i=1;i<=4;i++){
        nex.x=now.x+xto[i];
        nex.y=now.y+yto[i];//下一个点  
        now.z=i;
        //printf("(%d,%d,%d)\n",now.x,now.y,now.z);
        if(nex.x>0&&nex.x<=n&&nex.y>0&&nex.y<=m&&!vis[nex.x][nex.y]&&maze[nex.x][nex.y]==' '){
            vis[nex.x][nex.y]=1;
            maze[nex.x][nex.y]='.';
            huisu(nex,flag);
            vis[nex.x][nex.y]=0;
            maze[nex.x][nex.y]=' ';
        }
    }
    return;
}

//进度条 
void guodu(){
        printf("\n\n\t\t正在加载:") ; 
        int i=16;
        while(i--)
        {   printf("|");
            Sleep(30);
            printf("\b");
            printf("-");
            Sleep(30);
            printf("\b");
            printf("/");
            Sleep(30);
            printf("\b");
            printf(".");
            Sleep(30);
        }
        printf("\n");
} 

//初始化 
void init_vis(){
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=m;i++){//列 tu(第几列,第几排) 
        for(int j=1;j<=n;j++){//行填充 
            if(tu[j][i]==1){
                vis[j][i]=1;
                maze[j][i]='#';
            }
            else maze[j][i]=' ';
        }
    }
    if(maze[sx][sy]==' ')maze[sx][sy]='.';
}

//选择输出方式 
void choosepri(){
    printf("\n\n\t\t*****************************************\n");
    printf("\t\t*          选择输出(回车结束)           *\n");
    printf("\t\t*          1.指示输出一条路径           *\n");
    printf("\t\t*          2.方阵输出所有路径           *\n");
    printf("\t\t*****PS.输入-1可以快速退出整个程序*******\n");
    printf("\t\t*****************************************\n");
    printf("\t\t请输入你的选择:");
} 

//输入大小 
int inputsize(){
    printf("\n\n\t\t*****************************************\n");
    printf("\t\t*      输入迷宫的大小(0);
    printf("\t\t*****PS.输入-1可以快速退出整个程序*******\n");
    printf("\t\t*****PS.按下回车分隔两个数值*************\n");
    printf("\t\t*****************************************\n");
    printf("\t\t请输入|n:");
    n=panshu(); 
    printf("\t\t请输入|m:");
    m=panshu(); 
    if(n==-1||m==-1)return -1;
    else if(060&&060)return 1;
    else return 0;
}

//输入迷宫 
int inputmaze(){
    printf("\n\n\t\t*****************************************\n");
    printf("\t\t*       输入迷宫(回车换下一排)          *\n");
    printf("\t\t*       1----障碍       0----空路       *\n");
    printf("\t\t******PS.一旦输入有误请全部重新输入******\n");
    printf("\t\t******PS.输入-1可以快速退出整个程序******\n");
    printf("\t\t******PS.输入非0/1字符即可重新输入迷宫***\n");
    printf("\t\t******PS.回车分隔每一排,空格分隔每一列**\n");
    printf("\t\t*****************************************\n");
    int i,j;
    memset(vis,0,sizeof(vis));
    for(i=1;i<=m;i++){//列 tu(第几列,第几排) 
        printf("\t\t");
        for(j=1;j<=n;j++){//行填充 
            tu[j][i]=panshu();
            if(tu[j][i]==1){
                vis[j][i]=1;
                maze[j][i]='#';
            }
            else if(tu[j][i]==0){
                maze[j][i]=' ';
                vis[j][i]=0;
            }
            else if(tu[j][i]==-1){
                fff=0;
                return -1; 
            }
            else return 0; 
        }
    }
    return 1;
}

//输入起点(判错) 
int instart(){
    printf("\n\n\t\t*****************************************\n");
    printf("\t\t*           输入起点(x列,y排)           *\n");
    printf("\t\t*****PS.输入-1可以快速退出整个程序*******\n");
    printf("\t\t*****PS.按下回车分隔两个数值*************\n");
    printf("\t\t*****************************************\n");
    printf("\t\t请输入|x:");
    sx=panshu(); 
    printf("\t\t请输入|y:");
    sy=panshu();
    if(maze[sx][sy]==' ')maze[sx][sy]='.';
    if(sx==-1||sy==-1)return -1;
    else if(00return 1;
    else return 0;
}

//输入终点(判错) 
int inend(){
    printf("\n\n\t\t*****************************************\n");
    printf("\t\t*           输入终点(x列,y排)           *\n");
    printf("\t\t*****PS.输入-1可以快速退出整个程序*******\n");
    printf("\t\t*****PS.按下回车分隔两个数值*************\n");
    printf("\t\t*****************************************\n");
    printf("\t\t请输入|x:");
    ex=panshu();
    printf("\t\t请输入|y:");
    ey=panshu();
    if(ex==-1||ey==-1)return -1;    
    else if(00return 1;
    else return 0;
}

//迷宫无解输出 
void priworry(){
    printf("\n\n\t\t*****************************************\n");
    printf("\t\t*            sorry~此迷宫无解           *\n");
    printf("\t\t*****PS.输入-1可以快速退出整个程序*******\n");
    printf("\t\t*****************************************\n");
}

//输入错误时要求重新输入 ,同时输出该选项重输入 
void inputworry(){
    printf("\n\n\t\t*****************************************\n");
    printf("\t\t*            sorry~输入错误             *\n");
    printf("\t\t**************请重新输入*****************\n");
    printf("\t\t*****PS.输入-1可以快速退出整个程序*******\n"); 
    printf("\t\t*****************************************\n");  
}

//选择输出方式
int choose(){
    choosepri();
    q=panshu();
    if(q==-1)return -1;
    switch(q){
        case 1:{
            init_vis(); 
            if(dfs()&&maze[sx][sy]=='.'){
                LinkStackans;
                while(!path.IsEmpty()){
                    ans.Push(path.GetTop());
                    path.Pop();
                }
                ans.Print();
            }
            else priworry();
            break;
        }
        case 2:{
            init_vis();
            messege a;
            a.x=sx;
            a.y=sy;
            if(maze[sx][sy]=='.'){
                int flag=1;
            printf("\n\n\t\t**************************************************************\n");
                printf("\t\t*                     你输入的数值迷宫                       *\n");
                printf("\t\t**************************************************************\n"); 
                for(int i=1;i<=60;i++){
                    printf("\t\t*");
                    for(int j=1;j<=60;j++){
                        if(i<=m&&j<=n)printf("%d",tu[j][i]);//lie  hang 
                        else printf(" ");
                    } 
                    printf("*\n");
                }
                printf("\t\t**************************************************************\n"); 
                huisu(a,flag);
                if(flag)priworry();
            }
            else priworry();
            break;
        }
        default:{
            getchar(); 
            return 0;
            break;
        }
    }
    getchar(); 
    return 1;           
}

//是否想要消除上一个? 
int del(){
    printf("\t\t*****************************************\n");
    printf("\t\t*         是否想要消除上一个?          *\n");
    printf("\t\t*         1.是         0.否             *\n");
    printf("\t\t*****PS.输入-1可以快速退出整个程序********\n");
    printf("\t\t*****************************************\n");
    printf("\t\t请输入你的选择:");
    t=panshu();
    getchar();
    if(t==1)return 1;
    else if(t==-1)return -1;
    else if(t==0)return 0;
    else return -2;
}



int main(){
    system("color 4f");
    freopen("1.txt","r",stdin); 
    while(fff)
    {   
        //输入选项 
        while(fff){
            int z=menu();
            if(z==-1)fff=0;
            else if(z==1){
                int p; 
                while(fff){
                    p=del();
                    if(p==-1)fff=0;//退出 
                    else if(p==0)break;//否 
                    else if(p==1)break;//是 
                    else inputworry();//不符要求 
                }
                if(p==0)break;//成功的                 
            }
            else inputworry();
        }

        //进度条 
        guodu();
        system("cls");

        //输入大小 
        while(fff){
            int z=inputsize();
            if(z==-1)fff=0;
            else if(z==1){
                int p; 
                while(fff){
                    p=del();
                    if(p==-1)fff=0;//退出 
                    else if(p==0)break;//否 
                    else if(p==1)break;//是 
                    else inputworry();//不符要求 
                }
                if(p==0)break;//成功的 
            }
            else inputworry();
        }

        //输入迷宫 inputmaze
        while(fff){
            int z=inputmaze();
            if(z==-1)fff=0;//退出 
            else if(z==1){//符合要求 
                int p; 
                while(fff){
                    p=del();
                    if(p==-1)fff=0;//退出 
                    else if(p==0)break;//否 
                    else if(p==1)break;//是 
                    else inputworry();//不符要求 
                }
                if(p==0)break;//成功的 
            }
            else inputworry();//不符合要求 
        } 

        //起点instart
        while(fff){
            int z=instart();
            if(z==-1)fff=0;
            else if(z==1){
                int p; 
                while(fff){
                    p=del();
                    if(p==-1)fff=0;//退出 
                    else if(p==0)break;//否 
                    else if(p==1)break;//是 
                    else inputworry();//不符要求 
                }
                if(p==0)break;//成功的 
            }
            else inputworry();
        }

        //终点inend
        while(fff){
            int z=inend();
            if(z==-1)fff=0;
            else if(z==1){
                int p; 
                while(fff){
                    p=del();
                    if(p==-1)fff=0;//退出 
                    else if(p==0)break;//否 
                    else if(p==1)break;//是 
                    else inputworry();//不符要求 
                }
                if(p==0)break;//成功的 
            }
            else inputworry();
        }

        if(fff){
            guodu();        
        }
        //输入输出选择
        system("cls");

        while(fff){
            int z=choose();
            if(z==-1)fff=0;
            else if(z==0)inputworry();  
            printf("\t\t-----------------------------------------\n");
            printf("\t\t*****PS.按任意键退出这个观察区***********\n");
            getchar();
            system("cls");
            //getchar();
        }
    } 
    bye();
    return 0;
} 


你可能感兴趣的:(课设&实验)