数据结构-----迷宫问题(C语言)

数据结构-----迷宫问题

作者:黑衣侠客


前言

最近学习数据结构中,需要完成老师布置的作业,所以,研究了下迷宫问题,看起来很难的迷宫问题,其实,解决方法有很多,下面我将为大家介绍,用栈是如何解决迷宫问题的。

思路

首先,我们应该在代码中布置迷宫的地图,在布置迷宫地图时,以二维数组来存储每个点的数值,二维数组的好处是可以用坐标进行表示,此时,我设的是1为障碍物(墙),0为通路,下面来看一下,我在代码中所写的迷宫地图。
使用二维数组来对迷宫地图进行编辑
之后,我们定义一个栈结构,栈的每一层用来存储走过的每个格子的横坐标,纵坐标,以及从这个格子到下一格子所对应的方向的数字(在这里,我定义的方向是:0-上,1-右,2-下,3-左),然后再定义一个int型的指针,用于从栈底一次遍历到栈顶,方便对每一层的数据进行操作。具体代码是这样的:
typedef struct
{
    int i;              //当前方块的行号
    int j;              //当前方块的列号
    int di;             //di是下一可走相邻方位的方位号---上下左右的标记
} Box;
typedef struct
{
    Box data[MaxSize]; //是用来存储位置坐标的,当MaxSize<位置坐标的数目时,则程序出错,停止运行
    int top;            //栈顶指针
} StType;               //定义栈类型
然后我们再来说一下,具体的操作方法:
1.定义了mgpath方法,用来执行具体的走迷宫的思想操作
int mgpath(int xi,int yi,int xe,int ye)
其中,xi为原点的横坐标,yi为原点的纵坐标,xe为终点的横坐标,ye为终点的纵坐标。

2.初始化之前定义的栈,将栈的指针top赋值-1,然后top自增为0,就是栈的第一层,也就是栈底,存放横纵坐标,以及方位值,然后将点所在位置标为-1,以免走重。
 int i,j,k,di,find;
    StType st;                  //定义栈st
    st.top=-1;                  //初始化栈顶指针
    st.top++;                   //初始方块进栈
    st.data[st.top].i=xi;//栈底一号存入横坐标数值
    st.data[st.top].j=yi;//栈底一号存入纵坐标数值
    st.data[st.top].di=-1;//????????????????????????????????
    mg[xi][yi]=-1;
