三种迷宫小算法

1.简单迷宫(只有一条通路或者是有几条通路(不带环))

SimpleMaze.h

#ifndef AAA
#define AAA

#include<stdio.h>
#include<assert.h>

#define NUMBER 20
#define ROW 6
#define COL 6
typedef int DataType;

//地图
typedef struct Maze
{
	int map[ROW][COL];
}Maze;

//坐标
typedef struct Coordinate
{
	DataType x;
	DataType y;
}Coordinate;

//栈
typedef struct Stack
{
	Coordinate a[NUMBER];
	int top;
}Stack;

void Cpmap(DataType a[ROW][COL], Maze *q);
void InitStack(Stack *cur);
void WalkMaze(Coordinate entry, Maze *q, Stack *cur);
void WalkMaze2(Coordinate entry, Maze *q, Stack *cur);
void PrintMaze(Maze q);

#endif //AAA

MazeFunc.c

#include"SimpleMaze.h"

//地图  
void Cpmap(DataType a[ROW][COL], Maze *q)
{
   int i = 0;
   int j = 0;
   for(i = 0; i < ROW; i++)
   {
	   for(j = 0; j < COL; j++)
	   {
		   q->map[i][j] = a[i][j];
	   }
   }
}
//初始化栈
void InitStack(Stack *cur)
{
	assert(cur);
	cur->top = 0;
}
//入栈
void PushStack(Stack *cur, Coordinate entry)
{
	assert(cur);
	cur->a[cur->top] = entry;
	cur->top++;
}
//出栈
void PopStack(Stack *cur)
{
	assert(cur);
	cur->top--;
}
//判断栈是否为空
int EmptyStack(Stack *cur)
{
	assert(cur);
	return 0 == cur->top;
}
//取栈顶的元素
Coordinate TopCellStack(Stack *cur)
{
	assert(cur);
	if(cur->top != 0)
		return cur->a[cur->top-1];
}
//判断该坐标是否是通路
int Passage(Maze *q,int x, int y)
{
	//首先判断坐标是否在有效的范围内
	if(x < ROW && x >= 0 && y < COL && y >= 0)
	{
		if(q->map[x][y] == 1)
		{
			return 1;
		}
	}
	return 0;
}
//判断是否是出口
int ExitMaze(Coordinate ret, Coordinate entry)
{
	if((ret.x == 0 || ret.x == ROW-1 || ret.y == 0 || ret.y == COL-1)&& ret.x != entry.x && ret.y != entry.y)
		return 1;
	return 0;
}
//打印迷宫
void PrintMaze(Maze q)
{
	int i = 0;
	int j = 0;
	for(i = 0; i < ROW; i++)
	{
		for(j = 0; j < COL; j++)
		{
			printf("%d ", q.map[i][j]);
		}
		printf("\n");
	}
}
//简单的单通路迷宫

//入口--》走迷宫
//循环下面操作,直到找到出口/站空时退出
//    获取栈顶元素
//    每走一步,标记,判断是否到出口的位置,入栈
//    上:检测tmp的上方是否为通路
         //是:向上走--》入栈;continue
//     下:检测tmp的下方是否为通路
         //是:向下走--》入栈
//     左:检测tmp的左方是否为通路
         //是:向左走--》入栈
//     右:检测tmp的右方是否为通路
        //是:向右走--》入栈
