#include <stdio.h>
#include <stdlib.h>
#define MAXLENGTH 25 //行、列的最大值
#define STACT_INIT_SIZE 10 //存储空间初始分配量
#define STACKINCREMNET 2 //存储空间分配增量
typedef enum {true = 1, false = 0}bool; //布尔参量
typedef enum {OK = 1, ERROR = 0}status; //状态参量
//声明迷宫数组
typedef int MazeType[MAXLENGTH][MAXLENGTH];
//定义坐标位置结构类型
typedef struct
{
int x;
int y;
}PosType;
//定义通道块的结构类型
typedef struct
{
int ord; //通道块在路径上的序号
PosType seat; //通道块的坐标位置
int di; //从此通道块走向下一通道块的“方向”
}SElemType; //栈的元素类型
//定义栈的结构类型
typedef struct
{
SElemType *top;
SElemType *base;
int statck_size;
}SqStack;
//定义数组
MazeType m;
//全局变量
static int cur_step = 1; //当前足迹,初值为1
//函数声明
void array_print(int x, int y);
static bool Pass(PosType b);
static void FootPrint(PosType a);
PosType NextPos(PosType cur_pos, int di);
static bool MazePath(PosType start, PosType end);
static void MarkPrint(PosType e);
static bool InitStack(SqStack *s);
static bool StackEmpty(SqStack *s);
static bool PushStack(SqStack *s, SElemType e);
static bool PopStack(SqStack *s, SElemType *value);
static bool ClearStack (SqStack *s);
static bool StackTraverse(SqStack *s, SElemType *c);
static bool DestroyStack(SqStack *s);
int main(void)
{
int i, j, x, y;
int wall_x = 0;
int wall_y = 0;
int wall_num = 0;
PosType start;
PosType end;
puts("请输入迷宫的行数、列数(包括外墙)");
scanf("%d%d", &x, &y);
printf("您输入的行数和列数分别是:%5d%5d\n", x, y);
//将外墙都置为0
for (i=0; i<x; i++)
{
m[0][i] = 0; //将最上面一行都置为0
m[x-1][i] = 0; //将最右边一列都置为0
}
for (j=1; j<y; j++)
{
m[j][0] = 0;
m[j][y-1] = 0;
}
//将通道初值都设置为1
for (i=1; i<x-1; i++)
{
for (j=1; j<y-1; j++)
{
m[i][j] = 1;
}
}
printf("请输入迷宫内墙单元数:");
scanf("%d", &wall_num);
puts("请依次输入迷宫内墙每个单元的行数,列数");
for (i=1; i<=wall_num; i++)
{
scanf("%d%d", &wall_x, &wall_y);
m[wall_x][wall_y] = 0; //墙要设置为0
}
puts("迷宫的结构如下:");
array_print(x, y);
printf("请输入起点的行数、列数");
scanf("%d%d", &start.x, &start.y);
printf("请输入终点的行数、列数");
scanf("%d%d", &end.x, &end.y);
if (MazePath(start, end))
{
puts("此迷宫从入口到出口的一条路径如下:");
array_print(x, y);
}
else
{
puts("此迷宫没有从入口到出口的路径");
}
}
void array_print(int x, int y)
{
int i = 0;
int j = 0;
for (i = 0; i < x; i++)
{
for (j = 0; j< y; j++)
{
printf("%5d", m[i][j]);
}
putchar('\n');
}
return;
}
//测试这个点是否是可通过的块
static bool Pass(PosType b)
{
if (1 == m[b.x][b.y])
{
return true;
}
else
{
return false;
}
}
//使迷宫的a点的序号变为足迹(cur_step)
static void FootPrint(PosType a)
{
m[a.x][a.y] = cur_step;
}
//根据当前位置及移动方向,返回下一位置
PosType NextPos(PosType cur_pos, int di)
{
PosType direc[4] = {{0,1}, {1,0}, {0,-1}, {-1,0}}; //{行增量,列增量}
//移动方向,依次为东南西北
cur_pos.x += direc[di].x;
cur_pos.y += direc[di].y;
return cur_pos;
}
//将不能通过的块标记为-1
static void MarkPrint(PosType e)
{
m[e.x][e.y] = -1;
}
//走迷宫程序
static bool MazePath(PosType start, PosType end)
{
PosType cur_pos;
SElemType e;
SqStack s;
InitStack(&s);
cur_pos = start;
do
{
//当前通道块可以通过
if (Pass(cur_pos))
{
//留下足迹
FootPrint(cur_pos);
//将需要保存的状态放入e中
e.ord = cur_step;
e.seat.x = cur_pos.x;
e.seat.y = cur_pos.y;
e.di = 0;
//将e进栈
PushStack(&s, e);
//足迹加1
cur_step++;
//下面判断是否到达了终点
if (cur_pos.x==end.x && cur_pos.y==end.y)
{
return true;
}
cur_pos = NextPos(cur_pos, e.di);
}
else
{
if (!StackEmpty(&s))
{
PopStack(&s, &e);
cur_step--;
//前一个位置处于方向北
while(3==e.di && !StackEmpty(&s))
{
MarkPrint(e.seat); //将这个块做标记
PopStack(&s, &e); //再退一步
cur_step--;
}
//还没到最后一个方向
if (e.di < 3)
{
e.di++;
PushStack(&s, e);
cur_step++;
//设定当前位置是该新方向上的相邻块
cur_pos = NextPos(e.seat, e.di);
}
}
else
{
puts("已无路可走了");
return false;
}
}
} while (!StackEmpty(&s));
return false;
}
static bool InitStack(SqStack *s)
{
//分配存储空间,来存放SElemType类型的元素
s->base = (SElemType *) malloc (STACT_INIT_SIZE * sizeof(SElemType));
if (!s->base)
{
return false;
exit(-1);
}
//空栈时,栈顶指针和栈底指针指向同一个位置
s->top = s->base;
s->statck_size = STACT_INIT_SIZE;
return true;
}
static bool PushStack(SqStack *s, SElemType e)
{
//如果栈已满,则需要重新分配内存
if ((s->top-s->base) >= s->statck_size)
{
s->base = (SElemType *) realloc (s->base, (s->statck_size + STACKINCREMNET)*sizeof(SElemType));
if (!s->base)
{
return false;
exit(-1);
}
s->top = s->base + s->statck_size;
s->statck_size += STACKINCREMNET;
}
*s->top++ = e;
return true;
}
static bool PopStack(SqStack *s, SElemType *value)
{
if (s->top == s->base)
{
puts("stack is empty");
return false;
}
*value = *(--s->top);
return true;
}
static bool StackEmpty(SqStack *s)
{
if (s->top == s->base)
{
return true;
}
else
{
return false;
}
}
static bool ClearStack (SqStack *s)
{
s->top = s->base;
return true;
}
//栈必须从顶部开始出栈,
static bool StackTraverse(SqStack *s, SElemType *c)
{
SElemType *p = NULL;
p = s->top; //是为了保护这个栈,不让这个栈变成空栈
while(s->top > s->base)
{
*c = *(--s->top);
printf("%d", *c);
}
s->top = p; //栈遍历结束后,将top重新指向栈顶的位置
putchar('\n');
return true;
}
//销毁这个栈
static bool DestroyStack (SqStack *s)
{
free(s->base);
s->base = NULL;
s->top = NULL;
s->statck_size = 0;
return true;
}
运行结果: