2010-04-06 58 views
2

我试图创建一个迷宫生成器,为此我在C#中实现了随机Prim的算法。在WinForms.NET中渲染一个随机生成的迷宫

但是,生成的结果是无效的。我无法弄清楚它是我的渲染还是无效的实现。因此,对于初学者,我希望有人看看执行:

迷宫是一个单元矩阵。

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); 
} 

这里有一个例子在渲染结果:

Rendered Maze 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 
    } 
} 
+0

似乎无法找到算法的任何问题。问题必须在其他地方... – 2010-04-06 20:05:07

回答

2

这只是一个念头:

即使你没有张贴在您添加壁细胞的代码,我认为是逻辑上的错误。一个单元格有4个墙,但是两个相邻的单元格只有7个墙。不是8.

您需要从其他单元格中删除相应的墙以及删除随机墙。

详细说明: 如果您的AddWallsToMaze算法为每个单元格添加4个墙,那么会有重复的墙。

例如:
CellA有一堵墙CellB。我们称之为Wall1。
CellB墙上有CellA。这是Wall2 NOT Wall1。
它应该是Wall1。

+0

好赶上萨尼。你建议的是当我尝试使用上面的代码添加墙时碰到的同样的问题。 MazeCell类的addwall的实现需要检查墙是否已经从另一个单元添加(“MazeCell b”参数)。我认为这是你的答案克劳斯。 – Audie 2010-04-07 14:03:01

+0

嗯,好吧。这与添加的参考文献是相同的,并且我只获取非通道墙(注意lambda),但我会研究它。 – 2010-04-07 23:14:35

0

解决的办法是纠正绘制细胞的渲染错误。我正在做&底部墙壁,并渲染左侧&顶部墙壁。

private static void RenderCell(PaintEventArgs e, int cellSize, int y, int x, MazeWall wall, Pen pen) 
{ 
    if (wall.Direction == MazeWallOrientation.Horisontal) 
    { 
     e.Graphics.DrawLine(pen, 
      x * cellSize, 
      y * cellSize + cellSize, 
      x * cellSize + cellSize, 
      y * cellSize + cellSize 
     ); 
    } 
    else 
    { 
     e.Graphics.DrawLine(pen, 
      x * cellSize + cellSize, 
      y * cellSize, 
      x * cellSize + cellSize, 
      y * cellSize + cellSize 
     ); 
    } 
} 

我对结果并不满意。我想我会尝试另一种算法,这看起来不像我希望的那么健全。