百度首页 | 百度空间
 
查看文章
 
迷宫算法(经典广度优先搜索算法)
2008-05-07 22:34

经典广度优先搜索算法,用parentx,parenty存储上一步的位置,规范化使用队列和栈。
迷宫暂定为8*6,动态生成,四周为一圈障碍,出口坐标为(8,6)。

坐标的定义类似图形编程的屏幕坐标,横向为x分量,垂直为y分量,左上角为原点。

可以向8个方向试探。

源代码(TC下编译运行通过):


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

#define Status int

#define OK 1
#define ERROR 0

#define OVERFLOW -2

#define TRUE 1
#define FALSE 0

#define ROW 8            /*行列可自定*/
#define COLUM 10      /*行列可自定*/

#define OUT 8
#define STEPPED 2

#define MAXQSIZE 100

int maze[8][10]/*6行8列*/
={{1,1,1,1,1,1,1,1,1,1},
    {1,0,1,1,1,1,0,0,0,1},
    {1,0,1,0,0,1,1,0,0,1},
    {1,0,0,0,1,0,1,0,0,1},
    {1,1,1,0,1,0,1,0,0,1},
    {1,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,1,OUT,1},
    {1,1,1,1,1,1,1,1,1,1}};/*此处只是给一个初始化的例子,可以删去,后面的代码可以动态生成迷宫*/

void CreateRandomMaze()/*随机生成迷宫(可能产生走不通的迷宫)*/
{
    int i,j;
    srand((int)time());/*设置随机数种子,产生真随机数*/
    for(i=0;i<ROW;i++)
    {
        for(j=0;j<COLUM;j++)
        {
            maze[i][j]=rand()%2;/*产生0~1的随机数*/
        }
    }
    for(i=0;i<COLUM;i++)
    {
        maze[0][i]=1;
        maze[ROW-1][i]=1;
    }
    for(i=0;i<ROW;i++)
    {
        maze[i][0]=1;
        maze[i][COLUM-1]=1;
    }
    maze[1][1]=0;
    maze[ROW-2][COLUM-2]=OUT;/*设置出口*/
}

void printMaze()/*打印迷宫*/
{
int i,j;
clrscr();
for(i=0;i<ROW;i++)
{
      for(j=0;j<COLUM;j++)
      {
        printf(" %d",maze[i][j]);
      }
      printf("\n");
}
/*delay(1000);*/
}
/*********************队列(非循环顺序队列)************************/
typedef struct
{
    int x,y;
    int parentx,parenty;       /*记录上一个节点即路径中前驱节点,方便最后输出*/
}QNode,*QueuePtr;

typedef QNode ElemType;

typedef struct SqQueue
{
    ElemType * base;
    int front;
    int rear;
}SqQueue;/*队列结构体*/

Status InitQueue(SqQueue *Q)/*初始化队列*/
{
    Q->base = (ElemType *)malloc(MAXQSIZE *sizeof(ElemType));
    if(!Q->base)
    {exit(OVERFLOW);}
    Q->front = Q->rear = 0;
    return OK;
}

int QueueLength(SqQueue Q)
{
    return Q.rear - Q.front;
}

Status QueueEmpty(SqQueue Q)
{
if(Q.front==Q.rear)
{return TRUE;}
return FALSE;
}

Status GetHead(SqQueue Q,ElemType *e)
{
    if(Q.front==Q.rear)
    {return ERROR;}
    *e = Q.base[Q.front];
    return OK;   
}

Status EnQueue(SqQueue *Q,ElemType e)
{
    if(Q->rear>MAXQSIZE-1)/*队列满*/
    {return ERROR;}
    Q->base[Q->rear]=e;
    (Q->rear)++;
    return OK;
}

Status DeQueue(SqQueue *Q,ElemType *e)
{
    if(Q->front == Q->rear)/*队列空*/
    {return ERROR;}
    *e = Q->base[Q->front];
    (Q->front)++;
    return OK;
}

/*********************栈**********************/
typedef struct
{
int top,base,count;
ElemType container[100];/*ROW*COLUM];*/
}SqStack;

Status InitStack(SqStack *s)
{
s->top=-1;
s->base=0;
s->count=0;
}

