迷宫游戏(10×10)c实现

目录

使用栈实现迷宫路径搜索算法

迷宫表示

算法思路

代码实现

1.全部代码

2.头文件和宏定义

3.主调函数

4.核心函数

5.辅助函数

5.1构造一个空栈

5.2判断是否可通,并返回可通的方向

5.3将待入栈的元素设置指定值

5.4插入元素e为新的栈顶元素

5.5判断是否到达出口

5.6返回下一个位置(坐标)

5.7死路,标记不可通,设置迷宫的相应位置为-1

5.8判断是否为空栈

5.9出栈,弹出一个栈顶元素

5.10判断当前位置是否可通(通过判断下一个位置时墙、死路、还是访问过)

5.11遍历栈,打印路径

5.12打印路径信息

测试结果

总结

说明


使用栈实现迷宫路径搜索算法

在编程中,迷宫问题是一个经典的搜索问题,通常用于演示图搜索算法,如深度优先搜索(DFS)或广度优先搜索(BFS)。然而,这里我们将使用栈来实现一个深度优先搜索的迷宫路径搜索算法。栈是一种后进先出(LIFO)的数据结构,非常适合用于递归或迭代实现的深度优先搜索。

迷宫表示

迷宫通常用一个二维数组表示,其中0表示不可通行的墙壁,1表示可以通行的路径。为了记录搜索过程,我们还需要两个额外的状态:2表示已经访问过的路径,-1表示尝试但无法通行的路径。

算法思路

  1. 初始化:设置起点和终点,初始化栈。
  2. 搜索:从起点开始,尝试四个方向(东、南、西、北)的移动。
  3. 判断:如果当前位置是终点,则找到路径;如果当前位置可通行且未访问过,则标记为已访问并继续搜索;如果当前位置不可通行或已访问过,则回溯到上一个位置。
  4. 回溯:如果当前位置的所有方向都尝试过且无法继续,则从栈中弹出上一个位置,继续尝试其他方向。
  5. 结束:当栈为空时,表示所有可能的路径都已尝试,无法找到路径。

代码实现

以下是使用C语言实现的迷宫路径搜索算法的代码。

1.全部代码

#include<stdio.h>
#include<stdlib.h>
#define MAZESIZE 10
#define STACK_INIT_SIZE 20
#define STACKINCREMENT 2
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0

typedef int Status;//状态,函数返回值
typedef int Bool;
typedef struct
{
	int x, y;
}PosType;//坐标
typedef struct
{
	int ord;//当前位置在当前路径的序号
	PosType seat;
	int di;//方向
}SElemType;//栈元素类型
typedef struct
{
	SElemType* top, * base;
	int stacksize;
}SqStack;//栈结构
typedef struct
{
	int scene[MAZESIZE][MAZESIZE];
	PosType start, end;
}MazeType;//迷宫类型

//以下是函数声明
Status MazePath(MazeType, SqStack*);
Status InitStack(SqStack*);
int Pass(MazeType, PosType);//留下访问过的足迹
void SetCurSElem(int, PosType, int, SElemType*);
Status Push(SqStack*, SElemType);
void FootPrint(MazeType*, PosType);
Bool isReach(MazeType, PosType);
PosType NextPos(PosType, int);
Bool StackEmpty(SqStack);
void MarkPrint(MazeType*, PosType);//标记死路
Status Pop(SqStack*, SElemType*);
Bool isAccess(MazeType, PosType,int);
Status StackTraverse(SqStack);
void visit(SElemType);

