数据结构与算法——迷宫问题

课程名称:数据结构与算法

设计题目:迷宫问题

已知技术参数和设计要求:

问题描述:

以一个m*n的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍。迷宫问题要求求出从入口(1,1)到出口(m,n)的一条通路,或得出没有通路的结论。

基本要求:

首先实现一个以链表作存储结构的栈类型,然后编写一个求迷宫问题的非递归程序,求得的通路以三元组(ijd)的形式输出,其中:(ij)指示迷宫中的一个坐标, d表示走到下一坐标的方向。

测试数据:

迷宫用伪随机数产生程序产生。

左上角(1,1)为入口,右下(m,n)为出口。

选作内容:

1.编写递归形式的算法,求得迷宫中的所有可能的通路。

2.以方阵的形式输出迷宫及其通路迷宫中的所有可能的通路。

基本思路:

1.创建一个二维数组代表迷宫,另外在创建一个的等大且初值全为“0”的二维数组,用来在寻找通路的函数中记录位置。

2.创建一个栈结构体,用来存储路线(走过的点压进栈,走不通返回则弹栈)。

3.定义上、下、左、右、上左、上右、下左、下右八个遍历方向(如果是四个方向的话非常容易出现死路,且不符合实际)。

代码及相关注释如下:

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

#define size 100
#define M 100
#define N 100

typedef struct
{
	int x;//横
	int y;//纵
}position;

typedef struct stack
{
int row;//行
int col;//列
int dir;//方向
}date;

typedef struct//定义栈 
{
	date stack[size] ;
	int top;
}tstack;

position direction[8]={{-1,0},{1,0},{0,-1},{0,1},{-1,-1},{-1,1},{1,-1},{1,1}};//八个遍历方向 

int sum=0;
int maze[M][N];
int maze_2[M+2][N+2]={0};//等大全为0的数组 
int m,n;

void push(tstack*s,date x)//压栈 
{
	if(s->top==size-1)//从0开始,所以size-1 
	printf("栈满了");
	else
	{
		s->top++;
		s->stack[s->top]=x;//把x赋给top指向的栈顶 
	}
}

void pop(tstack*s)//弹栈 
{
	if(s->top==-1)//判断栈顶的值来判断是否为空栈 
	printf("栈空");
	else
	{
		s->top--;//弹出栈顶元素 
	}
}

void print_path(int sum,tstack s)
{
	int a;
	printf("第 %d 条通路:\n",sum);
	for(a=0;a<s.top;a++)
	printf("(%d,%d,%d)->",s.stack[a].row ,s.stack[a].col,s.stack[a+1].dir );//输出栈里的元素 ,三元坐标 
	printf("出口\n"); 
	printf("\n");	 
}

void path(int x,int y,tstack e)//寻找迷宫的通路 
{	
int i,a,b,c;
date t;//引用结构体date 
if(x==m&&y==n)//判断是否到(m,n)出口 
{
	sum++;
	print_path(sum,e);//调用打印迷宫(print_path)函数 
	}	
	else
	{
		for(i=0;i<8;i++)//遍历八个方向 
		{
			a=x+direction[i].x;//判断走向 
			b=y+direction[i].y;
			c=i;
			if(!maze[a][b]&&!maze_2[a][b])//可以走的路,相当于if(1&&1) 
			{
				t.row=a;
				t.col=b;
				t.dir=c;
				maze_2[a][b]=maze[a][b]=1;//走过的地方在maze和maze_2中标记为1 
				push(&e,t);//然后存到栈里面去 
				path(a,b,e);//在path函数自身调用path函数 ,获得点 
				maze_2[a][b]=maze[a][b]=0;//将位置清空,表示没有走过的路 
				pop(&e);//走不通的点,弹栈弹出走不通的点 
			}
		}
	}
}

/*主函数部分*/ 
int main()
{
int a,b;

tstack *s;//初始化栈 
s=(tstack *)malloc(sizeof(tstack));
s->stack[0].row =1;
s->stack[0].col=1;
s->top=0;

maze_2[1][1]=maze[1][1]=1;

printf("输入迷宫行数和列数:\n");
scanf("%d %d",&m,&n);

srand((unsigned)time(NULL));//随机迷宫 
for(a=0;a<m+2;a++)
{
	for(b=0;b<n+2;b++)
	{
		maze[a][b]=rand()%2;//只有0和1的随机迷宫
		if(a==m&&b==n) 
		{
		maze[a][b]=0;//出口设为0 
		maze[1][1]=0; //入口设为0 
	}
	}
}
for (a = 0; a < n + 2; a++) maze[0][a] = 1;//上 墙 (上下左右的墙用1代表,即为输出中的“#”) 
for (a = 0; a < m + 2; a++) maze[a][0] = 1;//左 墙 
for (a = 0; a < n + 2; a++) maze[m+ 1][a] = 1;//下 墙 
for (a = 0; a < m + 2; a++) maze[a][n + 1] = 1;//右 墙 
for (a = 0; a < n; a++) maze[m][a] = 1;

printf("随机迷宫:\n");
 for(a=0;a<m+2;a++)
{
	for(b=0;b<n+2;b++)
	{
	if (maze[a][b] == 1)
	printf("#");//“#”代表墙 
	else if(maze[a][b]==0)
	printf(" ");//“ ”代表可到到达的地方 
}
printf("\n");
}
 path(1,1,*s);//调用path函数得到通路 
return 0;
}

   注意:本代码仅供参考!

  • 15
    点赞
  • 161
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
程序在VC++ 6下顺利编译通过。 一、 实验目的: (1) 熟练掌握链栈的基本操作及应用。 (2) 利用链表作为栈的存储结构,设计实现一个迷宫的非递归程序。 二、实验内容: 【问题描述】 以一个m×n的方阵表示迷宫,0和1分别表示迷宫通路障碍。设计一个程序,对信任意设定的迷宫出一条从入口到出口的通路,或得出没有通路的结论。 【基本要求】 首先实现一个链表作存储结构的栈类型,然后编写一个迷宫的非递归程序。得的通路以三元组(i,j,d)的形式输出,其:(i,j)指示迷宫一个坐标,d表示走到下一坐标的方向。如:对于下列数据的迷宫,输出的一条通路为:(1,1,1),(1,2,2),(2,2,2),(3,2,3),(3,1,2),……。 【测试数据】 迷宫的测试数据如下:左上角(1,1)为入口,右下角(8,9)为出口。 1 2 3 4 5 6 7 8 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 1 1 0 1 0 1 1 1 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 0 0 0 1 0 1 1 1 0 0 0 0 0 0 以方阵形式输出迷宫及其通路。 输出: 请输入迷宫和宽:5 5 请输入迷宫内容: 0 1 1 0 0 0 0 1 1 0 1 0 0 1 1 1 0 0 1 0 1 1 0 0 0 迷宫的路径为 括号内的内容分别表示为(行坐标,列坐标,数字化方向,方向) (1,1,1,↓) (2,1,2,→) (2,2,1,↓) (3,2,1,↓) (4,2,2,→) (4,3,1,↓) (5,3,2,→) (5,4,2,→) (5,5,0,) 迷宫路径探索成功!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

蓝白杨

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

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

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

打赏作者

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

抵扣说明:

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

余额充值