迷宫问题C语言求解

迷宫:1-->通路     非1-->死路

简单迷宫 
0 0 0 0 0 0 
0 0 1 0 0 0 
0 0 1 0 0 0 
0 0 1 1 1 0 
0 0 1 0 1 1 

0 0 1 0 0 0

求解:①可以采用循环的方式。需要用到栈,从入口开始,往四个方向走,依次将走过的坐标点--入栈;如果走到“死路”,就出栈;--循环;最后栈中保存的就是出迷宫的路线。

求解:②可以采用递归的方式。每走一步,就把剩下的迷宫看成以下一步为入口的“新迷宫”,将走整个迷宫,化成走一个个“小迷宫”,这就是递归。走到出口,就“一路”返回。

多通路迷宫:通路间()带环 
0 0 0 0 0 0 
0 1 1 1 1 1 
0 1 0 0 0 0 
0 1 0 0 0 0 
0 1 1 1 1 1 

0 1 0 0 0 0 

求解:还是采用递归的方式:将当前步--入栈,然后向四周走;当四周都不能走时---出栈。

(1)为解决“带环”问题----找到最短出迷宫路径:在判断下一步可以(下一步的数大于当前的数)走后,就把下一步的数改为当前的数+1;这样在再次进入“环”后,不会在环里一直“转圈”。

(2)解决多通路问题:在找到一条“出路后”,不是直接退出,而是把每一条路都走一遍;所以开始从入口进,最后又会从入口出。

下面是代码:

maze.h

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

#define ROW 4
#define COL 4

int Maze[ROW][COL];


typedef struct Position
{
	int _x;
	int _y;
}Position;

typedef struct Stack 
{ 
	Position* _pos;
	int _top;      // 表示有效元素个数 表示栈顶位置 
	int _capacity; // 底层空间的总大小 
}Stack; 




void StackInit(Stack* s); 

// 入栈 
void StackPush(Stack* s, Position pos); 

// 出栈 
void StackPop(Stack* s); 

// 获取栈顶元素 
//pPos StackTop(Stack* s); 

// 有效元素的个数 
int StackSize(Stack* s); 

// 检测栈是否为空 
int StackEmpty(Stack* s);

//打印栈
void PrintfStack(Stack s);

//清空栈
void clearstack(Stack* s);




///迷宫问题函数
//判断入口是否有效
int IsEnterRight(Position enter);

//判断是否是出口
int IsExit(Position cur,Position enter);

//判断next是否可走
int IsNextPass(Position cur,Position next);

//保存路径
void saveshortpath(Stack* shortpath,Stack* path);


//走迷宫 
void passmaze(Position enter);                 //循环(栈)和递归走迷宫函数

//void passmaze(Position enter,Stack* shortpath);  //走复杂迷宫函数

maze.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "maze.h"





int Maze[ROW][COL]=
{
	{0,0,1,0},
	{0,1,1,1},
	{0,1,0,0},
	{0,1,0,0},
};
void StackInit(Stack* s)
{
	s->_pos=(Position*)malloc(sizeof(Position)*3);
	s->_capacity=3;
	s->_top=0;
}

// 入栈 
void StackPush(Stack* s,Position pos)
{
	Position* tmp;
	int newCapacity=s->_capacity*2;
	if(NULL==s)     //未初始化,退出
		return;
	if(s->_top==s->_capacity)             //如果栈已满,就扩容
	{
		tmp=(Position*)realloc(s->_pos,newCapacity*sizeof(Position));
		if(NULL==tmp)
		{
			printf("扩容失败\n");
			return;
		}
		s->_pos=tmp;
		s->_capacity=newCapacity;
	}
	s->_pos[s->_top]._x=pos._x;
	s->_pos[s->_top]._y=pos._y;
	s->_top++;
}

// 出栈 
void StackPop(Stack* s)
{
	if(NULL==s)
		return;
	if(0==s->_top)
		return;
	else 
		s->_top--;
}

// 获取栈顶元素 
Position StackTop(Stack* s)
{
	if(NULL==s)
		exit(EXIT_FAILURE);
	return s->_pos[s->_top-1];
}

// 有效元素的个数 
int StackSize(Stack* s)
{
	if(NULL==s)
		return -1;
	return s->_top;
}

// 检测栈是否为空 
int StackEmpty(Stack* s)
{
	if(NULL==s)
		exit(EXIT_FAILURE);
	if(0==s->_top)
		return 1;
	else
		return 0;
}

//打印栈
void PrintfStack(Stack s)
{
	int i=0; 
	if(0==s._top)
		return;
	printf("迷宫出口:");
	for (;i<s._top;i++)
	{
		printf("(%d %d)-->",s._pos[i]._x,s._pos[i]._y);
	}
	printf("\n");
}

