栈的思想用于求解迷宫问题

迷宫问题是一个经典的问题,当迷宫规模较大时,手工求解是十分困难的,所以用善于进行重复繁琐计算的计算机来求解便十分合适。基本思想和解决“八皇后问题” 的思想一致,都是利用回溯法。从入口开始,探索每一个迷宫中没有被墙挡住的位置,如果该位置可以移动到下一个位置,则标记该位置已被探索过并入栈;如果不能移动到下一位置,则标记为探索失败并回退到上一个位置,如果最终退回了出发点,则说明迷宫无解。下面附上代码:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define passed 2
#define failed 3
#define N 2//定义迷宫规模
#define NUM (N+2)//定义迷宫总宽度
/*迷宫中为1的地方为墙壁,0为可到达的点*/ 
typedef int status;
typedef int elemtype;
/*定义位置pos*/ 
typedef struct pos{
    elemtype x;
    elemtype y;
    elemtype next;//当前位置的下一个位置 
}pos;
typedef struct sqstack{
    pos p[N*N];
    int top;
}sqstack;
int maze[NUM][NUM];//定义迷宫 

/*定义栈操作*/ 
status initstack(sqstack *S){
    S->top=-1;
}

status stacklength(sqstack *S){
    return S->top+1;
}

status push(sqstack *S,pos p){
    S->top++;
    S->p[S->top]=p;
}

status pop(sqstack *S){
    S->top--;
}

status gettop(sqstack *S,pos *p){
    *p=S->p[S->top];
}

status emptystack(sqstack *S){
    if(S->top==-1)
       return TRUE;
    else
       return FALSE;
}

/*其他操作*/
/*********************************/ 
/*设定位置*/
status setpos(pos *p,elemtype x,elemtype y){
    p->x=x;
    p->y=y; 
}

/*设定下一位置next*/ 
status setnext(pos *p,elemtype next){
    p->next=next;
}
/*判断是否可以到达下一个位置*/
status hasnext(pos *p){
    int x=0,y=0;
    p->next=0;//p->next用于八个方向的确定 
    while(p->next<8){
        p->next++;
        /*这部分代码用来让pos在附近的八个位置移动,以判断是否能到达下一位置*/
        switch(p->next){
            case 1:
                x=p->x+1;
                y=p->y+1;
                break;
            case 2:
                x=p->x+1;
                y=p->y-1;
                break;
            case 3:
                x=p->x-1;
                y=p->y+1;
                break;
            case 4:
                x=p->x-1;
                y=p->y-1;
                break;
            case 5:
                x=p->x+1;
                y=p->y;
                break;
            case 6:
                x=p->x;
                y=p->y+1;
                break;
            case 7:
                x=p->x-1;
                y=p->y;
                break;
            case 8:
                x=p->x;
                y=p->y-1;
                break;
        }
        /*判断移动之后的位置能否到达*/ 
        if(maze[x][y]==0){ 
            p->x=x;
            p->y=y;
            p->next=0;
            return OK;
        }
    }
    return ERROR;//不能到达,返回ERROR 
}

/*标记探索过且能通过的点*/
status markpassedpoint(pos *p){
    maze[p->x][p->y]=passed;
} 

/*标记无路可走的点*/
status markfailedpoint(pos *p){
    maze[p->x][p->y]=failed;
}

/*判断出口*/
status isexit(pos *p){
    if(p->x==N&&p->y==N)
        return TRUE;
    return FALSE;
}

/*生成迷宫*/
status makemaze(void){
    int i=0,j=0;
    srand(time(0));
    for(i=0;i<NUM;i++){
        for(j=0;j<NUM;j++){
            if(i==0||i==NUM-1||j==0||j==NUM-1)//迷宫四周的墙 
                maze[i][j]=1;
            else
                maze[i][j]=rand()%2; 
        }
    }
    maze[1][1]=maze[NUM-2][NUM-2]=0;//定义出入口 
}

/*打印迷宫*/
status printmaze(void){
    int i=0,j=0;
    for(i=0;i<NUM;i++){
        for(j=0;j<NUM;j++){
            printf("%d ",maze[i][j]);
        }
        printf("\n");
    }
    printf("\n");
} 

/*打印路径*/
status printway(sqstack *S){
    int i=0;
    printf("The avalible way is:\n");
    for(i=0;i<S->top;i++)
         printf("<%d,%d>->",S->p[i].x,S->p[i].y);
    printf("<%d,%d>",S->p[i].x,S->p[i].y);//分开写的目的是让最后一项不出现-> 
}

/*搜索路径*/
status searchway(){
    sqstack S;
    pos p;
    initstack(&S);
    setpos(&p,1,1);//设置初始位置为(1,1) 
    setnext(&p,0);//设初始位置下一位置可到达 
    push(&S,p);
    markpassedpoint(&p);
    /*栈不空是取最上方点进行判断,判断是否为出口*/ 
    while(!emptystack(&S)){
        gettop(&S,&p);
        if(isexit(&p)){
            printway(&S);
            return OK;
        }
        if(hasnext(&p)){
            push(&S,p);
            markpassedpoint(&p);
        }
        else{
            pop(&S);
            markfailedpoint(&p);
        }
    }
    return ERROR;//最终回到了出发点,返回ERROR表示无解 
}

status main(void){
    sqstack S;
    pos p;
    initstack(&S);
    makemaze();
    printf("The Maze is:\n");
    printmaze();
    if(!searchway()){
        printf("\nNo Avalible Ways\n");
    }
}

2016-04-14更新:
今天在测试自己写的迷宫的过程中,觉得每次用随机数生成的迷宫常常无解,此时就必须要亲自动手才能让程序重新生成迷宫然后重新寻找路径,十分麻烦。于是我对主程序进行了修改,让其只有在生成一个有解的迷宫后再输出答案(我真机智……)代码如下:

int main(void){
    stack S;
    pos p;
    makemaze();
    printf("The Maze is:\n");
    printmaze();
    if(!searchway()){/*如果没找到路*/
        while(!searchway()){
            makemaze();/*重新生成迷宫*/
            printmaze();
        }
    } 
}
    原文作者:迷宫问题
    原文地址: https://blog.csdn.net/kelvinmao/article/details/51100310
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