| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 8605 人关注过本帖, 3 人收藏
标题:小杰作--找迷宫出口路线
只看楼主 加入收藏
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
结帖率:99.25%
收藏(3)
已结贴  问题点数:20 回复次数:38 
小杰作--找迷宫出口路线
呼啦啦~忙了两天终于完成迷宫第一代了无聊发个来看看~顺便求大神指点

对哦,这个没有实现找最短路线功能,只能判断有没有出口和找出口路线~

发过来看看,感觉怎么样都能看懂或多或少的~

程序代码:
#include<stdio.h>
#include<stdlib.h>
#define N 10

typedef struct Node
{

    int ww;//四个方向
    int ss;
    int aa;
    int dd;
    int count;//计算重复走过路线的次数~
    char map;//地图
}Node;
Node S[N][N];//迷宫数组
typedef struct SS
{
    int x;
    int y;

}SS;
SS Self;//自己的当前位置

void print()//打印地图
{
    int i,j;

    for (i=0;i<N;i++,printf("\n"))
        for (j=0;j<N;j++)
            printf("%c",S[i][j].map);
}

void begin(char k[][N])//初始化数据~
{
    int i=0;
    int j=0;

    for (i=0;i<N;i++)
        for (j=0;j<N;j++)
        {

            S[i][j].map=k[i][j];

            if (k[i][j]=='S')//找到初始位置
            {
                Self.x=i;
                Self.y=j;
            }
        }

      print();//打印初始化地图
}

int JUDGE_RUN(int count,int i,int j,int toward)//判断移动位置
{
    switch (count)
    {
        case 1:return(S[i-1][j].map!='*'&&i-1>=0&&toward!=1&&S[i][j].ww)?1:0;
        case 2:return(S[i+1][j].map!='*'&&i+1<=N&&toward!=2&&S[i][j].ss)?1:0;
        case 3:return(S[i][j-1].map!='*'&&j-1>=0&&toward!=3&&S[i][j].aa)?1:0;
        case 4:return(S[i][j+1].map!='*'&&j+1<=N&&toward!=4&&S[i][j].dd)?1:0;
        default:break;
    }

    return 0;
}

void JUDGE_MAP()
{
    int i=0;
    int j=0;

    for (i=0;i<N;i++)
        for (j=0;j<N;j++)
        {              
            S[i][j].ww=JUDGE_RUN(1,i,j,0)?0:1;//判断是否可以移动,此时toward是无指向的(即为0)~
            S[i][j].ss=JUDGE_RUN(2,i,j,0)?0:1;
            S[i][j].aa=JUDGE_RUN(3,i,j,0)?0:1;
            S[i][j].dd=JUDGE_RUN(4,i,j,0)?0:1;

            S[i][j].count=0;//设置重复走过的路线次数为0~
        }

    printf("\n");

}

void JUDGE_WIN()
{
    if (S[Self.x][Self.y].map=='E')
    {
        printf("Yes\n");
        print();
        exit(0);//直接退出处理~
    }
}

void change(int toward)//toward指的是当前方向~1 2 3 4分别代表上下左右~
{
    int i=Self.x;  //获取当前位置
    int j=Self.y;

    JUDGE_WIN();//判断是否找到出口~

    ++S[i][j].count;//重复走过路线的次数要加1

    if (S[i][j].map!='S')//保留初始化位置(其实可以不用)
        S[i][j].map='o';//标记走过路线

    if (JUDGE_RUN(1,i,j,toward))
    {
        --Self.x;           //移动当前位置
 
        S[i][j].ww=0;      //清除当前位置方向

        change(2);   //避免回头走,方向处理~    
        
        ++Self.x;          //退栈要改变当前位置    
    
    }

       if (JUDGE_RUN(2,i,j,toward))
    {
           ++Self.x;

        S[i][j].ss=0;

           change(1);

        --Self.x;
    
    }

       if (JUDGE_RUN(3,i,j,toward))
    {
           --Self.y;

        S[i][j].aa=0;

           change(4);

        ++Self.y;
     
    }

   if (JUDGE_RUN(4,i,j,toward))
    {
           ++Self.y;

        S[i][j].dd=0;

           change(3);

        --Self.y;
    }

    --S[i][j].count;  //退栈要减少重复走过次数    

    if (S[i][j].count==0&&S[i][j].map!='S')            
            S[i][j].map=' ';   //清除走过路线

    return;
}
int main()//'S'为起点,'E'为终点
{
    char k[N][N]=    //地图大小改了迷宫会错位,很麻烦的~改大小要注意一下~
    {
        {"**********"},
        {"*  S*  *E*"},
        {"* *** ** *"},
        {"* * *  * *"},
        {"*        *"},
        {"*** * ** *"},
        {"**  *  * *"},
        {"** ** ** *"},
        {"*  *   * *"},
        {"**********"},
    };

    begin(k);

    JUDGE_MAP();

    change(0);

    printf("NO!\n");  //找不到出口~

    return 0;
}


