找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 6730|回复: 0

一个求迷宫入口到出口最近距离的程序

[复制链接]
发表于 2012-5-23 21:36:07 | 显示全部楼层 |阅读模式
本文给出一个c/c++语言版的求迷宫最短路径的程序。程序的大部分使用标准c语言编写,包括输入和
输出。唯一用到C++库的地方是使用STL了中的deque。迷宫的宽和高,迷宫矩阵,迷宫的入口和出口从文
件读入。程序首先读入迷宫数据,然后求更新迷宫矩阵,并求出迷宫入口和出口的最短路径,并输出最
短路径长度。

1. 迷宫的表示。
迷宫用结构体MATRIX来表示
包括迷宫矩阵,迷宫的宽,迷宫的高,迷宫入口的坐标,迷宫出口的坐标。
结构体定义如下:
typedef struct _step
{
int x; //行坐标
int y; //列坐标
int distance; //距迷宫入口的距离
}STEP;
typedef struct _matrix
{
int data[MAX_WIDTH+2][MAX_WIDTH+2]; //迷宫数据,0:表示有路,1:表示墙
int width;  //矩阵(迷宫)的宽,包括最左和最有2堵墙
int height;  //矩阵(迷宫)的高,包括顶部和底部2堵墙
STEP entrance; //迷宫入口
STEP exit;  //迷宫出口
}MATRIX;

开始时,迷宫矩阵的每一个元素是0或-1,0表示可走,-1表示是墙,走不通。为了便于检查是否越界,
即坐标是否超过迷宫的范围。在迷宫的4个边增加了全-1数据,表示4堵墙。这样,在任何时候,都不
会越界。下面的数据表示1个5×5的迷宫,增加了4堵墙后,实际宽度和高度变为7,迷宫变成1个7×7
的矩阵。在搜索迷宫出口距入口的最近距离的过程中,需要修改矩阵相关元素的值。对所有和迷宫入
口相通的方格,其值被改为其距迷宫入口的最近距离。
-1, -1, -1, -1, -1, -1, -1,
-1,  0,  0,  0,  0,  0, -1,
-1, -1,  0, -1,  0, -1, -1,
-1,  0,  0, -1, -1, -1, -1,
-1,  0, -1,  0,  0,  0, -1,
-1,  0,  0,  0, -1,  0, -1,
-1, -1, -1, -1, -1, -1, -1,

2.算法
  迷宫的矩阵的每一方格可用三元组(x,y,d)来表示,x,y表示这个方格的坐标,d表示这个方格距入口
的距离.
  1.首先,将入口的坐标(x,y,0),放入双端队列my_queue。
  2. 接下来重复以下的过程,直到队列为空
    2.1.从队列头部取出一个三元组(x0,y0,d)
    2.2.从右,下,左,上四个方向搜索,看能否有非-1的格子
     如果可找到一个方格,其坐标为(x,y),且这个方格不是入口点,则有3种情况
      case 1.
      新方格对应的矩阵元素是0,表明新的方格距迷宫入口的距离尚未标记。
   则将新方格对应的矩阵元素设置为d+1,同时将三元组(x,y,d+1)入队
      case 2:
      新方格的对应的矩阵元素的值>d+1,表明该新方格距迷宫入口的距离已经标记但不是最近的。
   则将新方格对应的矩阵元素设置为d+1,同时将三元组(x,y,d+1)入队  
   case 3:
    如果新的方格的对应的矩阵元素<= d+1,该位置距入口的距离已经标记,则不做处理
  3.检查出口对应的矩阵元素M[exit.x][exit.y]的值,如果为0,表示没有一条路径可走,否则打印出
    口距入口的距离。