//清空栈
void clearstack(Stack* s)
{
	s->_top=0;
}

//判出口
int IsExit(Position cur,Position enter)
{
	if((cur._x!=enter._x && cur._y!= enter._y)&& 
	   ( 0==cur._x || ROW-1==cur._x ||
		0==cur._y || COL-1==cur._y)
	  )             //cur在边界即为出口(cur入口要排除在外)
		return 1; 
	return 0;                 //cur暂不是出口
}

//判入口是否有效
int IsEnterRight(Position enter)
{
	if(0==enter._x || ROW-1==enter._x || 0==enter._y || COL-1==enter._y)      //enter在"边界"即为有效
		return 1;
	return 0;
}



// 对简单迷宫进行求解----只有一条通路,迷宫不带环 
//---- 用循环的方式求解简单迷宫问题
#if 0
void passmaze(Position enter)
{
	Stack s;
	Position cur,next;
	StackInit(&s);
	if(!IsEnterRight(enter))          //判断入口是否有效
	{
		printf("enter error!\n");
		return;
	}
	StackPush(&s,enter);              //把入口入栈
	while (!StackEmpty(&s))           //栈不为空,就继续
	{
		cur=StackTop(&s);
		Maze[cur._x][cur._y]=2;
		if(IsExit(cur,enter))          //判断当前位置是否是出口
		{
            PrintfStack(s);
			return;
		}
		//上
		next=cur;
		next._x-=1;
		if(1==Maze[next._x][next._y])   
		{
			StackPush(&s,next);           //next为 1 ,可以走-->入栈
			continue;
		}
		//左
		next=cur;
		next._y-=1;
		if(1==Maze[next._x][next._y])   
		{
			StackPush(&s,next);           //next为 1 ,可以走-->入栈
			continue;
		}
		//右
		next=cur;
		next._y+=1;
		if(1==Maze[next._x][next._y])   
		{
			StackPush(&s,next);           //next为 1 ,可以走-->入栈
			continue;
		}
		//下
		next=cur;
		next._x+=1;
		if(1==Maze[next._x][next._y])   
		{
			StackPush(&s,next);           //next为 1 ,可以走-->入栈
			continue;
		}

		else
		{
			Maze[cur._x][cur._y]=3;
			StackPop(&s);                //next这一步走错了,回退到上一步-->出栈
		}
	}
	printf("没有出口!\n");
}
#endif

// 用递归的方式求解简单迷宫问题
#if  1
int _passmaze(Position enter,Position cur)
{
	Position next;
	if(1==Maze[cur._x][cur._y])
	{
		Maze[cur._x][cur._y]=2;
		if(IsExit(cur,enter))          //判断当前位置是否是出口
			return 1;
		//上
		next=cur;
		next._x-=1;
		if(_passmaze(enter,next))   
			return 1;
		//左
		next=cur;
		next._y-=1;
		if(_passmaze(enter,next))   
			return 1;
		//右
		next=cur;
		next._y+=1;
		if(_passmaze(enter,next))   
			return 1;
		//下
		next=cur;
		next._x+=1;
		if(_passmaze(enter,next))   
			return 1;

		Maze[cur._x][cur._y]=3;
	}

	return 0;
}



void passmaze(Position enter)
{
	if(!IsEnterRight(enter))          //判断入口是否有效
	{
		printf("enter error!\n");
		return;
	}
	_passmaze(enter,enter);
}


#endif

//对复杂迷宫进行求解---迷宫中可能有多条通路,多条路径有可能构成环
#if 0
void _passmaze(Position enter,Position cur,Stack* path,Stack* shortpath)
{
	Position next;
	if(StackEmpty(path))
		Maze[cur._x][cur._y]=2;
	StackPush(path,cur);              //把入口入栈

	if(IsExit(cur,enter))          //判断当前位置是否是出口
	{
		if(StackEmpty(shortpath) || StackSize(path)<StackSize(shortpath))
			saveshortpath(shortpath,path);
		StackPop(path);
		return;
	}
	//上
	next=cur;
	next._x-=1;
	if(IsNextPass(cur,next))   
	{
		Maze[next._x][next._y]=Maze[cur._x][cur._y]+1;
		_passmaze(enter,next,path,shortpath);
	}
	//左
	next=cur;
	next._y-=1;
	if(IsNextPass(cur,next))   
	{
		Maze[next._x][next._y]=Maze[cur._x][cur._y]+1;
		_passmaze(enter,next,path,shortpath);
	}
	//右
	next=cur;
	next._y+=1;
	if(IsNextPass(cur,next))   
	{
		Maze[next._x][next._y]=Maze[cur._x][cur._y]+1;
		_passmaze(enter,next,path,shortpath);
	}
	//下
	next=cur;
	next._x+=1;
	if(IsNextPass(cur,next))   
	{
		Maze[next._x][next._y]=Maze[cur._x][cur._y]+1;
		_passmaze(enter,next,path,shortpath);
	}
	StackPop(path);                //next这一步走错了,回退到上一步-->出栈
}

