这是大二上学期做的一个小玩意儿,上传上来凑个数哈哈哈。
首先贴出下载链接:
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 *MazeStack;
point move[4]; //人移动的四个方向
public:
point **matrix;
int height;//迷宫矩阵的行
int width;//迷宫矩阵的列
int X;//人的位置
int Y;
QList pathStack; // 存储动画演示的中间过程。
QList 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&&ipush(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&&jpush(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