迷宫问题

想了很久, 终于做出来了, 不过数据结构的设计基本都是参照数据结构基础书上来的,如如何表示不同方向?怎么根据不同方向计算下一个位置的坐标等,数据结构设计的好做起来就相对会更方便。

大致流程:

1. 设计表示数据的结构。如迷宫可以用一个二维数组表示, 坐标也可以用二维数组表示, 移动的方向也可以用一个结构体表示,不同方向存在一个一维数组中, 这样设计的好处是方便计算下一个位置的坐标,以及遍历各个方向。设计一个二维数组来标记走过的足迹。

2. 使用栈来记录走过得坐标。 首先将起点入栈,比较是否是迷宫出口, 不是的话设置栈顶元素为当前位置,  然后依次遍历各个方向, 根据方向计算下一个位置的坐标, 如果合法就入栈,记录足迹,重新设置当前位置。如果不合法就跳到下一个方向, 如果所有方向都不行,就出栈, 重新设置当前位置。

3. 可以用栈为空时表示找不到走出迷宫的路径。


源码如下:

//Stack.h

#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

typedef struct Element {
    short int row;
    short int col;
    short int dir;
} Element;

typedef struct Stack {
    Element * pelem;
    int top;
    int capacity;
}Stack;

Stack * initStack(void);
int isEmpty(const Stack * st);
int isFull(const Stack * st);
int addSpace(Stack * st);
int PUSH(Stack * st, Element e);
int POP(Stack * st, Element * e);
int destoryStack(Stack * st);
int getTop(Stack * st, Element *e);

//Stack.c

#include "Stack.h"
#define CAP 100

Stack * initStack(void)
{
    Stack * pst;
    pst = (Stack *)malloc(sizeof(Stack));
    if(NULL == pst)
    {
        return NULL;
    }
    pst->top = -1;
    pst->capacity = CAP;
    pst->pelem = (Element *)malloc(CAP * sizeof(Element));
    if(NULL == pst->pelem)
    {
        fprintf(stderr, "initStack failed.\n");
        return NULL;
    }
    
    return pst;
}

int isEmpty(const Stack * st)
{
    if (st->top == -1)
        return 1;
    return 0;
}

int isFull(const Stack * st)
{
    if(st->top == st->capacity -1)
        return 1;
    return 0;
}

int addSpace(Stack * st)
{
    if(NULL == st)
    {
        printf("addSpace error.\n");
        return 0;
    }
    st->pelem = (Element *)realloc(st->pelem, 2 * st->capacity * sizeof(Element));
    if(NULL == st->pelem)
    {
        return 0;
    }
    st->capacity = 2 * st->capacity;
    return 1;
}

int PUSH(Stack * st, Element e)
{
    if(++st->top == st->capacity)
    {
        addSpace(st);
    }
    st->pelem[st->top] = e;
    return 1;
}

int POP(Stack * st, Element * e)
{
    if(st->top == -1)
        return 0;
    memcpy(e, &st->pelem[st->top--], sizeof(Element));
    return 1;
}

int destoryStack(Stack * st)
{
    if(NULL == st)
        return 1;
    free(st->pelem);
    free(st);
    return 1;
}

int getTop(Stack * st, Element *e)
{
    if(NULL == st || NULL == e)
    {
        printf("getTop error\n");
        return 0;
    }
    *e = st->pelem[st->top];
    return 1;
}


//main.c

#include "Stack.h"
#define DIR 8
#define EXIT_ROW 11
#define EXIT_COL 14

typedef struct {
    short int vert;
    short int horiz;
}Offsets; //表示移动方向数据结构


Offsets move[DIR] = {{-1, -1}, {0, -1}, {1, -1}, {-1, 0}, {1, 0}, {-1, 1}, {0, 1}, {1, 1}};//共8个方向

void showpath(Stack * st);// 输出走出迷宫的路径

int maze[12][15] = {
    {0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1},
    {1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1},
    {0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1},
    {1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0},
    {1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1},
    {0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1},
    {0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1},
    {0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1},
    {0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1},
    {1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0},
    {0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0},
    {0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0}
};//迷宫, 0 表示可以通过, 1表示不可以通过

int main()
{
    Stack *pst;
    int mark[12][15]; //1表示走过的位置
    int i, j;
    Element current; //当前位置
    Element next; //下一个位置
    int success = 0; //成功标识
    
    pst = initStack();
    if(NULL == pst)
    {
        printf("initStack failed.\n");
        exit(1);
    }
    
    /*初始化标记为0*/
    for(i = 0; i < 12; i++)
        for(j = 0; j < 15; j++)
            mark[i][j] = 0;
    
    //起点入栈,并记录足迹
    current.row = 0;
    current.col = 0;
    current.dir = 0;
    PUSH(pst, current);
    mark[current.row][current.col] = 1;
    
    while(!isEmpty(pst)) //栈不空
    {
        int dirc;
        
        if(current.row == EXIT_ROW && current.col == EXIT_COL)  //当前位置就是出口
        {
            printf("Congraturation! you find the way!\n");
            success = 1;
            showpath(pst);
            break;
        }

        for(dirc = 0; dirc < DIR; dirc++) //遍历各个方向
        {
            //根据当前的方向计算下一个坐标
            current.dir = dirc;
            next.row = current.row + move[current.dir].vert;
            next.col = current.col + move[current.dir].horiz;
            
            //如果下一个坐标不合法就跳到下一个方向
            if(next.row < 0 || next.col < 0 || mark[next.row][next.col] == 1 || next.row > 11 || next.col > 14 ||
                maze[next.row][next.col] == 1)
            {
                if(dirc == DIR -1)  //如果所有方向的下一个位置都不合法,就退栈
                {
                    POP(pst, &current);//如果起点位置被退栈说明迷宫无解
                    printf("pop: row = %d, col = %d\n", current.row, current.col);
                    getTop(pst, &current); //重新设置当前位置
                    break;
                }
                continue;
            }
        
            if(maze[next.row][next.col] == 0)//下一个位置合法,入栈,记录足迹,重新设置当前位置
            {
                current = next;
                PUSH(pst, current);
                printf("push: row = %d, col = %d\n", current.row, current.col);
                mark[current.row][current.col] = 1;
                break;
            }
        
        }
    }
    
    if(!success)
    {
        printf("There is no way to go, Bye.\n");
    }
    
    return 0;
}

void showpath(Stack * st)
{
    Element path[st->top + 1];
    int i = 0;
    int count = 0;
    while(!isEmpty(st))
    {
        POP(st, &path[i++]);
    }
    while(i--)
    {
        printf("(%d, %d) -> ", path[i].row, path[i].col);
        if(count++ % 5 == 4)
            printf("\n");
    }
    printf("success.\n");
}


如果想找出所有路径可以怎么做呢?



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值