在 WinForms.NET 中渲染随机生成的迷宫
我正在尝试创建一个迷宫生成器,为此我在 C# 中实现了随机 Prim 算法。
但生成的结果是无效的。我无法弄清楚是我的渲染无效还是实现无效。因此,对于初学者来说,我想让某人看一下实现:
迷宫是一个细胞矩阵。
var cell = maze[0, 0];
cell.Connected = true;
var walls = new HashSet<MazeWall>(cell.Walls);
while (walls.Count > 0)
{
var randomWall = walls.GetRandom();
var randomCell = randomWall.A.Connected ? randomWall.B : randomWall.A;
if (!randomCell.Connected)
{
randomWall.IsPassage = true;
randomCell.Connected = true;
foreach (var wall in randomCell.Walls)
walls.Add(wall);
}
walls.Remove(randomWall);
}
以下是渲染结果的示例:
渲染迷宫 http://dl.dropbox。 com/u/1744224/Upload/primrecur.png
编辑 好的,让我们看一下渲染部分:
private void MazePanel_Paint(object sender, PaintEventArgs e)
{
int size = 20;
int cellSize = 10;
MazeCell[,] maze = RandomizedPrimsGenerator.Generate(size);
mazePanel.Size = new Size(
size * cellSize + 1,
size * cellSize + 1
);
e.Graphics.DrawRectangle(Pens.Blue, 0, 0,
size * cellSize,
size * cellSize
);
for (int y = 0; y < size; y++)
for (int x = 0; x < size; x++)
{
foreach(var wall in maze[x, y].Walls.Where(w => !w.IsPassage))
{
if (wall.Direction == MazeWallOrientation.Horisontal)
{
e.Graphics.DrawLine(Pens.Blue,
x * cellSize, y * cellSize,
x * cellSize + cellSize,
y * cellSize
);
}
else
{
e.Graphics.DrawLine(Pens.Blue,
x * cellSize,
y * cellSize, x * cellSize,
y * cellSize + cellSize
);
}
}
}
}
我想,要理解这一点,我们需要看到 MazeCell 和 MazeWall班级:
namespace MazeGenerator.Maze
{
class MazeCell
{
public int Column
{
get;
set;
}
public int Row
{
get;
set;
}
public bool Connected
{
get;
set;
}
private List<MazeWall> walls = new List<MazeWall>();
public List<MazeWall> Walls
{
get { return walls; }
set { walls = value; }
}
public MazeCell()
{
this.Connected = false;
}
public void AddWall(MazeCell b)
{
walls.Add(new MazeWall(this, b));
}
}
enum MazeWallOrientation
{
Horisontal,
Vertical,
Undefined
}
class MazeWall : IEquatable<MazeWall>
{
public IEnumerable<MazeCell> Cells
{
get
{
yield return CellA;
yield return CellB;
}
}
public MazeCell CellA
{
get;
set;
}
public MazeCell CellB
{
get;
set;
}
public bool IsPassage
{
get;
set;
}
public MazeWallOrientation Direction
{
get
{
if (CellA.Column == CellB.Column)
{
return MazeWallOrientation.Horisontal;
}
else if (CellA.Row == CellB.Row)
{
return MazeWallOrientation.Vertical;
}
else
{
return MazeWallOrientation.Undefined;
}
}
}
public MazeWall(MazeCell a, MazeCell b)
{
this.CellA = a;
this.CellB = b;
a.Walls.Add(this);
b.Walls.Add(this);
IsPassage = false;
}
#region IEquatable<MazeWall> Members
public bool Equals(MazeWall other)
{
return (this.CellA == other.CellA) && (this.CellB == other.CellB);
}
#endregion
}
}
I'm trying to create a maze-generator, and for this I have implemented the Randomized Prim's Algorithm in C#.
However, the result of the generation is invalid. I can't figure out if it's my rendering, or the implementation that's invalid. So for starters, I'd like to have someone take a look at the implementation:
maze is a matrix of cells.
var cell = maze[0, 0];
cell.Connected = true;
var walls = new HashSet<MazeWall>(cell.Walls);
while (walls.Count > 0)
{
var randomWall = walls.GetRandom();
var randomCell = randomWall.A.Connected ? randomWall.B : randomWall.A;
if (!randomCell.Connected)
{
randomWall.IsPassage = true;
randomCell.Connected = true;
foreach (var wall in randomCell.Walls)
walls.Add(wall);
}
walls.Remove(randomWall);
}
Here's a example on the rendered result:
Rendered Maze http://dl.dropbox.com/u/1744224/Upload/primrecur.png
Edit Ok, lets have a look at the rendering part then:
private void MazePanel_Paint(object sender, PaintEventArgs e)
{
int size = 20;
int cellSize = 10;
MazeCell[,] maze = RandomizedPrimsGenerator.Generate(size);
mazePanel.Size = new Size(
size * cellSize + 1,
size * cellSize + 1
);
e.Graphics.DrawRectangle(Pens.Blue, 0, 0,
size * cellSize,
size * cellSize
);
for (int y = 0; y < size; y++)
for (int x = 0; x < size; x++)
{
foreach(var wall in maze[x, y].Walls.Where(w => !w.IsPassage))
{
if (wall.Direction == MazeWallOrientation.Horisontal)
{
e.Graphics.DrawLine(Pens.Blue,
x * cellSize, y * cellSize,
x * cellSize + cellSize,
y * cellSize
);
}
else
{
e.Graphics.DrawLine(Pens.Blue,
x * cellSize,
y * cellSize, x * cellSize,
y * cellSize + cellSize
);
}
}
}
}
And I guess, to understand this we need to see the MazeCell and MazeWall class:
namespace MazeGenerator.Maze
{
class MazeCell
{
public int Column
{
get;
set;
}
public int Row
{
get;
set;
}
public bool Connected
{
get;
set;
}
private List<MazeWall> walls = new List<MazeWall>();
public List<MazeWall> Walls
{
get { return walls; }
set { walls = value; }
}
public MazeCell()
{
this.Connected = false;
}
public void AddWall(MazeCell b)
{
walls.Add(new MazeWall(this, b));
}
}
enum MazeWallOrientation
{
Horisontal,
Vertical,
Undefined
}
class MazeWall : IEquatable<MazeWall>
{
public IEnumerable<MazeCell> Cells
{
get
{
yield return CellA;
yield return CellB;
}
}
public MazeCell CellA
{
get;
set;
}
public MazeCell CellB
{
get;
set;
}
public bool IsPassage
{
get;
set;
}
public MazeWallOrientation Direction
{
get
{
if (CellA.Column == CellB.Column)
{
return MazeWallOrientation.Horisontal;
}
else if (CellA.Row == CellB.Row)
{
return MazeWallOrientation.Vertical;
}
else
{
return MazeWallOrientation.Undefined;
}
}
}
public MazeWall(MazeCell a, MazeCell b)
{
this.CellA = a;
this.CellB = b;
a.Walls.Add(this);
b.Walls.Add(this);
IsPassage = false;
}
#region IEquatable<MazeWall> Members
public bool Equals(MazeWall other)
{
return (this.CellA == other.CellA) && (this.CellB == other.CellB);
}
#endregion
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这只是一个想法:
即使您没有发布向单元格添加墙壁的代码,我相信这是逻辑错误。单个牢房有 4 个壁,但两个相邻的牢房只有 7 个壁。不是 8.
移除 randomWall 时,您还需要从其他单元移除相应的墙。
更详细地阐述一下:
如果您的
AddWallsToMaze
算法向每个单元添加 4 面墙,则存在重复的墙。例如:
CellA 与 CellB 有一面墙。我们称之为 Wall1。
CellB 与 CellA 有一面墙。这是墙 2,不是墙 1。
应该是Wall1。
This is just a thought:
Even though you have not posted the code where you add walls to a cell, I believe that is the logical error. A single cell has 4 walls but two adjoining cells have only 7 walls. Not 8.
You need to remove the corresponding wall from the other cell aswell when removing the randomWall.
To elaborate in a bit more detail:
If your
AddWallsToMaze
algorithm adds 4 walls to each cell then there are duplicate walls.Ex:
CellA has a wall with CellB. Let's call it Wall1.
CellB has a wall with CellA. This is Wall2 NOT Wall1.
It should be Wall1.
解决方案是纠正单元格绘制方式中的渲染错误。我正在做右墙和底墙,并渲染左墙和顶墙。
我对结果并不完全满意。我想我会尝试另一种算法,这似乎没有我希望的那么好。
The solution was to correct the rendering mistake in how the cells were drawn. I were doing right&bottom walls, and rendering left&top walls.
I'm not perfectly happy with the result. I think I'll try another algorihm, this doesn't seem as wellformed as I'd hoped.