int main()
{
	MazeType maze =
	{
		{	{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}
		},
		{1,1},
		{8,8},
	};//初始化迷宫,生成迷宫场景
	SqStack S;
	InitStack(&S);//构造空栈
	if (MazePath(maze, &S))//调用迷宫路径搜索函数
	{
		printf("The path is:\n");
		StackTraverse(S);
	}
	else
	{
		printf("No path found.");
	}
	return 0;
}
//迷宫通路搜索函数
Status MazePath(MazeType maze, SqStack*pS)
{//若迷宫maze存在从入口start到出口end通道,则求得一条存放在栈中(从栈底
	//到栈顶,这条路径的特点是所有方向的和一定是最小的,仅对该算法而言),
	//并返回TRUE;否则返回FALSE

	PosType CurPos = maze.start;//设定“当前位置”为“入口位置”
	int CurStep = 1;
	SElemType e;
	int i;
	do
	{//退出while循环的两种可能,找到出口或迷宫无解(栈空,由于栈的先进后出的特点,
		//它一定是以回到起点尝试了最后方向,发现无路可走而结束的)

		i = Pass(maze, CurPos);//判断当前位置是否可通,返回最小可通方向
		if (i)//可能值1,2,3,4
		{
			SetCurSElem(CurStep, CurPos, i, &e);
			Push(pS, e);//加入路径,准备走向可通方向上的下一个位置
			FootPrint(&maze, CurPos);//留下足迹,不影响退栈
			if (isReach(maze, CurPos))return TRUE;//到达出口
			CurPos = NextPos(CurPos, i);//走向下一个位置
			CurStep++;//准备下一步的探索
		}
		else//当前位置不可通
		{
			MarkPrint(&maze, CurPos);//标记死路
			if (!StackEmpty(*pS))//栈非空,可以回到上一个位置
			{
				Pop(pS, &e);//准备回到上一个位置
				CurPos = e.seat;//回到上一个位置,进行新一轮的判断
				CurStep = e.ord;
			}
		}
	} while (!StackEmpty(*pS));
	return FALSE;
}
//1.构造一个空栈(栈的基本操作)
Status InitStack(SqStack* pS)
{
	pS->base = (SElemType*)malloc(STACK_INIT_SIZE * sizeof(SElemType));
	if (!pS->base)return ERROR;
	pS->top = pS->base;
	pS->stacksize = STACK_INIT_SIZE;
	return OK;
}
//2.判断当前位置是否可通,并返回可通的最小方向,否则返回0
//通过判断下一个位置在迷宫中的性质(通路,墙,死路,访问过)
int Pass(MazeType maze, PosType pos)
{
	int i;
	for(i=1;i<=4;i++)
		if (isAccess(maze, pos,i))
		{
			return i;
		}
	return 0;
}
//3.将待入栈的元素设置为特定值
void SetCurSElem(int ord, PosType pos, int di, SElemType* p)
{
	p->ord = ord;
	p->seat = pos;//同一结构体类型可以赋值
	p->di = di;
}
//4.插入元素e为新的栈顶元素(栈的基本操作)
Status Push(SqStack* pS, SElemType e)
{
	if (pS->top - pS->base >= pS->stacksize)//栈满,追加空间
	{
		pS->base = (SElemType*)realloc(pS->base, 
			(pS->stacksize + STACKINCREMENT) * sizeof(SElemType));
		if (!pS->base)return ERROR;
		pS->top = pS->base + pS->stacksize;
		pS->stacksize += STACKINCREMENT;
	}
	*pS->top++ = e;
	return OK;
}
//5.在迷宫相应位置标记2,代表访问过
void FootPrint(MazeType* pMaze, PosType pos)
{
	pMaze->scene[pos.x][pos.y] = 2;
}
//6.判断是否到达出口(栈顶元素)
Bool isReach(MazeType maze, PosType pos)
{
	return pos.x == maze.end.x && pos.y == maze.end.y;
}
//7.返回下一个位置(坐标)
PosType NextPos(PosType pos, int i)
{
	PosType next = pos;
	switch (i)
	{
	case 1:next.y = pos.y + 1; break;
	case 2:next.x = pos.x + 1; break;
	case 3:next.y = pos.y - 1; break;
	case 4:next.x = pos.x - 1;
	}
	return next;
}
//8.标记死路,将迷宫相应位置改为-1
void MarkPrint(MazeType* pMaze, PosType pos)
{
	pMaze->scene[pos.x][pos.y] = -1;
}
//9.判断是否栈空
Bool StackEmpty(SqStack S)
{
	return S.top == S.base;
}
//10.弹出一个栈顶元素,用e返回其值,并返回OK;否则返回ERROR
Status Pop(SqStack* pS, SElemType* p)
{
	if (!StackEmpty(*pS))
	{
		*p = *--pS->top;
		return OK;
	}
	return ERROR;
}
//11.判断当前位置的下一个位置是否可通
Bool isAccess(MazeType maze, PosType pos,int i)
{
	PosType next = NextPos(pos, i);
	return maze.scene[next.x][next.y] == 1;
}
//12.遍历栈,打印路径
Status StackTraverse(SqStack S)
{
	SElemType* p;
	p = S.base;
	while (p)
	{
		visit(*p++);
	}
	return OK;
}
//13.打印路径信息
void visit(SElemType e)
{
	printf("Step %d:(%d,%d),next:%d\n", e.ord, e.seat.x, e.seat.y, e.di);
}