[此贴子已经被作者于2016-12-19 13:53编辑过]

2016-12-19 12:39
yangfrancis
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:贵宾
威 望:141
帖 子:1510
专家分:7661
注 册:2014-5-19
收藏
得分:3 
根据迷宫大小做个整形二维数组(n*m),记录每一格到达所需的步数,全部初始化为n*m, 起点赋为0,从起点开始递归,每走一步分值递增1,和所到坐标的步数做对比,用少的步数覆盖多的步数。最后得到终点的步数
2016-12-19 15:44
xzlxzlxzl
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖北
等 级:贵宾
威 望:125
帖 子:1091
专家分:5825
注 册:2014-5-3
收藏
得分:0 
既然是版主的辛苦之作,当然要顶下!
感觉完成类似效果我应该可以控制在50句内。
2016-12-19 16:38
xzlxzlxzl
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖北
等 级:贵宾
威 望:125
帖 子:1091
专家分:5825
注 册:2014-5-3
收藏
得分:15 
43行代码,不到30分钟完成,期待检测:
程序代码:
#include<stdio.h>
#define N 11
int go(char n[][N],int x,int y)
{
    if(x<0||x>=N||y<0||y>=12)return 0; //坐标不合格以0返回
    if(n[x][y]=='E')return 1;          //如果已经碰到出口以1返回
    if(n[x][y]!=' ')return 0;          //碰壁或已经走过的路径以0返回
    n[x][y]='o';                       //标记为已经走过的路
    if(go(n,x,y-1))return 1;
    if(go(n,x,y+1))return 1;
    if(go(n,x-1,y))return 1;
    if(go(n,x+1,y))return 1;           //步进方向的顺序这样排列针对本例是最短路径
    return 0;
}
int main()//'S'为起点,'E'为终点
{
    char k[N][N]=    //地图大小改了迷宫会错位,很麻烦的~改大小要注意一下~
    {
        {"**********"},
        {"*  S*  *E*"},
        {"* *** ** *"},
        {"* * *  * *"},
        {"*        *"},
        {"*** * ** *"},
        {"**  *  * *"},
        {"** ** ** *"},
        {"*  *   * *"},
        {"**********"},
    };
    int i,j,m;
    for(m=0;m<N;m++)printf("%s\n",&k[m][0]);
    for(i=0;i<N;i++)
    {
        for(j=0;j<N&&k[i][j]!='S';j++);
        if(j<N)break;
    }  //先找到入口坐标
    k[i][j]=' ';
    if(go(k,i,j))printf("Yes\n");
    else printf("No\n");
    k[i][j]='S';
    for(m=0;m<N;m++)printf("%s\n",&k[m][0]);
    return 0;
}



其实,以前写过图形化的五子棋程序,所以完成这个代码就轻车熟路了

[此贴子已经被作者于2016-12-19 17:25编辑过]

收到的鲜花
  • 九转星河2016-12-19 22:42 送鲜花  20朵   附言:好文章
  • 书生牛犊2016-12-25 11:16 送鲜花  20朵   附言:递归猛如虎。迷宫问题还是要用点算法比较好 ...
2016-12-19 17:23
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 4楼 xzlxzlxzl
上楼以后就做我的大神吧
拜谢大神参考了大神的代码,感觉以前高不可攀的迷宫算法现在做最基础的几乎是水到渠成了,这个算法很值得借鉴,学习了

