栈的应用(迷宫求解)

#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;
}

运行结果:


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值