迷宫问题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;
}

    原文作者:迷宫问题
    原文地址: https://blog.csdn.net/qq_33279168/article/details/80056896
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