2.头文件和宏定义

#include<stdio.h>
#include<stdlib.h>
#define MAZESIZE 10
#define STACK_INIT_SIZE 20
#define STACKINCREMENT 2
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0

typedef int Status;//状态,函数返回值
typedef int Bool;
typedef struct
{
	int x, y;
}PosType;//坐标
typedef struct
{
	int ord;//当前位置在当前路径的序号
	PosType seat;
	int di;//方向
}SElemType;//栈元素类型
typedef struct
{
	SElemType* top, * base;
	int stacksize;
}SqStack;//栈结构
typedef struct
{
	int scene[MAZESIZE][MAZESIZE];
	PosType start, end;
}MazeType;//迷宫类型

//以下是函数声明
Status MazePath(MazeType, SqStack*);
Status InitStack(SqStack*);
int Pass(MazeType, PosType);//留下访问过的足迹
void SetCurSElem(int, PosType, int, SElemType*);
Status Push(SqStack*, SElemType);
void FootPrint(MazeType*, PosType);
Bool isReach(MazeType, PosType);
PosType NextPos(PosType, int);
Bool StackEmpty(SqStack);
void MarkPrint(MazeType*, PosType);//标记死路
Status Pop(SqStack*, SElemType*);
Bool isAccess(MazeType, PosType,int);
Status StackTraverse(SqStack);
void visit(SElemType);

3.主调函数

int main()
{
	MazeType maze =
	{
		{	{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}
		},
		{1,1},
		{8,8},
	};//初始化迷宫,生成迷宫场景
	SqStack S;
	InitStack(&S);//构造空栈
	if (MazePath(maze, &S))//调用迷宫路径搜索函数
	{
		printf("The path is:\n");
		StackTraverse(S);
	}
	else
	{
		printf("No path found.");
	}
	return 0;
}

4.核心函数

//迷宫通路搜索函数
Status MazePath(MazeType maze, SqStack*pS)
{//若迷宫maze存在从入口start到出口end通道,则求得一条存放在栈中(从栈底
	//到栈顶,这条路径的特点是所有方向的和一定是最小的,仅对该算法而言),
	//并返回TRUE;否则返回FALSE

	PosType CurPos = maze.start;//设定“当前位置”为“入口位置”
	int CurStep = 1;
	SElemType e;
	int i;
	do
	{//退出while循环的两种可能,找到出口或迷宫无解(栈空,由于栈的先进后出的特点,
		//它一定是以回到起点尝试了最后方向,发现无路可走而结束的)

		i = Pass(maze, CurPos);//判断当前位置是否可通,返回最小可通方向
		if (i)//可能值1,2,3,4
		{
			SetCurSElem(CurStep, CurPos, i, &e);
			Push(pS, e);//加入路径,准备走向可通方向上的下一个位置
			FootPrint(&maze, CurPos);//留下足迹,不影响退栈
			if (isReach(maze, CurPos))return TRUE;//到达出口
			CurPos = NextPos(CurPos, i);//走向下一个位置
			CurStep++;//准备下一步的探索
		}
		else//当前位置不可通
		{
			MarkPrint(&maze, CurPos);//标记死路
			if (!StackEmpty(*pS))//栈非空,可以回到上一个位置
			{
				Pop(pS, &e);//准备回到上一个位置
				CurPos = e.seat;//回到上一个位置,进行新一轮的判断
				CurStep = e.ord;
			}
		}
	} while (!StackEmpty(*pS));
	return FALSE;
}

5.辅助函数