//     当前步走错--》回退--》出栈
void WalkMaze(Coordinate entry, Maze *q, Stack *cur)
{
	Coordinate ret = entry;
	assert(cur && q);
	//首先标记入口节点,用2来表示已经走过的节点
	q->map[entry.x][entry.y] = 2;
	PushStack(cur,entry);
	while(!EmptyStack(cur))
	{
		Coordinate tmp = {0};
		ret = TopCellStack(cur);
		//到达迷宫的出口
		if(ExitMaze(ret, entry))
		{
			break;
		}
		tmp = ret;
		//上面是通路
		if(Passage(q,tmp.x-1, tmp.y))
		{
			tmp.x -= 1;
			PushStack(cur,tmp);
			q->map[tmp.x][tmp.y] = 2;
			continue;
		}
		//下面是通路
		if(Passage(q,tmp.x+1, tmp.y))
		{
			tmp.x += 1;
			PushStack(cur,tmp);
			q->map[tmp.x][tmp.y] = 2;
			continue;			
		}
		//左边是通路
		if(Passage(q,tmp.x,tmp.y-1))
		{
			tmp.y -= 1;
			PushStack(cur,tmp);
			q->map[tmp.x][tmp.y] = 2;
			continue;
		}
		//右边是通路
		if(Passage(q, tmp.x, tmp.y+1))
		{
			tmp.y += 1;
			PushStack(cur,tmp);
			q->map[tmp.x][tmp.y] = 2;
			continue;
		}
		//如果上下左右都不可以代表此处是一个死胡同,立刻出栈
		PopStack(cur);
		//用3来表示出栈的地址
		q->map[tmp.x][tmp.y] = 3;
	}
}
//多条通路的迷宫
//当走到第一条路的出口时,不要立即退出
//而是开始出栈返回,寻找第二条路,
//直到栈为空时停止
void WalkMaze2(Coordinate entry, Maze *q, Stack *cur)
{
	Coordinate ret = entry;
	assert(cur && q);
	//首先标记入口节点,用2来表示已经走过的节点
	q->map[entry.x][entry.y] = 2;
	PushStack(cur,entry);
	while(!EmptyStack(cur))
	{
		Coordinate tmp = {0};
		ret = TopCellStack(cur);
		tmp = ret;
		//到达迷宫的出口时,先打印一条路径,然后原路返回
		if(ExitMaze(ret, entry))
		{
			PrintMaze(*q);
			printf("\n");
			q->map[tmp.x][tmp.y] = 3;			
		}
		//上面是通路,向上走
		if(Passage(q,tmp.x-1, tmp.y))
		{
			tmp.x -= 1;
			PushStack(cur,tmp);
			q->map[tmp.x][tmp.y] = 2;
			continue;
		}
		//下面是通路,向下走
		if(Passage(q,tmp.x+1, tmp.y))
		{
			tmp.x += 1;
			PushStack(cur,tmp);
			q->map[tmp.x][tmp.y] = 2;
			continue;			
		}
		//左边是通路,向左走
		if(Passage(q,tmp.x,tmp.y-1))
		{
			tmp.y -= 1;
			PushStack(cur,tmp);
			q->map[tmp.x][tmp.y] = 2;
			continue;
		}
		//右边是通路, 向右走
		if(Passage(q, tmp.x, tmp.y+1))
		{
			tmp.y += 1;
			PushStack(cur,tmp);
			q->map[tmp.x][tmp.y] = 2;
			continue;
		}
		//如果上下左右都不可以代表此处是一个死胡同,代表此时走错了,立刻出栈
		PopStack(cur);
		//用3来标记走错的路径
		q->map[tmp.x][tmp.y] = 3;
	}
}

Maze.c

#include"SimpleMaze.h"

void Text()
{
	Stack cur = {0};
	Coordinate entry;
	Maze m = {0};
	DataType a[ROW][COL] = {
	0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0,
	0, 1, 1, 1, 1, 1,
	0, 1, 0, 0, 0, 0,
	0, 1, 1, 1, 1, 1,
	0, 1, 0, 0, 0, 0
	};
	entry.x = 5;
	entry.y = 1;
	InitStack(&cur);
	Cpmap(a, &m);
    WalkMaze(entry, &m, &cur);
	PrintMaze(m);
}

int main()
{
	Text();
	return 0;
}

2.带环的迷宫

Maze.h

#ifndef AAA
#define AAA

#include<stdio.h>
#include<assert.h>

#define NUMBER 20
#define ROW 6
#define COL 6
typedef int DataType;

//地图
typedef struct Maze
{
	int map[ROW][COL];
}Maze;

//坐标
typedef struct Coordinate
{
	DataType x;
	DataType y;
}Coordinate;

//栈
typedef struct Stack
{
	Coordinate a[NUMBER];
	int top;
}Stack;

void StackInit(Stack *ret);
void ArrayInit(DataType a[ROW][COL], Maze *m);
void StackPop(Stack *cur);
int IsPass(Maze* m,Coordinate next,Coordinate ret);
int IsExport( Coordinate  next, Coordinate entry);
void  StackPush(Stack *cur, Coordinate ret);
void printMaze(Maze m);
void MazeRoute(Maze *m, Coordinate entry, Coordinate ret, Stack *cur, Stack *shortpath);

