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

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

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

程序代码:
#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
九转星河
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
九转星河
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
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 11楼 xzlxzlxzl
看来x版主递归还没有学得够火候哦我是通过测试才拿出来的~
前面有个重要条件

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

加这句是为了避免输出经过退格的路线,你可以去测试一下,看看有没有问题~

对哦,你写的代码末尾加了这句那无论怎么变动四个方向的权值都可以避免输出退格(虽然这样并不能保证走的是最短路径)~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-20 13:41
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 13楼 xzlxzlxzl
好吧,你是正确的~我还要再修改一下才行(看来我还是不应该删我原来的代码啊)~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-20 13:49
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 15楼 九转星河
把源码改回来了

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-20 14:01
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
多谢炎天版主置顶

想不到炎版主也这么重视我的杰作,很感动哦

这个迷宫我先研究一下,有时间再更新~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2016-12-20 20:52
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 13楼 xzlxzlxzl
哈哈,果然是理论上的"死循环"啊,其实,没有绝对的死循环,只不过这种方法当遇到新出路时会把原来走过的样板全部刷新,导致循环次数呈几何级别增长~貌似陷入"死循环",你可以拿下列代码测试一下~结果会很有趣的诶,我现在都会放动画了~

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

     for (i=0;i<N;i++)
        printf("%s\n",&K[i][0]);
}
int go(char n [][N],Node run[],int x,int y,int step)
{
    system("cls");
    print(n);

    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;

    if (n[x][y]=='o')
        n[x][y]=' ';

    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;
}

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



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

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