查看文章
 
一个C#的迷宫生成算法,采用深度优先遍历拆墙。
2008年07月29日 下午 8:49
因为最近要用C#开发一个走迷宫的小游戏,所以需要编写一个随机生成迷宫的组件,但是查阅了网上的很多相关资料,都不是很全。只知道最好的方法是采用图的遍历来做,但是依然不得要领。后来无意中看到了CodeZone上面的Generating Maze using C# and .NET( ),才一下子明白过来,思路也清晰了。

这是Mike的程序的UML图——


程序的核心在于遍历所有迷宫格子。Mike是这样写的:

public void Generate()
{
while (VisitedCells < TotalCells)
{
// get a list of the neighboring cells with all 4 walls intact
ArrayList AdjacentCells = GetNeighborsWithWalls(CurrentCell);
// test if a cell like this exists
if (AdjacentCells.Count > 0)
{
// yes, choose one of them, and knock down the wall between it and the current cell
int randomCell = Cell.TheRandom.Next(0, AdjacentCells.Count);
Cell theCell = ((Cell)AdjacentCells[randomCell]);
CurrentCell.KnockDownWall(theCell);
CellStack.Push(CurrentCell);
// push the current cell onto the stack
CurrentCell = theCell; // make the random neighbor the new current cell
VisitedCells++;
// increment the # of cells visited
}
else // No adjacent cells that haven't been visited, go back to the previous cell
{
CurrentCell = (Cell)CellStack.Pop();
}
}
}

我通过分析这个Generate()函数,再结合上方的UML,大致复原了Mike缩写程序的源代码。

简单的说,Mike这个程序的思路是这样的:

迷宫的格子当然是一个单独的类MazeCell,该对象除了拥有行、列两个坐标值外,还需要一个很重要的属性——墙,一个四个元素的INT型数组(private int[] wall = { 1, 1, 1, 1 };)。遍历迷宫的过程,就是拆墙的过程,数组的四个元素分别代表迷宫各自上、下、左、右四面墙的状态,拆哪面墙就将其置0以标志。相应的拆墙函数为KnockDownWall()。

迷宫格子的类写完了,相当于是基础已经搭建了起来。接下来就是核心的迷宫类,首先该对象必须用一个二维数组MazeCell[,] cells来装迷宫格子,然后需要一个堆栈Stack<MazeCell> mazeStack来装遍历过程中临时存储用的格子。

在最核心的遍历循环中,首先要从当前格子周围找一个四面墙都在的相邻格子(相邻是指的位于当前格子的上下左右),也就是未曾被访问的格子。这时可能得到以下几种结果:

1、有不止一个相邻的格子都未被访问过:这时需要生成一个随机数,挑选其中一个出来拆掉它与当前格子之间的墙并且压入堆栈,同时将其作为新的当前格子

2、只有一个相邻的各自未被访问,这更方便,随机数都不用生成了,直接拿来拆墙,之后同上。

3、周围的格子都被访问过了,这说明当前格子已经走到了一条死路的尽头,所以需要把堆栈中的前一个格子Pop出来当作当前格子,再看看周围是否有路,如果还是没有就继续Pop直到能找到另外一条路。

该循环在访问完所有的格子后结束。此时,所有的格子都被拆掉了一面墙,迷宫也就生成了。

(数字表示程序遍历该迷宫的顺序)

接下来开始研究最短路径的问题……头疼……


类别:默认分类| |分享到i贴吧|浏览(1786)|评论 (0)
 
网友评论:
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
     

   
帮助中心 | 空间客服 | 投诉中心 | 空间协议
©2012 Baidu