深度优先搜索生成迷宫
来源:互联网 发布:百会云计算 编辑:程序博客网 时间:2024/05/06 16:56
前些天逛书店,发现一本叫做<<opengl超级宝典第5版>>的书,买了下来回家慢慢看.感觉这本书比<<opengl编程指南>>更适合入门学习,因为里面有许多例子.后来才知道,这本书就是所谓"opengl蓝宝书".看了这本书,许多看红宝书时不明白的地方突然就明白了,可能是因为这本书翻译的质量更好,或者说这本书解释得更具体.
无意间发现了一个博客,http://blog.csdn.net/jiangcaiyang123.该博客主人还是个学生,技术却不错.代码写得清晰,注重复用,在学校写的代码就用上了泛型和跨平台,对opengl 和 dx的理解也比我强..跟他比起来,我很惭愧.上班这些年,总有许多生活上的琐事,让自己学习时间并不充足.即使在学生时代时间充足的时候,自己的水平也比人家差的太远.我不禁感慨时间飞逝,惋惜以往浪费的时间.
今天就弄个迷宫自动生成的控制台程序,过些天想办法移植到 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>#defineDEBUG_MAZE_GENERATEstruct 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:intm_nCol,m_nRow,m_nRawCol,m_nRawRow;//generate helperMazePoint**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 helpervoid 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 datam_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 datam_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");}#ifdefDEBUG_MAZE_GENERATEprintf("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)){#ifdefDEBUG_MAZE_GENERATEprintf("nextx: %d,nexty: %d\n",nextx,nexty);#endifm_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 oneint 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 dataif( 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 dataif( 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;}
- 深度优先搜索生成迷宫
- 深度优先迷宫生成类
- HDU1269--迷宫城堡--深度优先搜索
- Matlab 深度优先搜索求解迷宫问题
- 深度优先搜索找迷宫的出路
- 深度优先搜索-求解迷宫解空间
- 用深度优先搜索解迷宫问题
- 深度优先搜索DFS(迷宫问题)
- DFS深度优先搜索之走迷宫
- 深度优先搜索——迷宫
- 深度优先搜索--迷宫可能路径--栈
- 走迷宫——深度优先搜索
- 深度优先搜索:能否走出迷宫
- 深度优先搜索应用:走迷宫
- 深度优先搜索DFS 走迷宫
- 深度优先搜索求解迷宫问题
- dfs走迷宫_深度优先搜索
- 迷宫问题(深度优先搜索)
- Ilist<T>转换为List<T>
- 最全的 Twitter Bootstrap 开发资源清单
- js反射写法
- LRU Cache
- wget方式调用页面时注意的问题
- 深度优先搜索生成迷宫
- ORACLE PL/SQL编程之八: 把触发器说透
- 我的Android进阶之旅------>Android声明和使用权限
- 热爱OC
- omx4460
- windows编程经典书籍
- Android混淆、反编译以及反破解的简单回顾
- PHP.ini详解以及配置
- Liunx下Qos功能实现简析