导航

用栈实现的迷宫问题

Posted on 2015-09-14 23:23  CSU蛋李  阅读(2365)  评论(0编辑  收藏  举报

迷宫问题中为了保证任何位置上都能沿原路退回,显然需要用一个先进后出的结果来保存从入口到当前位置的路径。因此,在迷宫通路的算法中应用“栈”也是自然而然的事情

头文件:

#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define MYOVERFLOW -2
typedef int Status;
typedef struct{
    int x;      //通道块位置的横坐标
    int y;      //通道块位置的纵坐标
    char flag;  //通道块是否可行的标志
}PoseType;
typedef struct{
    int ord;         //通道块在路径上的”序号“
    PoseType seat;   //通道块在迷宫中的”坐标位置“
    int di;          //从此通道块走向下一通道块的”方向“
}SElemtype;          //栈的元素类型
typedef struct{
    SElemtype *base;//在栈构造之前和销毁之后,base的值为NULL
    SElemtype *top;//栈顶!d=====( ̄▽ ̄*)b指针
    int stacksize;//当前已分配的空间储存,以元素为单位
}SqStack;
//-------基本操作的函数原型说明--------
Status visit(SqStack S);//对栈进行遍历
void Create_Stack(SqStack &S);//创建一个栈
Status InitStack(SqStack &S);//构造一个空栈S
Status DestroyStack(SqStack &S);//销毁栈S,S不再存在
Status ClearStack(SqStack &S);//把S置为空栈
Status StackEmpty(SqStack S);//若栈S为空栈,则返回TRUE,否则返回FALSE    
int StackLength(SqStack S);//返回S的元素个数,即栈的长度
Status GetTop(SqStack S, SElemtype &e);
//若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR
Status Push(SqStack &S, SElemtype e);
//插入元素e为新的栈顶元素
Status Pop(SqStack &S, SElemtype &e);
//若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
Status StackTraverse(SqStack S, Status(*visit)(SqStack S));
//从栈底到栈顶依次对栈中每个元素调用函数visit()一旦visit()失败,则操作失败
void maze();//一个迷宫,求它从起点到终点的路径

上述操作的实现:

#include "stdafx.h"
Status InitStack(SqStack &S)//构造一个空栈S
{
    S.base = (SElemtype *)malloc(STACK_INIT_SIZE*sizeof(SElemtype));
    if (!S.base)exit(MYOVERFLOW);
    S.top = S.base;
    S.stacksize = STACK_INIT_SIZE;
    return OK;
}
Status DestroyStack(SqStack &S)//销毁栈S,S不再存在
{
    for (; S.top != S.base;){
        SElemtype *temp = S.top;
        S.top--;
        delete temp;
    }
    delete S.base;
    S.stacksize = 0;
    return OK;
}
Status ClearStack(SqStack &S)//把S置为空栈
{
    S.top = S.base;
    return OK;
}
Status StackEmpty(SqStack S)//若栈S为空栈,则返回TRUE,否则返回FALSE
{
    if (S.top == S.base)return TRUE;
    else return FALSE;
}
int StackLength(SqStack S)//返回S的元素个数,即栈的长度
{
    int length = 0;
    for (; S.top != S.base; S.top--)length++;
    return length;
}
Status GetTop(SqStack S, SElemtype &e)
//若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR
{
    if (S.top != S.base){
        e = *(S.top - 1);
        return OK;
    }
    else return ERROR;

}
Status Push(SqStack &S, SElemtype e)
//插入元素e为新的栈顶元素
{
    if (S.top - S.base >= S.stacksize){
        S.base = (SElemtype *)realloc(S.base, (S.stacksize + STACKINCREMENT)*sizeof(SElemtype));
        if (!S.base)exit(MYOVERFLOW);
        S.top = S.base + S.stacksize;
        S.stacksize += STACKINCREMENT;
    }
    *(S.top++) = e;
    return OK;
}
Status Pop(SqStack &S, SElemtype &e)
//若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
{
    if (S.top != S.base){
        e = *(--S.top);
        return OK;
    }
    else return ERROR;
}
Status visit(SqStack S)//对栈进行遍历1
{
    if (S.base){
        cout << "the data of the Stack is:";
        for (; S.top != S.base;)
        {
            --S.top;
            cout << S.top->di << " " << S.top->ord << " " << S.top->seat.x << ',' << S.top->seat.y <<S.top->seat.flag<< endl;
        }
        return OK;
    }
    else return ERROR;
}
Status StackTraverse(SqStack S, Status(*visit)(SqStack))
//从栈底到栈顶依次对栈中每个元素调用函数visit()一旦visit()失败,则操作失败
{
    if (visit(S))return OK;
    return ERROR;
}
void Create_Stack(SqStack &S)//创建一个栈
{
    InitStack(S);
    cout << "please input the length of the Stack:";
    int len;
    cin >> len;
    cout << "please input the data of the Stack:";
    for (int i = 1; i <= len; i++){
        SElemtype temp;
        cin >> temp.di>>temp.ord>>temp.seat.x>>temp.seat.y>>temp.seat.flag;
        Push(S, temp);
    }
}
void maze()//一个迷宫,求它从起点到终点的路径
{ 
    PoseType map[8][8];
    srand((int)time(0));
    for (int i = 0; i <= 7; i++)//构造地图
    {
        cout << "                         ";
        for (int j = 0; j <= 7; j++)
        {
            map[i][j].flag = 2;
            map[i][j].x = i;
            map[i][j].y = j;
            double ran = rand() / (RAND_MAX + 1.0);
            if (ran<= 0.7)map[i][j].flag = 1;//在这个地图中,墙所占的比例为30%
            cout << map[i][j].flag<< " ";
        }
        cout << endl;
    }
    cout << endl << endl << endl << endl;
    map[0][0].flag =0;//起点为地图的左上角
    map[7][7].flag = 1;//终点为地图的右下角
    int t = 1;//是迷宫路径上的第几块通道
    SqStack sq;
    InitStack(sq);//构造一个空的栈
    SElemtype first;
    first.di = 0;
    first.ord = t;
    first.seat = map[0][0];
    Push(sq, first);//将起点放到栈中
    do{
        SElemtype way, nextstep;
        Pop(sq,way);
        switch (way.di)
        {
        case 0:if (way.seat.y < 7 && map[way.seat.x][way.seat.y+1].flag==1){//如果上个通道块的di为0,则地图向右扩展
                   nextstep.di = 0;//新的通道块的di=0;是第++t个通道块,通道块的flag标志为0,说明此通道块被扩展
                   nextstep.ord = ++t;
                   map[way.seat.x][way.seat.y + 1].flag = 0;
                   nextstep.seat = map[way.seat.x][way.seat.y+1];
                   way.di++;//上个通道块的di++,说明右边的通道块已经被扩展
                   Push(sq, way);
                   Push(sq, nextstep);//将上个通道块和新的通道块都压入栈中
                   if (nextstep.seat.x == 7 && nextstep.seat.y == 7)goto label;//如果是终点,则跳出循环
                   break;
        }
               else {                                              //如果向右不能扩展,则di++,并将上个通道块压入栈
                   way.di++; Push(sq, way); break;
               }
        case 1:if(way.seat.x < 7 && map[way.seat.x+1][way.seat.y].flag == 1){//同case 0,这是向下扩展
                   nextstep.di = 0;
                   nextstep.ord = ++t;
                   map[way.seat.x+1][way.seat.y].flag = 0;
                   nextstep.seat = map[way.seat.x+1][way.seat.y];
                   way.di++;
                   Push(sq, way);
                   Push(sq, nextstep);
                   if (nextstep.seat.x == 7 && nextstep.seat.y == 7)goto label;
                   break;
        }
               else {
                   way.di++;
                   Push(sq, way); break;
               }
        case 2:if (way.seat.y >0 && map[way.seat.x ][way.seat.y- 1].flag == 1){//同case 0,这是向左扩展
                   nextstep.di = 0;
                   nextstep.ord = ++t;
                   map[way.seat.x][way.seat.y - 1].flag = 0;
                   nextstep.seat = map[way.seat.x][way.seat.y - 1];
                   way.di++;
                   Push(sq, way);
                   Push(sq, nextstep);
                   if (nextstep.seat.x == 7 && nextstep.seat.y == 7)goto label;
                   break;
        }
               else {
                   way.di++;
                   Push(sq, way); break;
               }
        case 3:if (way.seat.x > 0 && map[way.seat.x-1 ][way.seat.y].flag == 1){//同case 0,这是向上扩展
                   nextstep.di = 0;
                   nextstep.ord = ++t;
                   map[way.seat.x-1][way.seat.y].flag = 0;
                   nextstep.seat = map[way.seat.x-1 ][way.seat.y];
                   way.di++;
                   Push(sq, way);
                   Push(sq, nextstep);
                   if (nextstep.seat.x == 7 && nextstep.seat.y == 7)goto label;
                   break;
        }
               else {
                   way.di++;
                   Push(sq, way); break;
               }
        default:                                         //如果该通道块4个方向上已经被扩展完毕,则将这个通道块的flag设置为3,说明已经被扩展,但此路不通
                map[way.seat.x][way.seat.y].flag = 3;
                t--;
                break;
        }
    } while (!StackEmpty(sq));//当栈为空时,说明没有通路,跳出循环
    label:
    if (StackEmpty(sq)){ cout << "there is no way in the maze!"; exit(-1); }
    for (int i = 0; i <= 7; i++)
    {
        cout << "                         ";
        for (int j = 0; j <= 7; j++)
        {
            cout << map[i][j].flag << " ";
        }
        cout << endl;
    }
}

主函数:

// maze.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"


int _tmain(int argc, _TCHAR* argv[])
{
    maze();
    return 0;
}

 


运行结果:

上述实心笑脸表示墙,空心笑脸表示此路可行,最终形成的空白是从起点到终点的通路