深度优先搜索生成迷宫
2013-03-29 17:09
726 查看
前些天逛书店,发现一本叫做<<opengl超级宝典第5版>>的书,买了下来回家慢慢看.感觉这本书比<<opengl编程指南>>更适合入门学习,因为里面有许多例子.后来才知道,这本书就是所谓"opengl蓝宝书".看了这本书,许多看红宝书时不明白的地方突然就明白了,可能是因为这本书翻译的质量更好,或者说这本书解释得更具体.
无意间发现了一个博客,http://blog.csdn.net/jiangcaiyang123.该博客主人还是个学生,技术却不错.代码写得清晰,注重复用,在学校写的代码就用上了泛型和跨平台,对opengl 和 dx的理解也比我强..跟他比起来,我很惭愧.上班这些年,总有许多生活上的琐事,让自己学习时间并不充足.即使在学生时代时间充足的时候,自己的水平也比人家差的太远.我不禁感慨时间飞逝,惋惜以往浪费的时间.
那个博客里有个opengl 3d的迷宫,我最近也在学习opengl,打算不参考其他人代码的前提下,自己也搞一个.
今天就弄个迷宫自动生成的控制台程序,过些天想办法移植到 opengl上.
关于迷宫自动生成参考了一些资料,主要是维基百科
http://en.wikipedia.org/wiki/Maze_generation_algorithm
里面介绍了几种常用的算法,我这里的代码暂时只参考了深度优先搜索算法.算法本身里面描述的比较清楚 ,不再赘述.在过程
中遇到了一个转不过弯的地方,记录如下.
迷宫的存储结构是一个2维数组,在采用深度优先搜索的时候,会遍历这个数组的每个元素.
然而,最终迷宫存储的数组,并不是这个数组,而是一个"扩展数组".
即,如果把原数组看作是一个方格,该方格仅代表一个数组元素的话,扩展数组则把这一个方格扩展为9个元素,分别是
左上,正上,右上,左侧,正中,右侧,左下,正下,右下.
这样才能把深度优先搜索的矩阵,与最终的迷宫矩阵建立联系.
就像下面代码 Maze类中的 MazePoint** m_arrMaze 是最终迷宫的矩阵,
MazePoint** m_arrRaw 是用来做遍历生成路径的辅助矩阵。
现在不太方便具体绘图说明,上面一段话表达不够清晰,但是却是生成迷宫时困扰我时间最长的问题.
直接上代码和截图吧.
Maze.h
Maze.cpp
main.cpp
![](http://img.my.csdn.net/uploads/201303/29/1364548356_6445.png)
无意间发现了一个博客,http://blog.csdn.net/jiangcaiyang123.该博客主人还是个学生,技术却不错.代码写得清晰,注重复用,在学校写的代码就用上了泛型和跨平台,对opengl 和 dx的理解也比我强..跟他比起来,我很惭愧.上班这些年,总有许多生活上的琐事,让自己学习时间并不充足.即使在学生时代时间充足的时候,自己的水平也比人家差的太远.我不禁感慨时间飞逝,惋惜以往浪费的时间.
那个博客里有个opengl 3d的迷宫,我最近也在学习opengl,打算不参考其他人代码的前提下,自己也搞一个.
今天就弄个迷宫自动生成的控制台程序,过些天想办法移植到 opengl上.
关于迷宫自动生成参考了一些资料,主要是维基百科
http://en.wikipedia.org/wiki/Maze_generation_algorithm
里面介绍了几种常用的算法,我这里的代码暂时只参考了深度优先搜索算法.算法本身里面描述的比较清楚 ,不再赘述.在过程
中遇到了一个转不过弯的地方,记录如下.
迷宫的存储结构是一个2维数组,在采用深度优先搜索的时候,会遍历这个数组的每个元素.
然而,最终迷宫存储的数组,并不是这个数组,而是一个"扩展数组".
即,如果把原数组看作是一个方格,该方格仅代表一个数组元素的话,扩展数组则把这一个方格扩展为9个元素,分别是
左上,正上,右上,左侧,正中,右侧,左下,正下,右下.
这样才能把深度优先搜索的矩阵,与最终的迷宫矩阵建立联系.
就像下面代码 Maze类中的 MazePoint** m_arrMaze 是最终迷宫的矩阵,
MazePoint** m_arrRaw 是用来做遍历生成路径的辅助矩阵。
现在不太方便具体绘图说明,上面一段话表达不够清晰,但是却是生成迷宫时困扰我时间最长的问题.
直接上代码和截图吧.
Maze.h
#ifndef _MAZE_H_ #define _MAZE_H_ #include <vector> #define DEBUG_MAZE_GENERATE struct MazePoint { int _x,_y; bool _bIsVisisted; MazePoint() { _x = _y = 0; _bIsVisisted = false; _state = E_State_Wall; } MazePoint(int x,int y) { _x = x; _y = y; _bIsVisisted = false; } void setCoord(int x,int y) { _x = x; _y = y; } void operator = (const MazePoint& pt) { _x = pt._x; _y = pt._y; _bIsVisisted = pt._bIsVisisted; } bool IsVisited() { return _bIsVisisted; } void setVisited(bool visited = true) { _bIsVisisted = visited; } enum { E_State_Path, E_State_Wall, E_State_Entry, E_State_Dest, E_State_Max, }; int _state; }; class Maze { protected: int m_nCol,m_nRow,m_nRawCol,m_nRawRow; // generate helper MazePoint** m_arrMaze; MazePoint** m_arrRaw; MazePoint m_ptStart; MazePoint m_ptCur; std::vector<MazePoint> m_ptStack; public: Maze(); virtual ~Maze(); void initMazeArray(int rownum,int colnum); void printMazeArray(); // generate helper void autoGenerate(); bool isThereUnvisited(); bool isThePointInBoundary(int x,int y); void reset(); enum { E_Dir_Up, E_Dir_Down, E_Dir_Left, E_Dir_Right, E_Dir_Max, }; double random(double start,double end); bool getNeighbor(int &x,int &y); }; #endif //_MAZE_H_
Maze.cpp
#include "Maze.h" #include <stdio.h> #include <time.h> #include <stdlib.h> Maze::Maze() : m_nCol(0), m_nRow(0) { m_arrRaw = NULL; m_arrMaze = NULL; srand((int)time(0)); rand(); } Maze::~Maze() { reset(); } void Maze::initMazeArray(int rownum,int colnum) { // raw data m_nRawRow = rownum; m_nRawCol = colnum; m_arrRaw = new MazePoint*[m_nRawRow]; for(int i=0;i<m_nRawRow;i++) { m_arrRaw[i] = new MazePoint[m_nRawCol](); for(int j=0;j<m_nRawCol;j++) { m_arrRaw[i][j].setCoord(j,i); } } // generated data m_nRow = 2 * rownum + 1; m_nCol = 2 * colnum + 1; m_arrMaze = new MazePoint*[m_nRow]; for(int i=0;i<m_nRow;i++) { m_arrMaze[i] = new MazePoint[m_nCol](); for(int j=0;j<m_nCol;j++) { m_arrMaze[i][j].setCoord(j,i); } } } void Maze::printMazeArray() { printf("Maze Map:\n"); for(int i = 0; i < m_nRow; i++ ) { for(int j = 0 ;j < m_nCol; j++ ) { printf("%d",m_arrMaze[i][j]._state); } printf("\n"); } #ifdef DEBUG_MAZE_GENERATE printf("Raw data:\n"); for(int i = 0; i < m_nRawRow; i++ ) { for(int j = 0 ;j < m_nRawCol; j++ ) { printf("%d",m_arrRaw[i][j]._state); } printf("\n"); } #endif } void Maze::autoGenerate() { int curx,cury; int nextx,nexty; curx = cury = 0; m_arrRaw[cury][curx].setVisited(true); m_ptStack.push_back(m_arrRaw[cury][curx]); while(isThereUnvisited()) { nextx = curx; nexty = cury; if(getNeighbor(nextx,nexty)) { #ifdef DEBUG_MAZE_GENERATE printf("nextx: %d,nexty: %d\n",nextx,nexty); #endif m_arrRaw[nexty][nextx].setVisited(); m_ptStack.push_back(m_arrRaw[nexty][nextx]); // modfiy arrMaze[][] ,mark it passable between (curx,cury) => (nextx,nexty) m_arrMaze[2*cury+1][2*curx+1]._state = MazePoint::E_State_Path; m_arrMaze[2*nexty+1][2*nextx+1]._state = MazePoint::E_State_Path; m_arrMaze[(2*cury+1 + 2*nexty+1)/2][(2*curx+1 + 2*nextx+1)/2]._state = MazePoint::E_State_Path; curx = nextx; cury = nexty; } else if(m_ptStack.size() > 1) { m_ptStack.pop_back(); curx = m_ptStack[m_ptStack.size()-1]._x; cury = m_ptStack[m_ptStack.size()-1]._y; } else if(m_ptStack.size() == 1) { curx = m_ptStack[m_ptStack.size()-1]._x; cury = m_ptStack[m_ptStack.size()-1]._y; m_ptStack.pop_back(); } else { // is it possible ? printf("Stack is NULL\n"); } } } bool Maze::isThereUnvisited() { for(int i = 0; i < m_nRawRow; i++ ) { for(int j = 0 ;j < m_nRawCol; j++ ) { if(!m_arrRaw[i][j].IsVisited()) return true; } } return false; } bool Maze::isThePointInBoundary(int x,int y) { return x >= 0 && x < m_nRawCol && y >=0 && y < m_nRawRow; } double Maze::random(double start,double end) { return start+(end-start)*rand()/(RAND_MAX + 1.0); } bool Maze::getNeighbor(int &x,int &y) { int neighborX[E_Dir_Max]; int neighborY[E_Dir_Max]; bool isValid[E_Dir_Max]; neighborX[E_Dir_Right] = x + 1; neighborY[E_Dir_Right] = y; isValid[E_Dir_Right] = (isThePointInBoundary(neighborX[E_Dir_Right],neighborY[E_Dir_Right]) && !m_arrRaw[neighborY[E_Dir_Right]][neighborX[E_Dir_Right]].IsVisited()); neighborX[E_Dir_Left] = x - 1; neighborY[E_Dir_Left] = y; isValid[E_Dir_Left] = (isThePointInBoundary(neighborX[E_Dir_Left],neighborY[E_Dir_Left]) && !m_arrRaw[neighborY[E_Dir_Left]][neighborX[E_Dir_Left]].IsVisited()); neighborX[E_Dir_Down] = x; neighborY[E_Dir_Down] = y + 1; isValid[E_Dir_Down] = (isThePointInBoundary(neighborX[E_Dir_Down],neighborY[E_Dir_Down]) && !m_arrRaw[neighborY[E_Dir_Down]][neighborX[E_Dir_Down]].IsVisited()); neighborX[E_Dir_Up] = x; neighborY[E_Dir_Up] = y - 1; isValid[E_Dir_Up] = (isThePointInBoundary(neighborX[E_Dir_Up],neighborY[E_Dir_Up]) && !m_arrRaw[neighborY[E_Dir_Up]][neighborX[E_Dir_Up]].IsVisited()); // there's no valid direction bool isThereValidDir = false; for(int i=0;i<E_Dir_Max;i++) { isThereValidDir = isThereValidDir || isValid[i]; } if(!isThereValidDir) { return false; } // there's valid direction ,get random one int randnum = random(0,4); int finalDir = 0; for(int i=0;i<E_Dir_Max;i++) { if(isValid[i]) { finalDir = i; break; } } while(randnum) { randnum--; finalDir++; finalDir = finalDir == E_Dir_Max ? 0 : finalDir; while(!isValid[finalDir]) { finalDir++; finalDir = finalDir == E_Dir_Max ? 0 : finalDir; } } x = neighborX[finalDir]; y = neighborY[finalDir]; return true; } void Maze::reset() { // delete generated data if( m_arrMaze != NULL) { for(int i=0;i<m_nRow;i++) { delete[] (m_arrMaze[i]); m_arrMaze[i] = NULL; } delete[] m_arrMaze; m_arrMaze = NULL; } // delete raw data if( m_arrMaze != NULL) { for(int i=0;i<m_nRawRow;i++) { delete[] (m_arrRaw[i]); m_arrRaw[i] = NULL; } delete[] m_arrRaw; m_arrRaw = NULL; } }
main.cpp
#include <stdio.h> #include "Maze.h" Maze* pMaze = new Maze(); int main(int argc,char** argv) { pMaze->initMazeArray(20,20); pMaze->printMazeArray(); pMaze->autoGenerate(); pMaze->printMazeArray(); pMaze->reset(); pMaze->initMazeArray(3,8); pMaze->autoGenerate(); pMaze->printMazeArray(); if(pMaze) { delete pMaze; } return 0; }
![](http://img.my.csdn.net/uploads/201303/29/1364548356_6445.png)
![](http://img.my.csdn.net/uploads/201303/29/1364548506_8250.png)
相关文章推荐
- 利用深度优先搜索做的随机生成地图的迷宫小游戏
- 用深度优先搜索解迷宫问题
- DFS深度优先搜索之走迷宫
- 57.深度优先搜索 广搜练习:迷宫(未结题)
- makefile 入门指南实例——深度优先迷宫搜索
- 逃离迷宫 HDU - 1728 深度优先搜索
- makefile 入门指南实例——深度优先迷宫搜索
- 【面试题】迷宫问题-----深度优先搜索----栈
- 迷宫最短路径 深度优先搜索—C—python
- 57.深度优先搜索 广搜练习:迷宫(未结题)
- 栈:深度优先搜索与回溯算法求解迷宫
- C语言深度优先搜索之迷宫(堆栈)
- 57.深度优先搜索 广搜练习:迷宫(未结题)
- HDU1269--迷宫城堡--深度优先搜索
- 深度优先搜索找迷宫的出路
- 写给妹妹的编程札记 4 - 搜索: 迷宫问题 - 深度优先搜索
- 深度优先搜索找迷宫的出路
- 深度优先搜索之走迷宫 (sdut oj 2449)
- 搜索之深度优先【迷宫搜索】(判断是否n步恰好可以到达某点)
- 迷宫深度优先搜索 找出一条可行路径