Status StackEmpty(SqStack s)
{
if(s.count!=0)
{return FALSE;}
return TRUE;
}

Status Push(SqStack *s,ElemType e)
{
s->top++;
s->container[s->top]=e;
s->count++;
return OK;
}

Status Pop(SqStack *s,ElemType *e)
{
if(s->top<s->base)
{return ERROR;}
*e = s->container[s->top];
s->top--;
s->count--;
}

/*******************************************/
main()
{
    int dx[]={ 0, 1,1,1,0,-1,-1,-1}; /*方向偏移量*/
    int dy[]={-1,-1,0,1,1, 1, 0,-1};
    int direction,flag, /*找到出口标志*/
        cx,cy, /*当前位置坐标*/
        nx,ny; /*根据方向下一点坐标*/   

    SqQueue sqq;
    SqStack sqs,sqsout;
    ElemType start,et;
   
    CreateRandomMaze();/*创建随机地图*/
    printMaze();/*打印地图*/
   
    InitQueue(&sqq); /*初始化队列sqq*/
    InitStack(&sqs); /*初始化栈sqs*/
    InitStack(&sqsout); /*初始化栈sqsout*/
    

    start.x=1;
    start.y=1;
    start.parentx=-1;
    start.parenty=-1;
   
    EnQueue(&sqq,start); /*起始点入队*/
    
    for(;(flag!=TRUE)&&(!QueueEmpty(sqq));)
    {
        GetHead(sqq,&et); /*取队首元素(不是出队)*/
        cx=et.x;
        cy=et.y;
       
        for(direction=0;direction<8;direction++) /*朝八个方向试探*/
        {
            nx = cx+dx[direction]; /*nx = cx + 方向偏移量*/
            ny = cy+dy[direction];
           
            if(maze[ny][nx]==0||maze[ny][nx]==OUT) /*如果下一点坐标可通,或者是出口*/
            {
                et.x=nx;
                et.y=ny;
                et.parentx = cx; /*下一点的路径上的前驱是当前点*/
                et.parenty = cy;
                EnQueue(&sqq,et); /*将下一点入队*/
               
                if(maze[ny][nx]!=OUT)
                {maze[ny][nx]=STEPPED; /*访问过了*/}
            }
           
            if(maze[ny][nx]==OUT) /*如果下一点是出口*/
            {
                flag = TRUE; /*标志位置TRUE*/
                break; /*路径已找到,不用在试探了,退出循环*/
            }
        }       
        DeQueue(&sqq,&et);/*出队*/
        Push(&sqs,et);/*所有出队的元素都将别压入栈sqs*/
    }


    if(QueueEmpty(sqq)) /*如果每条路线都试过都没有找到出口,则队列为空,说明已经失败了*/
    {
        printf("failed!");
    }
       
    if(flag==TRUE) /*如果标记为是TRUE,那么说明已经找到路径了,广度优先所的路径即为最短路径*/
    {
        while(!QueueEmpty(sqq))
        {
            DeQueue(&sqq,&et);
            Push(&sqs,et);
        }
       
       /******以下用到了两个栈,第一个栈sqs用来搜索最短路径并把其存入第二个栈,第二个栈sqsout用于顺序输出********/
        Pop(&sqs,&start);
        Push(&sqsout,start);

        while(!StackEmpty(sqs))
        {
            Pop(&sqs,&et);
            if(et.x==start.parentx && et.y==start.parenty)
            {
                start=et;
                Push(&sqsout,et);
            }
        }
       
        while(!StackEmpty(sqsout))
        {
            Pop(&sqsout,&et);
            printf("(%d,%d)\t",et.x,et.y);
        }
    }
}


类别:c语言 | 添加到搜藏 | 浏览() | 评论 (4)
 
最近读者:
 
网友评论:
1
2008-06-11 21:07
应该没有人会认真看吧,除了像我这样要交作业的人!
 
2
2008-06-16 22:28
有人看当然好了,留在这里也可以当备忘。
o(∩_∩)o...哈哈
 
3
2008-06-19 13:52
我就认真看了……不过有点晕……
 
4
2008-10-23 13:00
编译出错啊!
 
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
验证码:
 

     

©2008 Baidu