void passmaze(Position enter,Stack* shortpath)
{
	Stack path;
	if(!IsEnterRight(enter))          //判断入口是否有效
	{
		printf("enter error!\n");
		return;
	}
	StackInit(&path);
	_passmaze(enter,enter,&path,shortpath);
}
//判断next是否可走
int IsNextPass(Position cur,Position next)
{
	if((1==Maze[next._x][next._y]) ||
		(Maze[cur._x][cur._y]<Maze[next._x][next._y]))
		return 1;
	return 0;
}

//保存路径
void saveshortpath(Stack* shortpath,Stack* path)
{
	int i=0;
	assert(path);
	if(0==path->_top)
		return;
	clearstack(shortpath);
	for (;i<path->_top;i++)
	{
		shortpath->_pos=path->_pos;
	}
	shortpath->_top=i;
} 

#endif

test.c

    

#define _CRT_SECURE_NO_WARNINGS 1
#include "maze.h"


int main()
{
	Position enter;
	Stack shortpath;
	int i=0,j=0;
	StackInit(&shortpath);

	enter._x=3;
	enter._y=1;
	//passmaze(enter,&shortpath);
	passmaze(enter);
	for (i=0;i<ROW;i++)
	{
		for (j=0;j<COL;j++)
		{
			printf("%d ",Maze[i][j]);
		}
		printf("\n");
	}
	PrintfStack(shortpath);
	return 0;
}

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
很抱歉,我是AI语言模型,无法直接运行或调试代码。但是我可以给你提供一些思路和参考,希望对你有帮助。 蓝桥杯迷宫问题可以使用深度优先搜索(DFS)或广度优先搜索(BFS)来解决。下面是使用DFS的思路: 1. 定义一个二维数组表示迷宫,0表示可以通过,1表示障碍物。 2. 定义一个二维数组表示已经访问过的位置,初始值都为0。 3. 从起点开始,按照上、右、下、左的顺序尝试走一步,如果能够走到新的位置且该位置没有被访问过,则标记为已经访问过并继续往下搜索,直到找到终点或者无法继续搜索为止。 4. 如果找到了终点,则输出路径;否则,返回上一步继续搜索。 下面是使用DFS的C语言代码示例: ```c #include <stdio.h> #define MAX_N 100 int maze[MAX_N][MAX_N]; int visit[MAX_N][MAX_N]; int path[MAX_N*MAX_N][2]; int n, m, sx, sy, tx, ty, flag = 0, top = 0; void dfs(int x, int y) { if (x == tx && y == ty) { flag = 1; return; } if (flag) return; if (x > 0 && maze[x-1][y] == 0 && !visit[x-1][y]) { visit[x-1][y] = 1; path[top][0] = x-1; path[top][1] = y; top++; dfs(x-1, y); top--; } if (y < m-1 && maze[x][y+1] == 0 && !visit[x][y+1]) { visit[x][y+1] = 1; path[top][0] = x; path[top][1] = y+1; top++; dfs(x, y+1); top--; } if (x < n-1 && maze[x+1][y] == 0 && !visit[x+1][y]) { visit[x+1][y] = 1; path[top][0] = x+1; path[top][1] = y; top++; dfs(x+1, y); top--; } if (y > 0 && maze[x][y-1] == 0 && !visit[x][y-1]) { visit[x][y-1] = 1; path[top][0] = x; path[top][1] = y-1; top++; dfs(x, y-1); top--; } } int main() { scanf("%d%d", &n, &m); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { scanf("%d", &maze[i][j]); visit[i][j] = 0; } } scanf("%d%d%d%d", &sx, &sy, &tx, &ty); visit[sx][sy] = 1; path[top][0] = sx; path[top][1] = sy; top++; dfs(sx, sy); if (flag) { for (int i = 0; i < top; i++) { printf("(%d,%d)\n", path[i][0], path[i][1]); } } else { printf("No path found.\n"); } return 0; } ``` 上述代码中,使用了一个全局变量`flag`来标记是否已经找到终点,使用一个全局变量`top`来记录当前已经搜索到的位置在路径中的下标。在搜索时,每访问一个新位置,都把该位置的坐标存储到`path`数组中,并将`top`加1。如果找到了终点,则输出路径;否则,返回上一步继续搜索。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值