winston 发表于 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; //迷宫数据,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的值,如果为0,表示没有一条路径可走,否则打印出
    口距入口的距离。
全部的代码见下:

#include <stdlib.h>   
#include <stdio.h>   
#include <memory.h>   
#include <queue>

using namespace std;

#define MAX_WIDTH    30   
#define MAX_HEIGHT   30   

typedef struct _step
{
    int x;          //行坐标   
    int y;          //列坐标
        int distance;   //距迷宫入口的距离       
}STEP;

typedef struct _matrix
{
    int data; //迷宫数据,0:表示有路,-1:表示墙   
    int width;            //矩阵(迷宫)的宽,包括最左和最有2堵墙   
    int height;             //矩阵(迷宫)的宽,包括顶部和底部2堵墙   
    STEP entrance;          //迷宫入口   
    STEP exit;            //迷宫出口   
}MATRIX;

MATRIX g_matrix=                //初始化为一个迷宫,程序也能从文件中读入迷宫数据   
{
    {
       {-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},
    },
    7,7,                  //7行,7列,包括4堵墙   
    {1,1},                  //入口坐标   
    {5,5}                   //出口坐标   
};


static STEPs_shift[]=
{
    {1,0,0},      //向右走, x++, y 不变   
    {0,1,0},      //向下走,x 不变, y++   
    {-1,0,0},   //向左走,x--, y不变   
    {0,-1,0}      //向上走,x 不变, y--   
};

void print_Matrix(MATRIX* pMatrix)      //打印迷宫数据,迷宫数据包含4堵墙   
{
    int i,j;
    for (i=0;i<pMatrix->height;i++)
    {
      for (j=0;j<pMatrix->width;j++)
      {
            if (j!=0)
                printf(" ");
            printf("%d",pMatrix->data);
      }
      printf("\n");
    }
}

int search_min_distance(int matric, STEP entrance, STEP exit)
{
    deque<STEP> my_queue;
        STEP t1,t2;
        int i;
        t1=entrance;
        t1.distance=0;
       
        my_queue.push_back(t1);

        while ( !my_queue.empty() )
        {
                t1=my_queue.front();
                my_queue.pop_front();
               
               
                t2.distance =t1.distance +1;
                for (i=0;i<4;i++)
                {
                        t2.x=t1.x + s_shift.x;
                        t2.y=t1.y + s_shift.y;
               
                        if ( (t2.x!=entrance.x || t2.y !=entrance.y) && matric != -1 )
                        {
                                if( matric==0 ||matric> t2.distance)
                                {
                                        matric=t2.distance;
                                        my_queue.push_back(t2);
                                }
                        }
                }
        }
       
        returnmatric;
               
}

int readMatrix(char *file)
{
    char line;
    FILE *fp=NULL;
    int i,j,x,y;

    fp=fopen(file,"rt");
    if (fp==NULL)
    {
      printf("Can not open file %s\n",file);
      return 0;
    }

    memset(&(g_matrix),0,sizeof(g_matrix));
    fgets(line,sizeof(line)-1,fp);
      
    sscanf(line,"%d %d",&x,&y);               //读入迷宫的行数和列数   
    if ( x>MAX_WIDTH || y>MAX_HEIGHT)
    {
      printf("The Matrix is too large\n");
      fclose(fp);
      return 0;
    }

    g_matrix.width=x+2;                         //在4条边增加4堵墙,故宽和高增加2   
    g_matrix.height=y+2;
      
    for (j=0;j<g_matrix.width;j++)
    {
      g_matrix.data=-1;                  //第一行为墙   
      g_matrix.data=-1;//最后一行为墙   
    }

    for (i=0;i<g_matrix.height;i++)      
    {
      g_matrix.data=-1;                  //最左边的列为墙   
      g_matrix.data=-1;   //最右边的列为墙   
    }

      
    for (i=1;i<g_matrix.height-1;i++)
    {
      char *p;
      fgets(line,sizeof(line)-1,fp);
      j=1;   
      p=line;
      while (1)
      {
            while ( *p==' ' || *p== 9 || *p== ',' )//跳过空格和逗号
                p++;

            if ( *p>='0' && *p<='9'|| *p == '-')
            {
                sscanf(p,"%d",&(g_matrix.data));//读入地i行j列的数据   
                while ( *p>='0' && *p<='9'|| *p== '-' )
                  p++;            //数据已经读入,跳过当前的数字   
                j++;
            }

            if (j>=g_matrix.width-2)
                break;
      }
    }
      
    fgets(line,sizeof(line)-1,fp);
      
    //读入入口的行坐标和列坐标,和出口的行坐标,列坐标   
    sscanf(line,"%d %d %d %d",&(g_matrix.entrance.x),&(g_matrix.exit.y),&(g_matrix.exit.x),&(g_matrix.exit.y));
    fclose(fp); fp=NULL;
      
    g_matrix.entrance.x++;//增加了一列是墙,故入口横坐标+1   
    g_matrix.entrance.y++;//增加了一行是墙,故入口纵坐标+1   
    g_matrix.exit.x++;      //增加了一列是墙,故入口横坐标+1   
    g_matrix.exit.y++;      //增加了一列是墙,故入口纵坐标+1   

    return 1;
}

int main()
{
    int distance;

    if ( !readMatrix("matrix.txt") )//不使用初始化的数据,从文件中读入迷宫数据   
    {
      return 0;                     //读取失败,直接跳出      
    }

    printf("The original matrix is\n");
    print_Matrix(&g_matrix);

        distance= search_min_distance(g_matrix.data,g_matrix.entrance,g_matrix.exit);
       
        printf("The new matrix is\n");
        print_Matrix(&g_matrix);

        printf("\nThe distance is %d\n",distance);

    return 0;
}


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

页: [1]
查看完整版本: 一个求迷宫入口到出口最近距离的程序