C_有趣的栈的寻路算法(非最优解决)

1.思路分析

我们先要输入迷宫的大小,和迷宫的地图,用1代表墙和已经走过的位置,0代表可以走的路。

注意:这里走过的位置也要将数据改为1,否则可能出现打圈的情况

在这里插入图片描述

如图,如果我们不把走过的地方都变成1,则序号5可能会走到序号4的位置上造成打圈

每当我们遇到可以走的位置时,先把此时的位置入栈保存,再将位置发生改变。当我们遇到周围都是死路的时候,则先回到原来的位置,在出栈回退

2.函数实现

全局变量定义

我们要保存的是坐标,先创立坐标结构体

#include<stdio.h>
#include<stdlib.h>

//数字1表示为墙或已经走过的位置,0表示可以走的位置.地图就是个二维数组

typedef struct pos //运动位置(行列)
{
	int row;
	int col;
}pos;

pos PosStack[100];//存放每次寻路的坐标(数组栈)

int StackTop = -1;//栈顶标记

生成迷宫函数

这里要自动向输入的迷宫添加边框

//生成迷宫

int** CreatArray(int row, int col)
{
	int** map = (int**)malloc(sizeof(int*)*row);
	//row行,每行放col个int数据
	for (int i = 0; i < row; i++)
	{
		map[i] = (int*)malloc(sizeof(int)*col);
		//每行有col个int
	}
	return map;
}

int**map;//全局变量存地图
int n;//地图大小

void CreatMap()
{
	printf("输入迷宫大小\n");
	scanf("%d",&n);
	map = CreatArray(n + 2, n + 2);//加上前后边框
	//输入迷宫(用户输入,这里不采用随机数生成)
	printf("输入迷宫结构\n");
	//加了边框,所以for循环从1开始
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
		{
			scanf("%d", &map[i][j]);
		}
	}
	//加边框
	for (int i = 0; i < n + 2; i++)
	{
		map[0][i] = 1;
		map[n + 1][i] = 1;
		map[i][0] = 1;
		map[i][n + 1] = 1;
	}
}

打印路径函数

//打印路径(因为栈是后入先出,所以正常打印的路径是反的,我们采用正序打印数组,这样路径就正常了)

void Print()
{
	printf("寻路路径为:\n");
	//正序打印数组
	if (StackTop == -1)//空栈
	{
		printf("没有可以找到的路径\n");
	}
	else
	{
		pos tmp;
		for (int i = 0; i <= StackTop; i++)
		{
			tmp = PosStack[i];
			printf("(%d,%d)-->",tmp.row,tmp.col);
		}
		printf("(%d,%d)\n",n,n);//(n.n)设计为终点
	}
}

寻路函数

因为每个位置都有4个位置可以移动,这里将位置放到结构体中

用变化量来形容其移动的位置

eg:向右移动行序号不变,列序号+1

每一次出栈的时候一定要将标记方向的beginpos还原为0让他在从第一个方向开始试,不会重复,因为不合理的位置已经被我们变成0了

当找到路径时返回1表示找到了
找不到返回0

//寻找路径
int findRow()
{
	//每一次寻找路径有四个方向我们用一个结构体数组储存
	pos offSet[4] = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
	//分别表示为右,下,左,上方向走的坐标偏移量
	//设定第一次出发的起点,并且将其在地图上的数字改为1,证明走过这里
	pos begin = { 1, 1 };
	map[1][1] = 1;
	int beginPos = 0;//开始方向为向右走
	int endPos = 3;//终止方向为向上走
	//设终点坐标为(n,n)
	while (begin.row != n || begin.col != n)//没有到终点
	{
		//记录变化后的坐标,看看能不能走
		int ChangeRow = 0; int ChangeCol = 0;
		while (beginPos <= endPos)//还有方向时
		{
			ChangeRow = begin.row + offSet[beginPos].row;
			//原坐标+偏移值
			ChangeCol = begin.col + offSet[beginPos].col;
			if (map[ChangeRow][ChangeCol] == 0)//可以移动
			{
				break;//跳出修改begin的坐标
			}
			else
			{
				++beginPos;//找下一个坐标
			}
		}
		if (beginPos <= endPos)//找到了可以移动的位置了
		{
			++StackTop;
//先把坐标入栈了再修改到下一个坐标,
//并且把下一个坐标的地图数据改为1(堵上)
			PosStack[StackTop] = begin;
			begin.row = ChangeRow;
			begin.col = ChangeCol;
			map[ChangeRow][ChangeCol] = 1;
			//起始方向又从0开始
			beginPos = 0;
		}
		else//出栈回退
		{
			if (StackTop == -1)//退到开头。没有路可以走
				return 0;
			else
			{
				begin = PosStack[StackTop];//回到前一个位置
				StackTop--;//出栈
				beginPos = 0;
//之前走过的位置已经被堵上了,所以beginePos可以从0开始,
//但是这样之前走过的方向还要判断一次,效率下降
			}
		}
	}
	return 1;//找到路径了
}

