[Qt] 迷宫随机生成和寻路算法

来源:互联网 发布:知美术馆 编辑:程序博客网 时间:2024/05/17 22:57


首先贴出下载链接:

1. 完整Qt源码:http://download.csdn.net/detail/mahabharata_/9824044

2. 发布的可执行程序:http://download.csdn.net/detail/mahabharata_/9824066


程序截图:

1. 动画演示自动寻路的过程(使用QSequentialAnimation)


2. 生成的一个较大迷宫和打印路径。




      最近,我陆续地把以前做的一些Qt或OpenGL的小程序、游戏等整理出来。其中的这个迷宫游戏,是我在大二时期为《数据结构综合实习》所做的程序。

      当时倒是觉得写完这个程序对我的Qt技巧的提升还挺大的。虽然现在时隔了将近2年,回头重新审视这段代码,发现不管是以前的代码结构,还是Qt的熟练程度还是差了一些火候。

      不过这里还是整理分享出来,希望能给那些希望学好Qt的同学一些帮助。顺带着,也可以通过这个程序,了解一下迷宫的随机生成算法、DFS的寻路算法。


说明:

1. 这个程序的灵感来自于最近流行的平面像素风格RPG游戏。

2. 当进入程序时,先点击“生成迷宫”,程序会自动生成一个给定宽度、高度的随机迷宫。

3. 点击“玩家模式”按钮,可以像普通RPG游戏那样,WASD操纵小人的移动,中间使用的插值会使小人的运动显得比较连贯。

4. 点击“圆形按钮”,小人将会动画演示自动寻路的过程

5. 点击“绘制路径”按钮,将会在地图上打印小人的路径。


核心算法:

0. 基本的数据结构

class point{public:    int i;    int j;    int state;    point();    point(int i,int j, int state);    bool operator==(const point& maze);};
class Maze{private:    point **recordMatrix;    QStack<point> *MazeStack;    point move[4]; //人移动的四个方向public:    point **matrix;    int height;//迷宫矩阵的行    int width;//迷宫矩阵的列    int X;//人的位置    int Y;    QList<point> pathStack;  // 存储动画演示的中间过程。    QList<point> autoPath;   //存放最终的路径。    Maze();    void initMaze(int h,int w);    void createMaze();    void autoFindPath();private:    void setDirFalse(bool& up,bool& down,bool& right,bool& left);};

1. 迷宫的随机生成:

  在随机生成的迷宫中要求任意两点,都可以找到一条路径相通,所以在图论中可以认为迷宫就是一个连通图。产生连通图的常见方法有kruskal和prim算法,一般来讲使用prim算法产生的迷宫比较自然和随机。其实本质是,一个有约束条件的深搜。

void Maze::createMaze(){    int i=3,j=3;    matrix[i][j].state=1;    point temp;    temp.i=i;    temp.j=j;    temp.state=1;    bool up=false, down=false, right=false, left=false;    while(true)    {        temp.i=i;        temp.j=j;        int randNum=qrand()%4;        switch(randNum)        {        case 0://上            if(!up&&i>2&&matrix[i-2][j].state==0)            {                MazeStack->push(temp);                matrix[i-2][j].state=1;                matrix[i-1][j].state=1;                i=i-2;                setDirFalse(up, down, right, left);            }            else                up=true;            break;        case 1://下            if(!down&&i<height-3&&matrix[i+2][j].state==0)            {                MazeStack->push(temp);                matrix[i+2][j].state=1;                matrix[i+1][j].state=1;                i=i+2;                setDirFalse(up, down, right, left);            }            else                down=true;            break;        case 2://左            if(!left&&j>2&&matrix[i][j-2].state==0)            {                MazeStack->push(temp);                matrix[i][j-2].state=1;                matrix[i][j-1].state=1;                j=j-2;                setDirFalse(up, down, right, left);            }            else                left=true;            break;        case 3://右            if(!right&&j<width-3&&matrix[i][j+2].state==0)            {                MazeStack->push(temp);                matrix[i][j+2].state=1;                matrix[i][j+1].state=1;                j=j+2;                setDirFalse(up, down, right, left);            }            else                right=true;            break;        }        if(up&&down&&right&&left)//如果当前访问节点四个方向都没有可拆的节点,回溯        {            if(!MazeStack->empty())            {                i=MazeStack->top().i;                j=MazeStack->top().j;                MazeStack->pop();                setDirFalse(up, down, right, left);            }            else//如果栈为空的话就返回,此时迷宫矩阵已经创建完毕            {                return;            }        }    }}
2. 迷宫的自动寻路:

void Maze::autoFindPath(){    pathStack.clear();    recordMatrix[X][Y].state = 0;  //出口位置标记为已经访问过,0为墙    point temp(X,Y,0);    pathStack.push_back(temp);    int i , j , d ;    while(!pathStack.isEmpty())    {        point top = pathStack.back();        pathStack.pop_back();        if(!autoPath.isEmpty()&& !(top==autoPath.back()))            autoPath.push_back(top);        if(autoPath.isEmpty())            autoPath.push_back(top);        i = top.i;j=top.j;d=top.state;        while(d < 4)        {            temp.i = i+move[d].i;            temp.j = j+move[d].j;            if(temp.i == height-2 &&temp.j ==width-2)            {                pathStack.push_back(top);                pathStack.push_back(temp);                autoPath.push_back(temp);                for(int i=0 ; i<pathStack.size();i++)                {                    qDebug()<<"("<<pathStack[i].i<<","<<pathStack[i].j<<")";                }                return;            }            if(matrix[temp.i][temp.j].state == 1 && recordMatrix[temp.i][temp.j].state == 1)            {                recordMatrix[temp.i][temp.j].state = 0;                top.state=d;                pathStack.push_back(top);                temp.state=0;                pathStack.push_back(temp);                autoPath.push_back(temp);                break;            }            d++;        }        if(d==4)            autoPath.push_back(pathStack.back());    }}

2 0
原创粉丝点击