全部的代码见下:
  1. #include <stdlib.h>   
  2. #include <stdio.h>   
  3. #include <memory.h>   
  4. #include <queue>
  5. using namespace std;
  6. #define MAX_WIDTH    30   
  7. #define MAX_HEIGHT   30   
  8.   
  9. typedef struct _step  
  10. {  
  11.     int x;          //行坐标   
  12.     int y;          //列坐标  
  13.         int distance;   //距迷宫入口的距离       
  14. }STEP;  
  15.   
  16. typedef struct _matrix  
  17. {  
  18.     int data[MAX_WIDTH+2][MAX_WIDTH+2]; //迷宫数据,0:表示有路,-1:表示墙   
  19.     int width;              //矩阵(迷宫)的宽,包括最左和最有2堵墙   
  20.     int height;             //矩阵(迷宫)的宽,包括顶部和底部2堵墙   
  21.     STEP entrance;          //迷宫入口   
  22.     STEP exit;              //迷宫出口   
  23. }MATRIX;  
  24.   
  25. MATRIX g_matrix=                //初始化为一个迷宫,程序也能从文件中读入迷宫数据   
  26. {  
  27.     {  
  28.        {-1, -1, -1, -1, -1, -1, -1},  
  29.        {-1,  0,  0,  0,  0,  0, -1},  
  30.        {-1, -1,  0, -1,  0, -1, -1},  
  31.        {-1,  0,  0, -1, -1, -1, -1},  
  32.        {-1,  0, -1,  0,  0,  0, -1},  
  33.        {-1,  0,  0,  0, -1,  0, -1},  
  34.        {-1, -1, -1, -1, -1, -1, -1},  
  35.     },  
  36.     7,7,                    //7行,7列,包括4堵墙   
  37.     {1,1},                  //入口坐标   
  38.     {5,5}                   //出口坐标   
  39. };  
  40.   
  41.   
  42. static STEP  s_shift[]=  
  43. {  
  44.     {1,0,0},      //向右走, x++, y 不变   
  45.     {0,1,0},      //向下走,  x 不变, y++   
  46.     {-1,0,0},     //向左走,  x--, y不变   
  47.     {0,-1,0}      //向上走,  x 不变, y--   
  48. };  
  49.   
  50. void print_Matrix(MATRIX* pMatrix)      //打印迷宫数据,迷宫数据包含4堵墙   
  51. {  
  52.     int i,j;  
  53.     for (i=0;i<pMatrix->height;i++)  
  54.     {  
  55.         for (j=0;j<pMatrix->width;j++)  
  56.         {  
  57.             if (j!=0)  
  58.                 printf(" ");  
  59.             printf("%d",pMatrix->data[i][j]);  
  60.         }  
  61.         printf("\n");  
  62.     }  
  63. }  
  64.   
  65. int search_min_distance(int matric[MAX_WIDTH+2][MAX_WIDTH+2], STEP entrance, STEP exit)  
  66. {  
  67.     deque<STEP> my_queue;
  68.         STEP t1,t2;
  69.         int i;
  70.         t1=entrance;
  71.         t1.distance=0;
  72.        
  73.         my_queue.push_back(t1);
  74.         while ( !my_queue.empty() )
  75.         {
  76.                 t1=my_queue.front();
  77.                 my_queue.pop_front();
  78.                
  79.                
  80.                 t2.distance =t1.distance +1;
  81.                 for (i=0;i<4;i++)
  82.                 {
  83.                         t2.x=t1.x + s_shift[i].x;
  84.                         t2.y=t1.y + s_shift[i].y;
  85.                
  86.                         if ( (t2.x!=entrance.x || t2.y !=entrance.y) && matric[t2.x][t2.y] != -1 )
  87.                         {
  88.                                 if  ( matric[t2.x][t2.y]==0 ||  matric[t2.x][t2.y]> t2.distance)
  89.                                 {
  90.                                         matric[t2.x][t2.y]=t2.distance;
  91.                                         my_queue.push_back(t2);
  92.                                 }
  93.                         }
  94.                 }
  95.         }
  96.        
  97.         return  matric[exit.x][exit.y];
  98.                
  99. }  
  100.   
  101. int readMatrix(char *file)  
  102. {  
  103.     char line[1024];  
  104.     FILE *fp=NULL;  
  105.     int i,j,x,y;  
  106.   
  107.     fp=fopen(file,"rt");  
  108.     if (fp==NULL)  
  109.     {  
  110.         printf("Can not open file %s\n",file);  
  111.         return 0;  
  112.     }  
  113.   
  114.     memset(&(g_matrix),0,sizeof(g_matrix));  
  115.     fgets(line,sizeof(line)-1,fp);  
  116.       
  117.     sscanf(line,"%d %d",&x,&y);                 //读入迷宫的行数和列数   
  118.     if ( x>MAX_WIDTH || y>MAX_HEIGHT)  
  119.     {  
  120.         printf("The Matrix is too large\n");  
  121.         fclose(fp);  
  122.         return 0;  
  123.     }  
  124.   
  125.     g_matrix.width=x+2;                         //在4条边增加4堵墙,故宽和高增加2   
  126.     g_matrix.height=y+2;  
  127.       
  128.     for (j=0;j<g_matrix.width;j++)  
  129.     {  
  130.         g_matrix.data[0][j]=-1;                  //第一行为墙   
  131.         g_matrix.data[g_matrix.height-1][j]=-1;  //最后一行为墙   
  132.     }  
  133.   
  134.     for (i=0;i<g_matrix.height;i++)        
  135.     {  
  136.         g_matrix.data[i][0]=-1;                  //最左边的列为墙   
  137.         g_matrix.data[i][g_matrix.width-1]=-1;   //最右边的列为墙   
  138.     }  
  139.   
  140.       
  141.     for (i=1;i<g_matrix.height-1;i++)  
  142.     {  
  143.         char *p;  
  144.         fgets(line,sizeof(line)-1,fp);  
  145.         j=1;   
  146.         p=line;  
  147.         while (1)  
  148.         {  
  149.             while ( *p==' ' || *p== 9 || *p== ',' )//跳过空格和逗号
  150.                 p++;  
  151.   
  152.             if ( *p>='0' && *p<='9'|| *p == '-')  
  153.             {  
  154.                 sscanf(p,"%d",&(g_matrix.data[i][j]));  //读入地i行j列的数据   
  155.                 while ( *p>='0' && *p<='9'|| *p== '-' )  
  156.                     p++;            //数据已经读入,跳过当前的数字   
  157.                 j++;  
  158.             }  
  159.   
  160.             if (j>=g_matrix.width-2)  
  161.                 break;  
  162.         }  
  163.     }  
  164.       
  165.     fgets(line,sizeof(line)-1,fp);  
  166.       
  167.     //读入入口的行坐标和列坐标,和出口的行坐标,列坐标   
  168.     sscanf(line,"%d %d %d %d",&(g_matrix.entrance.x),&(g_matrix.exit.y),&(g_matrix.exit.x),&(g_matrix.exit.y));  
  169.     fclose(fp); fp=NULL;  
  170.       
  171.     g_matrix.entrance.x++;  //增加了一列是墙,故入口横坐标+1   
  172.     g_matrix.entrance.y++;  //增加了一行是墙,故入口纵坐标+1   
  173.     g_matrix.exit.x++;      //增加了一列是墙,故入口横坐标+1   
  174.     g_matrix.exit.y++;      //增加了一列是墙,故入口纵坐标+1   
  175.   
  176.     return 1;  
  177. }  
  178.   
  179. int main()  
  180. {  
  181.     int distance;
  182.   
  183.     if ( !readMatrix("matrix.txt") )  //不使用初始化的数据,从文件中读入迷宫数据   
  184.     {  
  185.         return 0;                     //读取失败,直接跳出      
  186.     }  
  187.   
  188.     printf("The original matrix is\n");  
  189.     print_Matrix(&g_matrix);  
  190.         distance= search_min_distance(g_matrix.data,g_matrix.entrance,g_matrix.exit);
  191.        
  192.         printf("The new matrix is\n");  
  193.         print_Matrix(&g_matrix);  
  194.         printf("\nThe distance is %d\n",distance);
  195.   
  196.     return 0;  
  197. }  
复制代码

作者:liangbch 发表于2012-5-23 16:28:21 原文链接

您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-5-19 08:48 , Processed in 0.013685 second(s), 6 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表