3.测试代码

测试地图

1.地图大小为4

地图信息为

0 1 0 1
0 0 0 1
1 0 1 1
1 0 0 0

2.地图大小为4

0 1 0 1
0 0 0 1
1 0 1 1
1 0 0 1

int main()
{
	CreatMap();
	if (findRow())//找到返回1
	{
		Print();
	}
	else
	{
		printf("没有找到路径\n");
	}
	return 0;
}

运行结果为
在这里插入图片描述

在这里插入图片描述

4.完整代码

代码位置

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
#include<stdlib.h>

//数字1表示为墙或已经走过的位置,0表示可以走的位置.地图就是个二维数组

typedef struct pos //运动位置(行列)
{
	int row;
	int col;
}pos;

pos PosStack[100];//存放每次寻路的坐标(数组栈)

int StackTop = -1;//栈顶标记

//生成迷宫

int** CreatArray(int row, int col)
{
	int** map = (int**)malloc(sizeof(int*)*row);//row行,每行放col个int数据
	for (int i = 0; i < row; i++)
	{
		map[i] = (int*)malloc(sizeof(int)*col);//每行有col个int
	}
	return map;
}

int**map;//全局变量存地图
int n;//地图大小

void CreatMap()
{
	printf("输入迷宫大小\n");
	scanf("%d",&n);
	map = CreatArray(n + 2, n + 2);//加上前后边框
	//输入迷宫(用户输入,这里不采用随机数生成)
	printf("输入迷宫结构\n");
	//加了边框,所以for循环从1开始
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
		{
			scanf("%d", &map[i][j]);
		}
	}
	//加边框
	for (int i = 0; i < n + 2; i++)
	{
		map[0][i] = 1;
		map[n + 1][i] = 1;
		map[i][0] = 1;
		map[i][n + 1] = 1;
	}
}

//打印路径(因为栈是后入先出,所以正常打印的路径是反的,我们采用正序打印数组,这样路径就正常了)

void Print()
{
	printf("寻路路径为:\n");
	//正序打印数组
	if (StackTop == -1)//空栈
	{
		printf("没有可以找到的路径\n");
	}
	else
	{
		pos tmp;
		for (int i = 0; i <= StackTop; i++)
		{
			tmp = PosStack[i];
			printf("(%d,%d)-->",tmp.row,tmp.col);
		}
		printf("(%d,%d)\n",n,n);//(n.n)设计为终点
	}
}

//寻找路径
int findRow()
{
	//每一次寻找路径有四个方向我们用一个结构体数组储存
	pos offSet[4] = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };//分别表示为右,下,左,上方向走的坐标偏移量
	//设定第一次出发的起点,并且将其在地图上的数字改为1,证明走过这里
	pos begin = { 1, 1 };
	map[1][1] = 1;
	int beginPos = 0;//开始方向为向右走
	int endPos = 3;//终止方向为向上走
	//设终点坐标为(n,n)
	while (begin.row != n || begin.col != n)//没有到终点
	{
		//记录变化后的坐标,看看能不能走
		int ChangeRow = 0; int ChangeCol = 0;
		while (beginPos <= endPos)//还有方向时
		{
			ChangeRow = begin.row + offSet[beginPos].row;//原坐标+偏移值
			ChangeCol = begin.col + offSet[beginPos].col;
			if (map[ChangeRow][ChangeCol] == 0)//可以移动
			{
				break;//跳出修改begin的坐标
			}
			else
			{
				++beginPos;//找下一个坐标
			}
		}
		if (beginPos <= endPos)//找到了可以移动的位置了
		{
			++StackTop;//先把坐标入栈了再修改到下一个坐标,并且把下一个坐标的地图数据改为1(堵上)
			PosStack[StackTop] = begin;
			begin.row = ChangeRow;
			begin.col = ChangeCol;
			map[ChangeRow][ChangeCol] = 1;
			//起始方向又从0开始
			beginPos = 0;
		}
		else//出栈回退
		{
			if (StackTop == -1)//退到开头。没有路可以走
				return 0;
			else
			{
				begin = PosStack[StackTop];//回到前一个位置
				StackTop--;//出栈
				beginPos = 0;
			//之前走过的位置已经被堵上了,所以beginePos可以从0开始,但是这样之前走过的方向还要判断一次,效率下降
			}
		}
	}
	return 1;//找到路径了
}

int main()
{
	CreatMap();
	if (findRow())//找到返回1
	{
		Print();
	}
	else
	{
		printf("没有找到路径\n");
	}
	return 0;
}
  • 8
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NUC_Dodamce

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值