精华内容
下载资源
问答
  • 迷宫求解 设计一个迷宫求解程序要求如下 以M N表示长方阵表示迷宫求出一条从入口到出口的通路或得出没有通路的结论 能任意设定的迷宫 选作如果有通路列出所有通路 提示 以一个二维数组来表示迷宫0和1分别表示迷宫中...
  • C语言 迷宫求解 自己结合数据结构课本写的,还有问题,待修改~
  • 数据结构 C语言 迷宫问题求解 栈 针对严蔚敏 吴伟民编著的数据结构(C语言版)中讲到栈的时候,会有一个迷宫求解的实验题,我写了一下,然后希望对别人有帮助……运行环境visual studio 2012
  • c语言迷宫问题求解

    2013-11-28 15:44:43
    两百行左右的代码,可以根据自己的需求进行修改,给对迷宫有疑惑的朋友一个参考。
  • C语言堆栈求解迷宫问题 问题如下: 实现如下迷宫的自动寻路,以圆圈为迷宫入口,以五角星为迷宫出口,打印出完整的走迷宫路径。 为了表示迷宫,我们设置一个二维数组mg,其中每个元素代表一个方位的状态,我们定义0...

    问题如下:

    实现如下迷宫的自动寻路,以圆圈为迷宫入口,以五角星为迷宫出口,打印出完整的走迷宫路径。
    在这里插入图片描述为了表示迷宫,我们设置一个二维数组mg,其中每个元素代表一个方位的状态,我们定义0为通路,1为墙,-1为已走过的路,通过堆栈保存当前路径,找到一条可行的路径。

    算法如下:

    将入口(xi,yi)进栈并将其初始方位向量di设置为-1:mg[xi][yi]=-1;
    while(栈不空)
    {	取栈顶方块并判断是否为出口
    	若是出口则打印路径
    	return true;
    	free(s);
    	若不是则查找当前块的下一个相邻可走方块;
    	if(找到一个)
    	{
    		该方块为(i1,j1),栈顶方块对应方位更改为di;
    		找到的方块进栈;
    		mg[i1][j1]=-1;
    	}
    	if(没有找到)
    		将当前方块退栈;
    		//注意退栈后不能将此方块状态置零,否则会陷入死循环
    }
    return false;
    

    代码实现:

    #include<stdio.h>
    #include<stdlib.h>//记住这个头文件,malloc函数和free函数都离不开它
    #define MaxSize 100//定义顺序栈最大空间
    typedef struct{
    	int i;//当前方块的行号
    	int j;//当前方块的列号
    	int di;//方块方向属性
    }Box;//定义路径属性
    typedef struct{
    	Box data[MaxSize];//栈保存当前路径
    	int top;
    }sqstack;//顺序栈
    int mg[10][10]=//地图
    {{1,1,1,1,1,1,1,1,1,1},
     {1,0,0,1,0,0,0,1,0,1},
     {1,0,0,1,0,0,0,1,0,1},
     {1,0,0,0,0,1,1,0,0,1},
     {1,0,1,1,1,0,0,0,0,1},
     {1,0,0,0,1,0,0,0,0,1},
     {1,0,1,0,0,0,1,0,0,1},
     {1,0,1,1,1,0,1,1,0,1},
     {1,1,0,0,0,0,0,0,0,1},
     {1,1,1,1,1,1,1,1,1,1}};
    bool push(sqstack * &s,Box e)//压栈
    {
    	if(s->top==MaxSize-1)
    		return false;
    	s->top++;
    	s->data[s->top]=e;
    	return true;
    }
    bool pop(sqstack * &s,Box &e)//退栈
    {
    	if(s->top==-1)
    		return false;
    	e=s->data[s->top];
    	s->top--;
    	return true;
    }
    bool mgpath(int xi,int yi,int xe,int ye)//求解路径为(xi,yi)->(xe,ye)
    {	
    	sqstack *s;//定义栈s
    	s=(sqstack * )malloc(sizeof(sqstack));
    	s->top=-1;//初始化栈顶指针
    	Box e;
    	mg[xi][yi]=-1;//将起点压栈并将状态记录为-1(已走)
    	e.i=xi;e.j=yi;e.di=-1;
    	push(s,e);
    	mg[xi][yi]=-1;
    	while(s->top!=-1)//栈不空时循环
    	{
    	e=s->data[s->top];
    	if(e.i==xe&&e.j==ye)//找到出口,输出该路径
    	{
    		printf("这是一条路径:\n");
    		for(int k=0;k<=s->top;k++)
    			{
    			printf("(%d,%d) ",s->data[k].i,s->data[k].j);
    			if((k+1)%5==0)
    			printf("\n");
    			}
    		free(s);
    		return true;//输出一条路径后返回true并销毁数据栈
    	}
    	int i,j,di;
    	i=e.i;j=e.j;di=-1;
    	int x=i,y=j;
    	while(di<=3)//不是出口则继续查找
    	{
    	di++;
    	if(di==0)
    		{
    			x=i-1;
    			y=j;
    		}
    		else if(di==1)
    		{
    			x=i;
    			y=j+1;
    		}
    		else if(di==2)
    		{
    			x=i+1;
    			y=j;
    		}
    		else
    		{
    			x=i;
    			y=j-1;
    		}
    	if(mg[x][y]==0)//找到相邻可走方块
    		break; 
    	}
    	if(mg[x][y]==0)
    	{
    	s->data[s->top].di=di;//修改原栈顶元素di值
    	e.i=x;e.j=y;e.di=-1;
    	push(s,e);//相邻可走方块e进栈
    	mg[x][y]=-1;//将状态记录为-1(已走),防止重复
    	}
    	else
    	{
    	pop(s,e);//没有路径可走,将当前方块退栈 
    	//mg[e.i][e.j]=0;//注意这里我专门注释掉的部分,不可以置0
    	}
    	}
    	free(s);
    	return false;//无路可走,销毁栈 
    }
    int main()
    {
    	if(!mgpath(1,1,8,8))
    		printf("该迷宫无解!");
    	return 0;
    } 
    

    实现结果:

    在这里插入图片描述

    谢谢观看

    展开全文
  • [color=#FF0000][size=18px]//C语言迷宫求解 求解函数执行还有问题 大家帮忙看下啊,拜托了,很急~[/size][/color] #include<stdio.h> #include<stdlib.h> #include<malloc.h> #include<...
  • 主要为大家详细介绍了C语言数据结构之迷宫求解问题,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • margin-right:0pt">求解迷宫问题,以一个M*N的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍,设计算法,对任意设定的迷宫,求从入口到出口的路径并以方阵形式显示。 ; margin-...
  • C语言迷宫问题递归和非递归求解,手动或者自动生成迷宫均可
  • C语言求解迷宫问题

    2019-11-25 00:33:50
    C语言求解迷宫问题 #include <stdio.h> #include <stdlib.h> #define c 6 //宽 #define d 8 //长 int e;//初始x坐标 int f;//初始y坐标 int g;//终点x坐标 int h;//终点y坐标 char mizu[c][d];...

    用C语言求解迷宫问题

    #include <stdio.h>
    #include <stdlib.h>
    #define c 6 //宽 
    #define d 8 //长 
    int e;//初始x坐标 
    int f;//初始y坐标 
    int g;//终点x坐标 
    int h;//终点y坐标 
     char mizu[c][d];
    int flag[d][c] = {0} ;      
    typedef int TypeData ;
    typedef struct node{
     TypeData datax ;//x
     TypeData datay ;//y
     struct node* next ;
    }Node , *LinkList ; 
     
    typedef struct stack{
     LinkList top ;
    }STACK ;
    //************************函数声明******************************
    int stackInit(STACK* s ) ;
    int pushStack(STACK* s ,TypeData x , TypeData y) ;//压栈 
    void popStack(STACK* s , TypeData* x , TypeData* y) ;//出栈 
    int isStackEmpty(STACK* s) ;
    int mizePath(STACK* s ,TypeData end_x , TypeData end_y ) ;
    int passMizu(TypeData x , TypeData y ) ;
    //********************************************************** 
     
    //链栈的初始化 
    int stackInit(STACK* s )
    {
     LinkList p = (LinkList)malloc(sizeof(Node)) ;
     if(!p)   return -1 ;
     p->next = NULL ;
     p->datax = -1 ;  
     p->datay = -1 ;
     s->top = p ;
     return 1 ;
    }
    //入栈操作
    int pushStack(STACK* s ,TypeData x , TypeData y)
    {
     LinkList p = (LinkList)malloc(sizeof(Node)) ;
     if(!p)   return -1 ;  //分配内存失败
     p->datax = x ;
     p->datay = y ;
     p->next = s->top ;
     s->top = p ; 
     return 1 ;
    } 
    //出栈的操作
    void popStack(STACK* s , TypeData* x , TypeData* y)
    {
     LinkList p = s->top ;
     s->top = p->next ;
     (*x) = p->datax ;
     (*y) = p->datay ;
     free(p) ;
    }
    //判断栈是否为空 
    //1 空  0 不空 
    int isStackEmpty(STACK* s)
    {
     if(s->top->datax == -1)  //栈空 
      return 1 ;
     return 0 ; 
    }
    //判断该位置是否可通 
    int passMizu(TypeData x , TypeData y )
    {
     if((x > (d-1))||(y > (c-1)))
      return 0 ;  //越界不可通
     if(mizu[y][x]) 
      return 0 ;  //该位置是墙,不可通
     if(flag[y][x])   
      return 0 ;  //该坐标已经被占用,不能通过 
     return 1 ;    
    }
    //找到最佳路径
    //end_x , end_y为结束的坐标
    //上 、右、下、左寻找方式 
    int mizePath(STACK* s ,TypeData end_x , TypeData end_y ) 
    {
     pushStack(s , e ,f) ; //初始坐标压栈 
     TypeData nowx = e , nowy = f ; 
     flag[nowx][nowy] = 1 ;  //该坐标已经被占用不能再通过 
     while(!isStackEmpty(s)) //当栈不空的时候 
     {
      if((nowx == g)&&(nowy == h))
      {
       return 1 ;
      } 
    
      if(passMizu(nowx , nowy-1))   //先向上寻找
      {
       nowy = nowy - 1 ; //坐标更改 
       pushStack(s , nowx , nowy) ;  //把该坐标压栈
        flag[nowy][nowx] = 1 ;  //该坐标已经被占用不能再通过
      }
      else  if(passMizu(nowx+1 , nowy)) //向右寻找   
      {
       nowx = nowx + 1 ; 
       pushStack(s , nowx , nowy) ;  //把该坐标压栈
       flag[nowy][nowx] = 1 ;  //该坐标已经被占用不能再通过
      } 
      else if(passMizu(nowx , nowy+1)) //向下寻找 
      {
       nowy = nowy + 1 ; 
       pushStack(s , nowx , nowy) ;  //把该坐标压栈
       flag[nowy][nowx] = 1 ;  //该坐标已经被占用不能再通过
      }
      else if(passMizu(nowx-1 , nowy)) //向左寻找 
      {
       nowx = nowx - 1 ; 
       pushStack(s , nowx , nowy) ;  //把该坐标压栈
       flag[nowy][nowx] = 1 ;  //该坐标已经被占用不能再通过
      }
      else  //都行不通 
      {
       popStack(s , &nowx , &nowy) ;
      }
       
     } //while(!isStackEmpty(s)) //当栈不空的时候 
     return 0 ;
    }
    
    //打印栈中的数据 
    int printStackData(STACK s)
    {
     STACK temp ;  //新建一个临时的栈 
     stackInit(&temp) ;
     if(s.top->datax == -1)  return 0 ; //栈为空 
     while(s.top->datax != -1)
     {
      pushStack(&temp,s.top->datax,s.top->datay);
      s.top = s.top->next ;
     }
     while(temp.top->datax != -1)
     {
      int a=temp.top->datax;
      int b=temp.top->datay;
      mizu[b][a]='#';
      printf("(%d,%d)\n",a , b) ;
      temp.top = temp.top->next ;
     } 
     printf("路径为\n");
     
     for(int i=0;i<c;i++)
    	{
    		for(int j=0;j<d;j++)
    		printf("%c ",mizu[i][j]);
    	printf("\n");
    	
    	}
     return 1 ;
    }
    int main()
    {
     STACK mi_stack ; 
     printf("下面是迷宫,1为障碍\n"); 
     printf("请输入迷宫1为障碍0为通路"); 
    	for(int i=0;i<c;i++)
    	{
    		for(int j=0;j<d;j++)
    		scanf("%d",&mizu[i][j]);
    	printf("\n");
    	}
    	for(int i=0;i<c;i++)
    	{
    		for(int j=0;j<d;j++)
    		printf("%d ",mizu[i][j]);
    	printf("\n");
    	}
    	for(int i=0;i<c;i++)
    	{
    		for(int j=0;j<d;j++)
    		printf("%c ",mizu[i][j]);
    	printf("\n");
    	}
    printf("请输入起点坐标,中间用,隔开\n"); 
    scanf("%d,%d",&e,&f);
    
    
    printf("请输入终点坐标,中间用,隔开\n"); 
    scanf("%d,%d",&g,&h);
    printf("输出路径坐标\n"); 
    
    stackInit(&mi_stack) ; 
     if(mizePath(&mi_stack , g , h))
     {
      printStackData(mi_stack) ; //把坐标倒叙打印出来 
     } 
     else printf("没有通路!\n") ;
      
     
     return  0 ;
     
    }
    

    在这里插入图片描述

    展开全文
  • 迷宫求解问题 我们要先初始化一个迷宫地图,这里分为两种,一类为简单迷宫(不带环),一类为复杂迷宫(带环)。具体示例如下,这里采用6*6的数组表示迷宫地图,每个位置上对应元素的值非0即1,1表示路,0表示墙;...

    迷宫求解问题


        我们要先初始化一个迷宫地图,这里分为两种,一类为简单迷宫(不带环),一类为复杂迷宫(带环)。具体示例如下,这里采用6*6的数组表示迷宫地图,每个位置上对应元素的值非0即1,1表示路,0表示墙;
        这里迷宫求解问题,我们可以采用两种方式求解,一种是利用函数本身递归的调用,一种则是利用循环一直查找。且这里的迷宫求解问题也分为两类,一类是简单的查找迷宫的一条路径,一类则是找到迷宫的最小路径。

    一.  查找迷宫的一条通路

        1. 我们从入点开始,先判断入口点是否能走,若入口点都不能走,说明传入参数错误,直接返回;
        2. 入口点能走,我们就将其标记,并放入栈中;
        3. 检查当前点是否为出口(我们将迷宫四周的非入口点都可以看做出口),是出口就找到了一条路;
        4. 若当前点不是出口,则对当前点按顺时针方向(上、右、下、左)的顺序依次探测,是否能走,能走就标记入栈,再按同样的方式继续向下探测,直至找到出口;
        5. 直至找到一条完整的路径时,查找结束,栈内存放即为路径。

    二. 查找迷宫的最短路径

        1. 定义两个栈,一个为cur当前栈,存放查找的路径,一个为short栈,存放最短路径;
        2. 我们从入点开始,先判断入口点是否能走,若入口点都不能走,说明传入参数错误,直接返回;
        3. 入口点能走,我们就将其标记,并放入cur栈中;
        4. 检查当前点是否为出口(我们将迷宫四周的非入口点都可以看做出口),是出口就找到了一条路;
       5. 若当前点不是出口,则对当前点按顺时针方向(上、右、下、左)的顺序依次探测,是否能走,能走就标记入栈,再按同样的方式继续向下探测,直至找到出口;
        6. 找到一条路时,若cur栈中路径比short栈内路径短,或是short栈为空,则用cur中路径替代short中路径;
        7. 直至再也找不到新的路径了,此时short栈内即为最短路径。


    代码如下,其中也有必要的解释:

    maze.h
    #pragma once
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #define SHOW_NAME printf("\n===================%s=================\n",__FUNCTION__);
    #define ROW 6
    #define COL 6
    
    typedef int MazeType;
    typedef struct Point
    {
        MazeType row;
        MazeType col;
    }Point;
    
    typedef struct Maze
    {
        MazeType map[ROW][COL];
    }Maze;
    
    typedef struct SeqStack
    {
        Point* data;
        size_t size;
        size_t capacity;
    }SeqStack;
    


    maze.c
    #include "maze.h"
    
    void PointInit(Point* entry)
    {
        if(entry == NULL)
            return;
        entry->row = 0;
        entry->col = 1;
        return;
    }
    
    void MazeInit(Maze* maze)//初始化,建立一个迷宫地图
    {
        if(maze == NULL)
            return;
        int map[ROW][COL] = {{0,1,0,0,0,0},\
                             {0,1,1,1,0,0},\
                             {0,1,0,1,1,1},\
                             {1,1,1,0,0,0},\
                             {0,0,1,0,0,0},\
                             {0,0,1,0,0,0}};//1表示路,0表示墙,之后走过的路标记为2
        size_t i = 0;
        for(; i<ROW; ++i)
        {   
            size_t j = 0;
            for(; j<COL; ++j)
            {   
                maze->map[i][j] = map[i][j];
            }   
        }   
        return;
    }
    
    void MazePrint(Maze* maze, const char* msg)//打印迷宫
    {
        printf("[%s]\n",msg);
        if(maze == NULL)
            return;
        size_t i = 0;
        for(; i<ROW; ++i)
        {
            size_t j = 0;
            for(; j<COL; ++j)
            {
                printf("%2d ",maze->map[i][j]);
            }
            printf("\n");
        }
        return;
    }
    
    int CanStay(Maze* maze, Point cur)//判断当前点是否能落脚
    {
        if(maze == NULL)
            return 0;
        if(cur.row < 0 || cur.row >= ROW || cur.col < 0 || cur.col >= COL)//当前点越界,不在迷宫地图内
            return 0;
        if(maze->map[cur.row][cur.col] == 1)
            return 1;
        return 0;
    }
    
    void Mark(Maze* maze, Point cur)//标记当前点,将对应值改为2即可
    {
        if(maze == NULL)
            return;
        maze->map[cur.row][cur.col] = 2;
        return;
    }
    
    int IsExit(Maze* maze, Point cur, Point entry)//判断当前点是否为出口,注意判断是否为入口
    {
        if(maze == NULL)
            return 0;
        if(cur.row == entry.row && cur.col == entry.col)//当前点为入口点
            return 0;
        if(cur.row == 0 || cur.row == ROW-1 || cur.col == 0 || cur.col == COL-1)//迷宫有四条边,每一个边上的点都可作出口
            return 1;
        return 0;
    }
    
    ///
    1.利用递归查找简单迷宫的一条路径
    ///
    
    void _GetPath(Maze* maze, Point cur, Point entry)//真正实现查找迷宫路径的函数
    {
        printf("cur : (%d, %d)\n",cur.row,cur.col);//可看到函数调用的过程
        if(maze == NULL)
            return;
        //1.判断当前点是否能落脚
        if(!CanStay(maze,cur))
            return;
        //2.能落脚就标记
        Mark(maze,cur);
        //3.判断当前点是否为出口(非入口、迷宫最外围),为出口,就找到一条路径
        if(IsExit(maze,cur,entry))
        {
            printf("找到一条路\n");
            return;
        }
        //4.不为出口,顺时针探测四周点,递归调用函数本身,递归时更新cur
        Point up = cur;//上方点
        up.row -= 1;
        _GetPath(maze,up,entry);
        Point right = cur;//右方点
        right.col += 1;
        _GetPath(maze,right,entry);
        Point down = cur;//下方点
        down.row += 1;
        _GetPath(maze,down,entry);
        Point left = cur;//左方点
        left.col -= 1;
        _GetPath(maze,left,entry);
        return;
    }
    
    void GetPath(Maze* maze,Point entry)//寻找迷宫路径
    {
        if(maze == NULL)
            return;
        _GetPath(maze,entry,entry);//调用寻找函数,第二个参数表示当前位置,第三个参数表示入口点
    }
    
    ///
    2.利用非递归(循环)查找简单迷宫的一条路径
    ///
    
    void SeqStackInit(SeqStack* stack)
    {
        if(stack == NULL)
            return;
        stack->size = 0;
        stack->capacity = 1000;
        stack->data = (Point*)malloc(sizeof(Point) * stack->capacity);
        return;
    }
    
    void SeqStackPush(SeqStack* stack,Point value)
    {
        if(stack == NULL)
            return;
        if(stack->size >= stack->capacity)
            return;
        stack->data[(stack->size)++] = value;
        return;
    }
    
    void SeqStackPop(SeqStack* stack)
    {
        if(stack == NULL)
            return;
        if(stack->size == 0)
            return;
        --stack->size;
        return;
    }
    
    int SeqStackGetTop(SeqStack* stack, Point* value)
    {
        if(stack == NULL || value == NULL)
            return 0;
        if(stack->size == 0)
            return 0;
        *value = stack->data[stack->size - 1];
        return 1;
    }
    
    void SeqStackPrint(SeqStack* stack, const char* msg)
    {
        printf("[%s]\n",msg);
        if(stack == NULL)
            return;
        size_t i = 0;
        for(; i<stack->size; ++i)
        {
            printf("(%d, %d)\n",stack->data[i].row,stack->data[i].col);
        }
        printf("\n");
    }
    void GetPathByLoop(Maze* maze, Point entry)
    {
        if(maze == NULL)
            return;
        //1.创建一个栈,用于保存走过的路径
        SeqStack stack;
        SeqStackInit(&stack);
        //2.判断入口能否落脚(不能说明传入的参数非法)
        if(!CanStay(maze,entry))
            return;
        //3.能落脚就标记并入栈
        Mark(maze,entry);
        SeqStackPush(&stack, entry);
        //4.进入循环,获取当前栈顶元素
        while(1)
        {
            Point top;
            int ret = SeqStackGetTop(&stack, &top);
            if(ret == 0)//栈为空,回溯结束
                return;
            //5.判断是否为出口
            if(IsExit(maze,top,entry))
            {
                printf("找到一条路\n");
                SeqStackPrint(&stack,"找到的路径为");
                return;
            }
            //6.顺时针取四周点,判断是否能落脚。能落脚就标记且入栈,进行下一轮循环
            Point up = top;//上方点
            up.row -= 1;
            if(CanStay(maze,up))
            {
                Mark(maze,up);
                SeqStackPush(&stack,up);
                continue;
            }
            Point right = top;//右方点
            right.col += 1;
            if(CanStay(maze,right))
            {
                Mark(maze,right);
                SeqStackPush(&stack,right);
                continue;
            }
            Point down = top;//下方点
            down.row += 1;
            if(CanStay(maze,down))
            {
                Mark(maze,down);
                SeqStackPush(&stack,down);
                continue;
            }
            Point left = top;//左方点
            left.col -= 1;
            if(CanStay(maze,left))
            {
                Mark(maze,left);
                SeqStackPush(&stack,left);
                continue;
            }
            //7.若四周都不能落脚,出栈顶元素(出到栈为空,则说明没路可走)
            SeqStackPop(&stack);
        }
    }
    
    ///
    3.查找简单迷宫的最短路径(递归实现)
    ///
    
    
    void SeqStackAssgin(SeqStack* from, SeqStack* to)
    {//to的内存用来拷贝from的,有好几种可能性,这里为了保证代码的简洁性,统一先释放内存再重新申请再拷贝数据
        if(from==NULL || to==NULL)
            return;
        //1.释放to的原有内存
        free(to->data);
        to->size = 0;
        to->capacity = 0;
        //2.依据from的大小给to申请内存
        to->size = from->size;
        to->capacity = from->capacity;
        to->data = (Point*)malloc(sizeof(Point) * to->capacity);
        //3.数据拷贝
        size_t i = 0;
        for(; i<from->size; ++i)
        {
            to->data[i] = from->data[i];
        }
        return;
    }
    
    void _GetShortPath(Maze* maze, Point cur, Point entry, SeqStack* cur_path, SeqStack* short_path)
    {
        //1.判断当前点是否能落脚
        if(!CanStay(maze,cur))
            return;
        //2.能落脚,标记并入cur_path栈
        Mark(maze,cur);
        SeqStackPush(cur_path,cur);
        //3.判断当前点是否为出口点
        if(IsExit(maze,cur,entry))
        {
            printf("找到了一条路\n");
            //1)为出口,找到一条路,此时若cur_path比short_path栈中路径短或short_path为空,用当前路径代替short_path中的路;
            if(cur_path->size < short_path->size || short_path->size==0)
            {
                printf("找到一条较短路径\n");
                SeqStackAssgin(cur_path, short_path);
            }
            //2)为出口,但比short_path中路径长,再回溯去找另外的路径,并出栈顶元素
            //这里不论cur_path中路径比short_path中短还是长,只要是出口,都要回溯,去找是否还有其他路径
            SeqStackPop(cur_path);
            return;
        }
        //4.不是出口,探测周围四个相邻点
        Point up = cur;
        up.row -= 1;
        _GetShortPath(maze,up,entry,cur_path,short_path);
        Point right = cur;
        right.col += 1;
        _GetShortPath(maze,right,entry,cur_path,short_path);
        Point down = cur;
        down.row += 1;
        _GetShortPath(maze,down,entry,cur_path,short_path);
        Point left = cur;
        left.col -= 1;
        _GetShortPath(maze,left,entry,cur_path,short_path);
        //5.四个点都探测过,就出栈回溯
        SeqStackPop(cur_path);
        return;
    }
    
    void GetShortPath(Maze* maze, Point entry)
    {//先遍历找到所有路径,找到里面最短的即可
        SeqStack cur_path;
        SeqStack short_path;
        SeqStackInit(&cur_path);
        SeqStackInit(&short_path);
        _GetShortPath(maze, entry, entry, &cur_path, &short_path);
        SeqStackPrint(&short_path,"最短路径");
    }
    
    ///
    4.复杂迷宫中查找最短路径(递归实现)
    //      复杂迷宫不仅有多个入口,路径上还可能带环      /
    ///
    
    void ComplexMazeInit(Maze* maze)//初始化复杂迷宫地图
    {
        if(maze == NULL)
            return;
        int map[ROW][COL] = {{0,1,0,0,0,0},\
                             {0,1,1,1,0,0},\
                             {0,1,0,1,1,1},\
                             {1,1,1,1,0,0},\
                             {0,0,1,0,0,0},\
                             {0,0,1,0,0,0}};//1表示路,0表示墙
        size_t i = 0;
        for(; i<ROW; ++i)
        {
            size_t j = 0;
            for(; j<COL; ++j)
            {
                maze->map[i][j] = map[i][j];
            }
        }
        return;
    }
    
    void PointPreInit(Point* pre)//入口点的前一个点初始化为(-1,-1)非法点
    {
        if(pre == NULL)
            return;
        pre->row = -1;
        pre->col = -1;
        return;
    }
    
    int CanStayWithCycle(Maze* maze, Point pre, Point cur)
    {
        //1.判断当前点是否在地图上
        if(cur.row < 0 || cur.row >= ROW || cur.col < 0 || cur.col >= COL)
            return 0;
        //2.当前点是否为墙(是则不能落脚)
        if(maze->map[cur.row][cur.col] == 0)
            return 0;
        //3.当前点是否为路(是则直接落脚)
        if(maze->map[cur.row][cur.col] == 1)
            return 1;
        //4.若当前点已走过,判断是否值得走
        //若此时走比之前走花的步数更少,就值得去走,若步数相同或多,就没有意义,因为我们要找最短路径
        //这里不用判断pre位置是否非法,因为仅当入口点为当前点时,pre才会非法,而入口点的值非0即1,前面已过滤
        int pre_value = maze->map[pre.row][pre.col];
        int cur_value = maze->map[cur.row][cur.col];
        if(pre_value + 1 < cur_value)
            return 1;
        return 0;
    }
    
    void MarkWithCycle(Maze* maze, Point pre, Point cur)
    {//将走过的位置标记为入口点到该点的步数,入口点标记为2,实际步数为每个位置的值减去1
        if(pre.row==-1 && pre.col==-1)//当前点为入口点
        {
            maze->map[cur.row][cur.col] = 2;
            return;
        }
        int pre_value = maze->map[pre.row][pre.col];
        maze->map[cur.row][cur.col] = pre_value + 1;
        return;
    }
    
    void _GetShortPathWithCycle(Maze* maze, Point cur, Point pre, Point entry, SeqStack* cur_path, SeqStack* short_path)
    {
        //1.判断当前点是否能落脚(与之前判断方法不同)
        if(!CanStayWithCycle(maze,pre,cur))
            return;
        //2.标记并入cur_path栈(与之前标记方法不同)
        MarkWithCycle(maze, pre, cur);
        SeqStackPush(cur_path, cur);
        //3.判断当前点是否为出口
        if(IsExit(maze, cur, entry))
        {
            //1)为出口,且为更短路径,替换short_path中的路径
            printf("找到一条路\n");
            if(cur_path->size < short_path->size || short_path->size == 0)
            {
                printf("找到一条较短路径\n");
                SeqStackAssgin(cur_path, short_path);
            }
            //2)只要当前点为出口,就要回溯去找其他路径
            SeqStackPop(cur_path);
            return;
        }
        //4.当前点不是出口,探测周围四个相邻点
       Point up = cur;
       up.row -= 1;
       _GetShortPathWithCycle(maze,up,cur,entry,cur_path,short_path);
       Point right = cur;
       right.col += 1;
       _GetShortPathWithCycle(maze,right,cur,entry,cur_path,short_path);
       Point down = cur;
       down.row += 1;
       _GetShortPathWithCycle(maze,down,cur,entry,cur_path,short_path);
       Point left = cur;
       left.col -= 1;
       _GetShortPathWithCycle(maze,left,cur,entry,cur_path,short_path);
        //5.四个点都探测完,出栈回溯
       SeqStackPop(cur_path);
       return;
    }
    
    void GetShortPathWithCycle(Maze* maze, Point pre, Point entry)
    {//先遍历找到所有路径,找到里面最短的即可
        SeqStack cur_path;
        SeqStack short_path;
        SeqStackInit(&cur_path);
        SeqStackInit(&short_path);
        //该方法的标记与之前不同,还要用到前一步点,所以增加一个参数pre
        _GetShortPathWithCycle(maze, entry, pre, entry, &cur_path, &short_path);
        SeqStackPrint(&short_path,"最短路径");
    }
    ///
    以下为测试代码,test1、2、3、4对应上面四种求解情况
    ///
    
    void test1()
    {
        SHOW_NAME;
        Maze maze;
        MazeInit(&maze);
        Point entry;
        PointInit(&entry);
        MazePrint(&maze,"初始迷宫地图");
        GetPath(&maze,entry);
        MazePrint(&maze,"寻找出路");
    }
    
    void test2()
    {
        SHOW_NAME;
        Maze maze;
        MazeInit(&maze);
        Point entry;
        PointInit(&entry);
        MazePrint(&maze,"初始迷宫地图");
        GetPathByLoop(&maze,entry);
        MazePrint(&maze,"寻找出路");
    }
    
    void test3()
    {
        SHOW_NAME;
        Maze maze;
        MazeInit(&maze);
        Point entry;
        PointInit(&entry);
        MazePrint(&maze,"初始迷宫地图");
        GetShortPath(&maze,entry);
    }
    
    void test4()
    {
        SHOW_NAME;
        Maze maze;
        ComplexMazeInit(&maze);
        Point entry;
        Point pre;
        PointInit(&entry);
        PointPreInit(&pre);
        MazePrint(&maze,"初始迷宫地图");
        GetShortPathWithCycle(&maze, pre, entry);
    }
    
    int main()
    {
        test1();
        test2();
        test3();
        test4();
        return 0;
    }
    

    运行结果如下:
    1. 简单迷宫求解一条通路(递归实现)

    此方法通过递归实现,探测路径所走过的点都保存在函数栈帧中,故这里未能将完整的路径所经过的点打印出来。

    2. 简单迷宫求解一条通路(循环实现)
    3. 简单迷宫求解最短路径

    4. 复杂迷宫求解最短路径

    展开全文
  • #include<stdio.h> #include<stdlib.h> #include<assert.h> #include<stdbool.h> typedef struct Postion { int row; int col; }PT; typedef PT STDataType; // 支持动态增长的栈 ...///
  • c语言实现迷宫问题求解,输出路径矩阵
  • C语言实现迷宫求解问题

    千次阅读 2009-10-24 23:19:00
    最近学数据结构的,看到个迷宫求解问题,拿老师的代码来仔细专研,研究了大半天,才看出个端倪,是采用先进后出的#include #include #include #define m 8#define n 8struct stype{int r,c,pre;}sq[400];int maze...

    最近学数据结构的,看到个迷宫求解的问题,拿老师的代码来仔细专研,研究了大半天,才看出个端倪,

    是采用先进后出的

    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>
    #define m 8
    #define n 8
    struct stype
    {int r,c,pre;
    }sq[400];
    int maze[m+2][n+2];/*define maze*/
    int zx[8]={-1,-1,0,1,1,1,0,-1},zy[8]={0,1,1,1,0,-1,-1,-1};/*X,Y移动增量,八个方向*/

    void printpath(int rear);

    void mazepath( )
    {
       int i,j,x,y,v,find,rear,front;
       sq[1].r=1;
       sq[1].c=1;
       sq[1].pre=0;
       find=0;
       j=0;
       front=1;                              //从(1,1)开始搜索
       rear=1;
       maze[1][1]=1;//有改动
       while(front<=rear&&!find)
       {
          x=sq[front].r;
          y=sq[front].c;
          for(v=0;v<8;v++)                 //循环扫描每个方向
          {
              i=zx[v]+x;                    //选择一个前进方向(i,j)
              j=zy[v]+y;
              if(maze[i][j]==0)            //如果该方向可走
              {
                  rear++;                   //进入队列
                  sq[rear].r=i;
                  sq[rear].c=j;
                  sq[rear].pre=front;
                  maze[i][j]=-1;            //避免搜索过的位置重复搜索
              }
              if(i==m&&j==n)             //找到了出口
              {
                 printpath(rear);
                 find=1;
              }
           }
           front++;
       }
       if(!find) printf("不存在路径!");
    }

    void printpath(int rear)/*输出路径算法*/
    {
       int i,j;
       struct stype p[100];
       i=rear;
       do
       {
          printf("(%d,%d)",sq[i].r,sq[i].c);
          i=sq[i].pre;
       }while(i!=0);
    }

    void main()
    {
     int i,j;
     printf("输入迷宫:");
       for(i=0;i<=m+1;i++)
       {
          printf("第%d行:/n",i);
          for(j=0;j<=n+1;j++)
             scanf("%d",&maze[i][j]);
       }
       printf("输出迷宫:/n");
       for(i=0;i<=m+1;i++)
       {
          for(j=0;j<=n+1;j++)
             printf("%d",maze[i][j]);
          printf("/n");
       }
    printf("路径为:");
    mazepath();
       getch();
    }

    最后找到的路径为(8,8)(7,8)(6,7)(5,6)(4,5)(3,4)(3,3)(2,2)(1,1)

    从[1][1] 开始,按北,东北,东,东南,南,西南,西,西北的方向分别对[0][1],[0][2],[1][2],[2][2],[2][1],[2][0],[1][0],[0][0]

    进行扫描,如果该方向可走,把该通道放入队列,并把此通道赋值为-1,可避免重复搜索,其他文字还有很多懒得再写了

    展开全文
  • 初学数据结构和C语言,尝试实现了迷宫求解问题。代码组织比较差,改进的地方也有很多,博君一乐而已。希望能够帮助到别人
  • c语言迷宫问题求解——递归、栈回溯

    千次阅读 多人点赞 2018-05-26 21:02:37
    第一次写,见谅以下是求迷宫的实现/*第一部分使用递归求解为了数据的简单化,不对路口进行数据结构化,将用一个简单的int类型数组来表示迷宫因为每一个路口的四个方向相对于当前路口的位移都是一样的,这样可以用一...
  • 这是一个C语言实现的迷宫求解问题,其中迷宫可以是手动生成,也可以自动生成,附带详细注释
  • C语言实现迷宫求解问题(详细思路+附源代码)

    万次阅读 多人点赞 2016-01-03 16:59:59
    1) 建立一个二维数组表示迷宫的路径(0表示通道,1表示墙壁); 2) 创建一个栈,用来存储“当前路径”,即“在搜索过程中某一时刻所在图中某个方块位置”。 1) 创建一个Int类型的二维数组intmaze[n1][n2],用来存放0...
  • 使用“穷举求解”方法实现迷宫问题求解,以递归形式的算法求得迷宫中所有可能的通路,以方阵形式输出迷宫及其通路。
  • 首先实现一个以链表做存储结构的栈类型,然后编写一个求解迷宫的非递归程序。求得的通路以三元组(i,j,d)的形式输出,其中:(i,j)指示迷宫中的一个坐标,d表示走到下一坐标的方向。如:对于下列数据的迷宫,输出的...
  • [cpp] view ...//顺序栈的应用:迷宫  //作者:nuaazdh  //时间:2011年12月7日  #include  #include    #define OK 1  #define ERROR 0  #define TRUE 1  #define FALSE 0 
  • 迷宫求解问题

    2013-08-04 22:36:26
    迷宫求解问题C语言实现 迷宫求解问题C语言实现

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 186
精华内容 74
关键字:

c语言迷宫求解问题

c语言 订阅