C/C++数据结构栈的应用:迷宫求解核心算法

本文详细介绍了一种基于栈的迷宫寻路算法,利用二维数组表示迷宫结构,通过递增的足迹值追踪路径,结合东南西北四个方向的移动策略,实现从入口到出口的有效路径寻找。

前面的一些类型的定义

#define MAXLENGTH 25 //最大列为25
struct PosType
{
  int x;
  int y;
};
PosType Begin,End; //入口坐标,出口坐标
//行增量,列增量,分别为东南西北
PosType direc[4]={{0,1},{1,0},{0,-1},{-1,0}};
typedef int MazeType[MAXLENGTH][MAXLENGTH]; //迷宫数组类型
MazeType m; //m是一个[25][25]的二维数组
int x,y; //迷宫的行列数
int curstep=1; //当前足迹(在入口处)为1
typedef struct
{
  int ord; //通道快在路径上的序号
  PosType seat; //通道块在迷宫中的坐标
  int di; //走向下一个通道块的方向
}SElemType;
#include"Stack.h"//栈的基本操作函数

迷宫的创建

void Init()
{
  int i,j,x1,y1;
  printf("输入迷宫的行数,列数(包括外墙):");
  scanf("%d,%d",&x,&y);
  for(i=0;i<y;i++)
  {
    m[0][i]=0; //上面
    m[x-1][i]=0; //下面
  }
  for(i=1;i<x-1;i++)
  {
    m[i][0]=0; //左边
    m[i][y-1]=0; //右边
  }
  for(i=1;i<x-1;i++)
   for(j=1;j<y-1;j++)
    m[i][j]=1; //其余都是通道,初值为1
  printf("请输入迷宫内墙的单元数(不包括外墙):");
  scanf("%d",&j);
  printf("请依次输入迷宫内墙的行列数(eg:3,4):\n");
  for(i=1;i<=j;i++)
  {
    scanf("%d,%d",&x1,&y1);
    m[x1][y1]=0;
  }
  printf("迷宫结构如下(1为通路,0为墙):\n");
  Print1();
  printf("请输入起点的行列数(eg:1,1):");
  scanf("%d,%d",&Begin.x,&Begin.y);
  printf("请输入终点的行列数(eg:8,8):");
  scanf("%d,%d",&End.x,&End.y);
}

核心算法中用到的函数:
1.迷宫m的b点值为1(可通过路径),返回OK,否则返回ERROR

// 定义墙元素值为0,可通过路径为1,经试探不可通过路径为-1,通过路径为足迹
Status Pass(PosType b)
{
  if(m[b.x][b.y]==1)
    return OK;
  else
    return ERROR;
}

2.使迷宫m的b点值变为足迹(已经通过的路径标识)curstep(>1)

void FootPrint(PosType b)
{
  m[b.x][b.y]=curstep+1; //+1防止开局右边死胡同出现bug
}

3.根据当前位置b和移动方向di,修改b为下一个位置

void NextPos(PosType &b, int di)
{ //0123东南西北
  b.x+=direc[di].x;
  b.y+=direc[di].y;
  //direc[4]={{0,1},{1,0},{0,-1},{-1,0}};
}

4.使迷宫m的b点值变为-1(经试探不能到达终点的路径)

void MarkPrint(PosType b)
{
  m[b.x][b.y]=-1;
}

核心算法MazePath,默认往东走,判断这一步会不会撞墙,不会就赋值一个大于1的正数,表示已经走过的路径,入栈;如果撞墙了,退栈到前一个位置,按顺时针方向依次尝试看能否走通,都走不通(遇到0以及大于1的数)标记此路不通(-1),退栈到前一个位置,换一个方向继续尝试

//迷宫中存在一条通路,求得一条放入栈中(栈底->栈顶)并返回TRUE
Status MazePath(PosType start, PosType end)
{
  PosType curpos=start; //当前位置在入口
  SqStack s; //顺序栈
  SElemType e; //栈元素,存储了足迹,位置,方向的信息
  InitStack(s); //初始化栈
  do
  {
    if(Pass(curpos)) //当前位置可以通过(未走过的通道块) m[i][j]=1才满足
    {
      //m[i][j]=0(墙),m[i][j]>1(走过的路径)
      FootPrint(curpos); //将大于1的数赋给m[i][j],留下足迹表示已经走过
      e.ord=curstep; //栈元素的序号为当前足迹curstep=1
      e.seat=curpos; //栈元素的位置为当前位置
      e.di=0; //下一个位置向东
      Push(s,e); //入栈当前位置及状态
      if(curpos.x==End.x&&curpos.y==End.y) return TRUE;
      NextPos(curpos,e.di); //当前位置以及移动方向,确定下一个位置
      curstep++; //足迹+1
    }
    else //当前位置不能通过
    {
      if(!StackEmpty(s)) //栈不空
      {
        Pop(s,e); //退栈到前一个位置
        curstep--;
        while(e.di==3&&!StackEmpty(s))
        {
          MarkPrint(e.seat); //留下不能到达终点的标记(-1)
          Pop(s,e);
          curstep--;
        }
        if(e.di<3) //未到最后一个方向(北)
        {
          e.di++; //换下一个方向探索
          Push(s,e);
          curstep++;
          curpos=e.seat; //确定当前方向
          NextPos(curpos,e.di);
        }
      }
    }
  }while(!StackEmpty(s));
  return FALSE;
}

程序运行结果验证算法:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值