(C语言)栈的应用——迷宫问题求解

本文介绍了一种使用栈数据结构实现迷宫寻路的算法。通过递归回溯的方法找到从起点到终点的路径,详细展示了算法的具体实现过程及代码细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

全部代码

#include "stdio.h"
#include "stdlib.h"
#include "stdbool.h"
#define TRUE 1
#define ERROR 0
#define FALSE 0
#define STACK_INIT_SIZE 100
#define STACK_INCREMNT 10
#define OK 1

typedef int Status;
typedef struct {
	int x;
	int y;
}PosType;
typedef struct {
	int ord;       //通道块在路径上的“序号”
	PosType seat;  //通道块在迷宫中的“坐标位置”
	int di;        //从此通道块走向下一通道块的“方向”
}SElemType;        //栈的元素类型
typedef struct {
	int maze[10][10];
}MazeType;
typedef struct {
	SElemType* top;
	SElemType* base;
	int stacksize;
}Stack;
Status InitStack(Stack* S);
Status Pass(Stack S,MazeType map, PosType loc);
void FootPrint(MazeType maze, PosType pos);
PosType NextPos(PosType curpos, int a);
void Push(Stack* S, SElemType e);
Status StackEmpty(Stack S);
Status Pop(Stack* S, SElemType* e);
void MarkPrint(MazeType maze, PosType e);
Status MazePath(MazeType maze, PosType start, PosType end);

int main() {
	int i, j;
	MazeType map;
	PosType start, end;
	int maze_original[10][10] = {
		{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}
	};
	for (i = 0; i < 10; i++)
		for (j = 0; j < 10; j++)
			map.maze[i][j] = maze_original[i][j];
	for (i = 0; i < 10; i++) {
		for (j = 0; j < 10; j++)
		{
			printf("%d,",map.maze[i][j]);
		}
		printf("\n");
	}
	start.x = 1,start.y=1;
	end.x = 8, end.y = 8;
	MazePath(map, start, end);
}
Status ExitNode(Stack S,PosType loc) {
	while (S.base != S.top) {
		if (S.base->seat.x == loc.x && S.base->seat.y ==loc.y)
			return TRUE;
		S.base++;
	}
	return FALSE;
}
Status Pass(Stack S,MazeType map, PosType loc) {
	if (ExitNode(S, loc)) {return FALSE; }
	if (!map.maze[loc.x][loc.y]) {return TRUE; }
	else {return FALSE; }
}
Status InitStack(Stack* S) {
	S->base = (SElemType*)malloc(sizeof(SElemType) * STACK_INIT_SIZE);
	S->stacksize = STACK_INIT_SIZE;
	S->top = S->base;
}
void FootPrint(MazeType maze, PosType pos) {
	int i, j = 0;
	for (i = 0; i < 10; i++) {
		for (j=0; j < 10; j++) {
			if (i == pos.x && j == pos.y)
				printf("#,");
			else printf("%d,", maze.maze[i][j]);
		}
		printf("\n");
	}
	printf("\n");
}
PosType NextPos(PosType curpos, int a) {
	PosType CurNext;
	if (a == 1) {
		CurNext.x = curpos.x;
		CurNext.y = curpos.y + 1;
		return CurNext;
	}
	else if (a == 2) {
		CurNext.x = curpos.x + 1;
		CurNext.y = curpos.y;
		return CurNext;
	}
	else if (a == 3) {
		CurNext.x = curpos.x;
		CurNext.y = curpos.y - 1;
		return CurNext;
	}
	else if (a == 4) {
		CurNext.x = curpos.x - 1;
		CurNext.y = curpos.y;
		return CurNext;
	}
	else {
		printf("ERROR!\n");
	}
}
void Push(Stack* S, SElemType e) {
	if (S->top - S->base >= S->stacksize) {
		S->base = (SElemType*)realloc(S->base, sizeof(SElemType) * (S->stacksize + STACK_INCREMNT));
		S->top = S->base + S->stacksize;
		S->stacksize += STACK_INCREMNT;
	}
	S->top->di = e.di;
	S->top->ord = e.ord;
	S->top->seat = e.seat;
	S->top++;
}
Status StackEmpty(Stack S) {
	if (S.top == S.base)return TRUE;
	else return FALSE;
}
Status Pop(Stack* S, SElemType* e) {
	if (StackEmpty(*S))return ERROR;
	*e = *(S->top - 1);
	S->top--;
	return OK;
}
void MarkPrint(MazeType maze, PosType e) {
	int i, j;
	for (i = 0; i < 10; i++) {
		for (j = 0; j < 10; j++) {
			if (i == e.x && j == e.y) {
				printf("*,");
			}
			else {
				printf("%d,", maze.maze[i][j]);
			}
		}
		printf("\n");
	}
	printf("\n");
}
Status MazePath(MazeType maze, PosType start, PosType end) {
	//若迷宫maze中存在从入口start到出口end的通道,则求得一条存放在栈中(从栈底到栈顶),并返回TRUE;
	//否则返回FALSE
	PosType curpos;
	int curstep;
	Stack S;
	SElemType e,*p;
	InitStack(&S); curpos = start; //设定“当前位置”为“入口位置”
	curstep = 1;           //探索第一步
	do {
		if (Pass(S,maze, curpos)) {		//当前位置可以通过,即是未曾走到过的通道块
			//FootPrint(maze, curpos);          //留下足迹
			e.di = 1;
			e.ord = curstep;
			e.seat = curpos;
			Push(&S, e);             //加入路径
			if (curpos.x == end.x && curpos.y == end.y) break;  //到达终点(出口)
			curpos = NextPos(curpos, 1);    //下一位置是当前位置的东邻
			curstep++;          //探索下一步
		}
		else {  //当前位置不能通过
			if (!StackEmpty(S)) {
				Pop(&S, &e);
				while (e.di == 4 && !StackEmpty(S)) {
					//MarkPrint(maze, e.seat); 
					Pop(&S, &e);      //留下不能通过的标记,并退回一步
				}
				if (e.di < 4) {
					e.di++; Push(&S, e); //换下一个方向探索
					curpos = NextPos(e.seat, e.di); //设定当前位置是该新方向上的相邻块
				}
			}
		}
	} while (!StackEmpty(S));
	p = S.base;
	while (p != S.top) {
		printf("(%d,%d),", p->seat.x, p->seat.y);
		p++;
	}
	return (FALSE);
}

写在后面:代码稍微有点长,有许多需要改善的地方,有其他问题留言相互交流学习;

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值