一个求迷宫入口到出口最近距离的程序
本文给出一个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]