3.这是最重要的一步,当栈不是空的时候就一直循环,直到找到终点为止,每次循环开始时,find都为0,而di为0~3,因此,满足条件时,进入内层循环,在内层循环的第一行有一个di++,原因是:每次循环开始时,di的值都为-1,di自增后,就满足了对横纵坐标操作的条件了,我按照上右下左的顺序,改变此时所在的位置坐标,(详解:当di=0时,若走不通,那么就再次进入循环,进行自增,依次类推…),然后,当找到下一个位置为0时(通路),find=1,然后top向上走,在创建一行空间,让每个走过的0位置,都变为-1,此外,需要注意是弹栈操作,当碰到死胡同的时候,那么就需要进行弹栈了,返回到上一步,并将该位置的值从-1变回到0(在进行图像操作时需要用到这一点),(这里不用担心会再次重复走到这个死胡同的位置,因为di++,直接在上一基础方位自增,而不是重新开始,所以不必担心这一点),至此,迷宫思想已全部完成,接下来就该做一些优化了。
while (st.top>-1)           //栈不空时循环
    {
        i=st.data[st.top].i;
        j=st.data[st.top].j;
        di=st.data[st.top].di;  //取栈顶方块
        if (i==xe && j==ye)     //找到了出口,输出路径
        {
            printf("迷宫路径如下:\n");
            for (k=0; k<=st.top; k++)
            {
                printf("\t(%d,%d)",st.data[k].i,st.data[k].j);
                if ((k+1)%5==0) //每输出5个元素,就换行
                    printf("\n");
            }
            printf("\n");
            return 0;      //找到路径之后,将所有路径打印出来,然后,程序结束
        }
        find=0;
        while (di<4 && find==0)     //找下一个可走方块
        {
            di++;
            switch(di)
            {
            case 0://向上走
                i=st.data[st.top].i-1;
                j=st.data[st.top].j;
                break;
            case 1://向右走
                i=st.data[st.top].i;
                j=st.data[st.top].j+1;
                break;
            case 2://向下走
                i=st.data[st.top].i+1;
                j=st.data[st.top].j;
                break;
            case 3://向左走
                i=st.data[st.top].i;
    j=st.data[st.top].j-1;
                break;
            }
            if (mg[i][j]==0) find=1;    //mg[i][j]==0说明:该点可以走--------------(该点为此时所在点的下一预判点)
        }
        if (find==1)                    //找到了下一个可走方块
        {
            st.data[st.top].di=di;      //修改原栈顶元素的di值
            st.top++;                   //下一个可走方块进栈
            st.data[st.top].i=i;
            st.data[st.top].j=j;
            st.data[st.top].di=-1;  //再次初始化方向数值
            mg[i][j]=-1;                //避免重复走到该方块-----------------------//让每一个点都变成起点,因此,既满足递归的条件,也避免重复走到该位置
        }
        else                            //没有路径可走,则退栈-----------???????????为什么要退栈?不是刚刚只判断了一个方向吗?
        {
            mg[st.data[st.top].i][st.data[st.top].j]=0;//让该位置变为其他路径可走方块
            st.top--;                   //将该方块退栈
        }
4.我在主函数中,添加了一些优化操作,主要对输入原点以及图像做了简单处理。
 while(1){
   printf("请输入起点坐标:\n");
   printf("(横坐标范围:0~9,纵坐标范围:0~9)\n");
   scanf("%d %d",&x,&y);
   if(mg[x][y]==1){
   printf("输入坐标有误,该位置为墙,请重新输入:\n");
   }else{
    break;
   }
 }
图像处理:
 printf("\n\n图像表示:\n");
 for(t=0;t<10;t++){
  printf("\t\t");
  for(k=0;k<10;k++){
   if(mg[t][k]==1){
    printf("#");
   }else if(mg[t][k]==0){
    printf(" ");
   }else{
    printf("o");
   }
  }
  if(k==10){
   printf("\n");
  }
 }
 printf("\n此时,o所代表的图标为迷宫行走路径!!!\n");

代码部分

#include <stdio.h>
#define MaxSize 100
#define M 8
#define N 8
int mg[M+2][N+2]=
{
    {1,1,1,1,1,1,1,1,1,1},
    {1,0,0,1,0,0,0,1,0,1},
    {1,0,0,1,0,0,0,1,0,1},
    {1,0,0,0,0,1,1,0,0,1},
    {1,0,1,1,1,0,0,0,0,1},
    {1,0,0,0,1,0,0,0,0,1},
    {1,0,1,0,0,0,1,0,0,1},
    {1,0,1,1,1,0,1,1,0,1},
    {1,1,0,0,0,0,0,0,0,1},
    {1,1,1,1,1,1,1,1,1,1}
};//构造地图
typedef struct
{
    int i;              //当前方块的行号
    int j;              //当前方块的列号
    int di;             //di是下一可走相邻方位的方位号---上下左右的标记
} Box;
typedef struct
{
    Box data[MaxSize]; //是用来存储位置坐标的,当MaxSize<位置坐标的数目时,则程序出错,停止运行
    int top;            //栈顶指针
} StType;               //定义栈类型
//该栈中:每一个位置用于存储Box,该栈对应了一个int型的top作为指针,依次移动,方便对栈中每一个位置进行操作,而Box中,存储了该迷宫位置的横坐标,纵坐标,和从上一位置移动到该位置所对应的方向数值
int mgpath(int xi,int yi,int xe,int ye) //求解路径为:(xi,yi)->(xe,ye)
     //初位置横坐标,初位置纵坐标,终点横坐标,终点纵坐标
{
    int i,j,k,di,find;
    StType st;                  //定义栈st
    st.top=-1;                  //初始化栈顶指针
    st.top++;                   //初始方块进栈
    st.data[st.top].i=xi;//栈底一号存入横坐标数值
    st.data[st.top].j=yi;//栈底一号存入纵坐标数值
    st.data[st.top].di=-1;//????????????????????????????????
    mg[xi][yi]=-1;
    while (st.top>-1)           //栈不空时循环
    {
        i=st.data[st.top].i;
        j=st.data[st.top].j;
        di=st.data[st.top].di;  //取栈顶方块
        if (i==xe && j==ye)     //找到了出口,输出路径
        {
            printf("迷宫路径如下:\n");
            for (k=0; k<=st.top; k++)
            {
                printf("\t(%d,%d)",st.data[k].i,st.data[k].j);
                if ((k+1)%5==0) //每输出5个元素,就换行
                    printf("\n");
            }
            printf("\n");
            return 0;      //找到路径之后,将所有路径打印出来,然后,程序结束
        }
        find=0;
        while (di<4 && find==0)     //找下一个可走方块
        {
            di++;
            switch(di)
            {
            case 0://向上走
                i=st.data[st.top].i-1;
                j=st.data[st.top].j;
                break;
            case 1://向右走
                i=st.data[st.top].i;
                j=st.data[st.top].j+1;
                break;
            case 2://向下走
                i=st.data[st.top].i+1;
                j=st.data[st.top].j;
                break;
            case 3://向左走
                i=st.data[st.top].i;
    j=st.data[st.top].j-1;
                break;
            }
            if (mg[i][j]==0) find=1;    //mg[i][j]==0说明:该点可以走--------------(该点为此时所在点的下一预判点)
        }
        if (find==1)                    //找到了下一个可走方块
        {
            st.data[st.top].di=di;      //修改原栈顶元素的di值
            st.top++;                   //下一个可走方块进栈
            st.data[st.top].i=i;
            st.data[st.top].j=j;
            st.data[st.top].di=-1;  //再次初始化方向数值
            mg[i][j]=-1;                //避免重复走到该方块-----------------------//让每一个点都变成起点,因此,既满足递归的条件,也避免重复走到该位置
        }
        else                            //没有路径可走,则退栈-----------???????????为什么要退栈?不是刚刚只判断了一个方向吗?
        {
            mg[st.data[st.top].i][st.data[st.top].j]=0;//让该位置变为其他路径可走方块
            st.top--;                   //将该方块退栈
        }
    }
    return(0);                          //表示没有可走路径,返回0
}
int main()
{
 int x,y,k,t;
 printf("终点坐标为:(8,8)\n");
 while(1){
   printf("请输入起点坐标:\n");
   printf("(横坐标范围:0~9,纵坐标范围:0~9)\n");
   scanf("%d %d",&x,&y);
   if(mg[x][y]==1){
   printf("输入坐标有误,该位置为墙,请重新输入:\n");
   }else{
    break;
   }
 }
  mgpath(x,y,M,N);
 printf("\n\n图像表示:\n");
 for(t=0;t<10;t++){
  printf("\t\t");
  for(k=0;k<10;k++){
   if(mg[t][k]==1){
    printf("#");
   }else if(mg[t][k]==0){
    printf(" ");
   }else{
    printf("o");
   }
  }
  if(k==10){
   printf("\n");
  }
 }
 printf("\n此时,o所代表的图标为迷宫行走路径!!!\n");
    return 0;
}

运行结果

在这里插入图片描述

以上全部代码由vc++6.0调试成功
本次代码,我已传到github上------迷宫问题
  • 84
    点赞
  • 507
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
以下是使用C语言实现走迷宫的示例代码: ```c #include <stdio.h> #include <stdlib.h> #define ROW 10 #define COL 10 int maze[ROW][COL] = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 1, 1, 0, 1, 1, 1, 0, 1, 0}, {0, 1, 1, 0, 1, 1, 1, 0, 1, 0}, {0, 1, 1, 1, 1, 0, 0, 1, 1, 0}, {0, 1, 0, 0, 0, 1, 1, 1, 1, 0}, {0, 1, 1, 1, 0, 1, 1, 1, 1, 0}, {0, 1, 0, 1, 1, 1, 0, 1, 1, 0}, {0, 1, 0, 0, 0, 1, 0, 0, 1, 0}, {0, 0, 1, 1, 1, 1, 1, 1, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; int visited[ROW][COL] = {0}; // 标记是否访问过 typedef struct { int x; int y; } Pos; Pos path[ROW * COL]; // 保存路径 int top = -1; // 栈顶指针 void push(Pos p) { path[++top] = p; } Pos pop() { return path[top--]; } Pos get_top() { return path[top]; } int is_empty() { return top == -1; } void print_path() { int i; for (i = 0; i <= top; i++) { printf("(%d, %d) ", path[i].x, path[i].y); } printf("\n"); } void dfs(Pos start, Pos end) { push(start); visited[start.x][start.y] = 1; while (!is_empty()) { Pos cur = get_top(); if (cur.x == end.x && cur.y == end.y) { print_path(); return; } int i; for (i = 0; i < 4; i++) { Pos next; switch (i) { case 0: // 上 next.x = cur.x - 1; next.y = cur.y; break; case 1: // 下 next.x = cur.x + 1; next.y = cur.y; break; case 2: // 左 next.x = cur.x; next.y = cur.y - 1; break; case 3: // 右 next.x = cur.x; next.y = cur.y + 1; break; } if (maze[next.x][next.y] == 1 && visited[next.x][next.y] == 0) { push(next); visited[next.x][next.y] = 1; break; } } if (i == 4) { // 四个方向都走不通,回溯 visited[cur.x][cur.y] = 0; pop(); } } printf("No path found.\n"); } int main() { Pos start = {1, 1}; Pos end = {8, 8}; dfs(start, end); return 0; } ``` 该示例代码使用深度优先搜索算法实现了走迷宫的功能。其中,使用栈来保存路径,使用visited数组来标记是否访问过某个位置。具体实现过程可以参考代码注释。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值