#endif //AAA

MazeFunc.c

#include"Maze.h"

//栈的初始化
void StackInit(Stack *ret)
{
	assert(ret);
	ret->top = 0;
}
//初始化地图
void ArrayInit(int a[ROW][COL], Maze *m)
{
	int i = 0;
	int j = 0;
	for(i = 0; i < ROW; i++)
	{
		for(j = 0; j < COL; j++)
		{
			m->map[i][j] = a[i][j];
		}
	}
}
//出栈
void StackPop(Stack *cur)
{
	assert(cur);
	if((cur)->top == 0)
	{
		printf("栈空了\n");
		return;
	}
	(cur)->top--;
}
//是否是通路
int IsPass(Maze* m,Coordinate next,Coordinate ret)
{
	if(m->map[next.x][next.y] == 1 || m->map[next.x][next.y] > m->map[ret.x][ret.y])
	{
		return 1;
	}
	return 0;
}
//判断是否是出口
int IsExport( Coordinate  next, Coordinate entry)
{
	if(next.x == 0 || next.x == ROW-1 || next.y == 0 || next.y == COL-1)
	{
		if(next.x != entry.x && next.y != entry.y)
			return 1;
	}
	return 0;
}
//入栈
void  StackPush(Stack *cur, Coordinate ret)
{
	assert(cur);
	cur->a[cur->top] = ret;
	cur->top++;
}
//打印
void printMaze(Maze m)
{
	int i = 0;
	int j = 0;
	for(i = 0; i < ROW; i++)
	{
		for(j = 0; j < COL; j++)
		{
			printf(" %d ", m.map[i][j]);
		}
		printf("\n");
	}
}
//迷宫路线
void MazeRoute(Maze *m, Coordinate entry, Coordinate ret, Stack *cur, Stack *shortpath)
{
	Coordinate next = ret;
	if(cur->top == 0)
		m->map[entry.x ][entry.y] = 2;
	//判断坐标是否合格
	if(!(ret.x >= 0 && ret.x < ROW && ret.y >= 0 && ret.y < COL))
	{
		printf("坐标不合理\n");
		return ;
	}
	//判断是否是出口
	if(IsExport(next, entry))
	{
		int i = 0;
		StackPush(cur, ret);
		if(shortpath->top == 0 || (shortpath->top > cur->top && shortpath->top))
		{
			for(i = 0; i < cur->top; i++)
			{
				shortpath->a[i] = cur->a[i];
			}
		}
		shortpath->top = cur->top;
		StackPop(cur);
		return ;
	}
		StackPush(cur, ret);
	//上
	next = ret;
	next.x -= 1;
	if(IsPass(m, next, ret))
	{
		m->map[next.x][next.y] = m->map[ret.x][ret.y]+1;
		MazeRoute(m, entry, next, cur, shortpath);
	}
	//下
	next = ret;
	next.x += 1;
	if(IsPass(m, next, ret))
	{
		m->map[next.x][next.y] = m->map[ret.x][ret.y]+1;
		MazeRoute(m, entry, next, cur, shortpath);
	}
	//左
	next = ret;
	next.y -= 1;
	if(IsPass(m, next, ret))
	{
		m->map[next.x][next.y] = m->map[ret.x][ret.y]+1;
		MazeRoute(m, entry, next, cur, shortpath);
	}
	//右
	next = ret;
	next.y += 1;
	if(IsPass(m, next, ret))
	{
		m->map[next.x][next.y] = m->map[ret.x][ret.y]+1;
		MazeRoute(m, entry, next, cur, shortpath);
	}
	StackPop(cur);
}

Maze.c

#include"Maze.h"

void Text()
{
	Stack cur;
	Stack shortpath;
	Coordinate entry;
	Maze m;
	DataType a[ROW][COL] = {
	0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0,
	0, 1, 1, 1, 0, 0,
	0, 1, 0, 1, 0, 0,
	0, 1, 1, 1, 1, 1,
	0, 1, 0, 0, 0, 0
	};
	entry.x = 5;
	entry.y = 1;
	StackInit(&cur);
	StackInit(&shortpath);
	ArrayInit(a, &m);
	MazeRoute(&m, entry, entry, &cur, &shortpath);
	printMaze(m);
}

int main()
{
	Text();
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值