我自己参考大神的代码后自己完善了一下功能,在源代码的基础上增加了统计迷宫步数和输出所走过的迷宫路径功能~

感觉自己一写代码就不简洁了还是要多多向大神学习一下才行~

程序代码:
#include<stdio.h>
#define N 11
int COUNT=-1;//计算起点和终点间的步数,如果不存在通向终点的路径,则保留初值-1
typedef struct Node
{
    int x;
    int y;
}Node;
Node run[N*N]={0};
int go(char n [][N],Node run[],int x,int y,int step)
{

    if (x<0||x>=N||y<0||y>=N)
        return 0;

    if (n[x][y]=='E')
    {
        COUNT=step;
        return 1;
    }

    if (n[x][y]!=' ')
        return 0;

    n[x][y]='o';

    run[step].x=x;
    run[step].y=y;

    if (go(n,run,x-1,y,step+1))
        return 1;

    if (go(n,run,x+1,y,step+1))
        return 1;

    if (go(n,run,x,y-1,step+1))
        return 1;

    if (go(n,run,x,y+1,step+1))
        return 1;



    return 0;
}
int main()
{
       char K[N][N]=    
     {
        {"**********"},
        {"*  S*  *E*"},
        {"* *** ** *"},
        {"* * *  * *"},
        {"*      * *"},
        {"*** * ** *"},
        {"**  *    *"},
        {"** ** ** *"},
        {"*  *   * *"},
        {"**********"},
     };


     int i=0;
     int j=0;
     int step=0;

     for (i=0;i<N;i++)
     {
         for (j=0;j<N&&K[i][j]!='S';j++);
         if (j<N)
             break;
     }

    K[i][j]=' ';

    if (go(K,run,i,j,step))
        printf("Yes\n");
    else
        printf("NO\n");

    K[i][j]='S';

    for (i=0;i<N;i++)
        for (j=0;j<N;j++)
            if (K[i][j]=='o')
                K[i][j]=' ';

    for (i=0;i<COUNT;i++)
        K[run[i].x][run[i].y]='o';

    for (i=0;i<N;i++)
        printf("%s\n",&K[i][0]);

    printf("The step(s) is: %d\n",COUNT);

    printf("The Road is:\n");

    for (i=0;i<COUNT;i++)
    {
        printf("[%d][%d] ",run[i].x,run[i].y);

        if (i%10==9&&i!=COUNT-1)
            printf("\n");
    }

    printf("\n");

    return 0;
}


[此贴子已经被作者于2016-12-20 14:00编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-19 22:20
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 2楼 yangfrancis
迷宫出口在尽头处,通过递归它走到出口判断是尽头路就不再对其进行第二次递归了,这个问题怎么解决

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-19 23:37
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 6楼 九转星河
想到了,求迷宫的最路径不是用栈,而是用队列,栈是深度搜索,队列是广度搜索思路解决了~

[此贴子已经被作者于2016-12-20 07:52编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-20 07:49
xzlxzlxzl
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖北
等 级:贵宾
威 望:125
帖 子:1091
专家分:5825
注 册:2014-5-3
收藏
得分:0 
我不是大神,共同学习进步吧!
你5楼代码不能将“if (n[x][y]=='E')”放在“if (x<0||x>=N||y<0||y>=N)”前面执行,因为坐标不合法意味着数组溢出,c是不检查数组溢出的,会给你一个不确定的值,如果恰好给了字符E的值,你就得到错误结果了。
至于最优路径,则是用四叉树了,在四叉树节点登记搜索深度(搜索层数),每次使用层数最小的进行搜索,最先到达的层数就是最优路径,等今天空下来给代码测试。
2016-12-20 09:45
yangfrancis
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:贵宾
威 望:141
帖 子:1510
专家分:7661
注 册:2014-5-19
收藏
得分:0 
回复 6楼 九转星河
走到尽头的话只结束一个分支,其他分支如果所用步数更少的话可用来覆盖已有的步数。
2016-12-20 10:01
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 8楼 xzlxzlxzl
谢谢x版主的提醒,上面代码问题已修正,而且还优化了一下代码~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-20 12:38
快速回复:小杰作--找迷宫出口路线
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.031832 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved