Рендеринг случайного сгенерированного лабиринта в WinForms.NET - PullRequest
2 голосов
/ 06 апреля 2010

Я пытаюсь создать генератор лабиринта, и для этого я реализовал алгоритм рандомизированного Прима в C #.

Однако результат генерации недействителен. Я не могу понять, является ли это мой рендеринг, или реализация, которая является недействительной. Поэтому для начала я бы хотел, чтобы кто-то взглянул на реализацию:

Лабиринт - это матрица клеток.

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

Ответы [ 2 ]

2 голосов
/ 07 апреля 2010

Это просто мысль:

Даже если вы не разместили код, в котором вы добавляете стены в ячейку, я считаю, что это логическая ошибка.Одна ячейка имеет 4 стенки, но две соседние ячейки имеют только 7 стен.Не 8.

При удалении randomWall необходимо также удалить соответствующую стену из другой ячейки.

Для более подробной информации: если ваш алгоритм AddWallsToMaze добавляет 4 стеныв каждой ячейке есть дубликаты стен.

Пример:
CellA имеет стену с CellB.Давайте назовем это Wall1.
У CellB есть стена с CellA.Это Wall2, а не Wall1.
Это должна быть Wall1.

0 голосов
/ 08 апреля 2010

Решение было исправить ошибку рендеринга в том, как были нарисованы ячейки. Я делал правую и нижнюю стены и рендеринг левой и верхней стен.

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

Я не совсем доволен результатом. Я думаю, что попробую другой алгоритм, это выглядит не так хорошо, как я надеялся.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...