5.1构造一个空栈
//1.构造一个空栈(栈的基本操作)
Status InitStack(SqStack* pS)
{
	pS->base = (SElemType*)malloc(STACK_INIT_SIZE * sizeof(SElemType));
	if (!pS->base)return ERROR;
	pS->top = pS->base;
	pS->stacksize = STACK_INIT_SIZE;
	return OK;
}
5.2判断是否可通,并返回可通的方向
//2.判断当前位置是否可通,并返回可通的最小方向,否则返回0
//通过判断下一个位置在迷宫中的性质(通路,墙,死路,访问过)
int Pass(MazeType maze, PosType pos)
{
	int i;
	for(i=1;i<=4;i++)
		if (isAccess(maze, pos,i))
		{
			return i;
		}
	return 0;
}
5.3将待入栈的元素设置指定值
//3.将待入栈的元素设置为特定值
void SetCurSElem(int ord, PosType pos, int di, SElemType* p)
{
	p->ord = ord;
	p->seat = pos;//同一结构体类型可以赋值
	p->di = di;
}
5.4插入元素e为新的栈顶元素
//4.插入元素e为新的栈顶元素(栈的基本操作)
Status Push(SqStack* pS, SElemType e)
{
	if (pS->top - pS->base >= pS->stacksize)//栈满,追加空间
	{
		pS->base = (SElemType*)realloc(pS->base, 
			(pS->stacksize + STACKINCREMENT) * sizeof(SElemType));
		if (!pS->base)return ERROR;
		pS->top = pS->base + pS->stacksize;
		pS->stacksize += STACKINCREMENT;
	}
	*pS->top++ = e;
	return OK;
}

5.4留下足迹,表示在当前路径中,并设置迷宫的相应位置为2

//5.在迷宫相应位置标记2,代表访问过
void FootPrint(MazeType* pMaze, PosType pos)
{
	pMaze->scene[pos.x][pos.y] = 2;
}
5.5判断是否到达出口
//6.判断是否到达出口(栈顶元素)
Bool isReach(MazeType maze, PosType pos)
{
	return pos.x == maze.end.x && pos.y == maze.end.y;
}
5.6返回下一个位置(坐标)
//7.返回下一个位置(坐标)
PosType NextPos(PosType pos, int i)
{
	PosType next = pos;
	switch (i)
	{
	case 1:next.y = pos.y + 1; break;
	case 2:next.x = pos.x + 1; break;
	case 3:next.y = pos.y - 1; break;
	case 4:next.x = pos.x - 1;
	}
	return next;
}
5.7死路,标记不可通,设置迷宫的相应位置为-1
//8.标记死路,将迷宫相应位置改为-1
void MarkPrint(MazeType* pMaze, PosType pos)
{
	pMaze->scene[pos.x][pos.y] = -1;
}
5.8判断是否为空栈
//9.判断是否栈空
Bool StackEmpty(SqStack S)
{
	return S.top == S.base;
}
5.9出栈,弹出一个栈顶元素
//10.弹出一个栈顶元素,用e返回其值,并返回OK;否则返回ERROR
Status Pop(SqStack* pS, SElemType* p)
{
	if (!StackEmpty(*pS))
	{
		*p = *--pS->top;
		return OK;
	}
	return ERROR;
}
5.10判断当前位置是否可通(通过判断下一个位置时墙、死路、还是访问过)
//11.判断当前位置的下一个位置是否可通
Bool isAccess(MazeType maze, PosType pos,int i)
{
	PosType next = NextPos(pos, i);
	return maze.scene[next.x][next.y] == 1;
}


​
5.11遍历栈,打印路径
//12.遍历栈,打印路径
Status StackTraverse(SqStack S)
{
	SElemType* p;
	p = S.base;
	while (p)
	{
		visit(*p++);
	}
	return OK;
}
5.12打印路径信息
//13.打印路径信息
void visit(SElemType e)
{
	printf("Step %d:(%d,%d),next:%d\n", e.ord, e.seat.x, e.seat.y, e.di);
}


测试结果

运行上述代码,如果迷宫中存在从起点到终点的路径,程序将打印出该路径的每一步。每一步包括步数、当前位置坐标以及下一步的方向(1为东,2为南,3为西,4为北)。如果迷宫中不存在路径,则打印“No path found.”。

总结

通过栈实现的迷宫路径搜索算法是一种深度优先搜索的变体。它利用栈来保存搜索过程中的状态,并在无法继续搜索时回溯到上一个状态。这种算法在解决迷宫问题时非常有效,并且可以通过调整搜索策略来优化性能。

说明

这个是《数据结构(C语言版)》严蔚敏里的算法,C代码实现。学习记录p47

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值