public Maze Build() { Maze maze = new Maze(mazeWidth, mazeHeight); // Build a full spanning tree maze first System.Random random = new System.Random(); ISet <CellPosition> visitedCells = new HashSet <CellPosition>(); List <WallPosition> walls = new List <WallPosition>(); CellPosition p = new CellPosition(random.Next() % mazeWidth, random.Next() % mazeHeight); foreach (CellPosition neighbour in p.Neighbours()) { if (!IsValidCellPosition(maze, neighbour)) { continue; } walls.Add(new WallPosition(p, neighbour)); } visitedCells.Add(p); while (walls.Count > 0) { int wallIdx = random.Next() % walls.Count; WallPosition wall = walls[wallIdx]; walls.RemoveAt(wallIdx); if (visitedCells.Contains(wall.next)) { continue; } if (wall.cell.x == wall.next.x) { maze.cells[wall.cell.x, Math.Min(wall.cell.y, wall.next.y)] |= Maze.Passage.Top; } else { maze.cells[Math.Min(wall.cell.x, wall.next.x), wall.cell.y] |= Maze.Passage.Right; } p = wall.next; foreach (CellPosition neighbour in p.Neighbours()) { if (!IsValidCellPosition(maze, neighbour)) { continue; } walls.Add(new WallPosition(p, neighbour)); } visitedCells.Add(p); } // Then reduce number of walls to wallCount List <WallPosition> leftoverWalls = new List <WallPosition>(); for (int x = 0; x < maze.width; x++) { for (int y = 0; y < maze.height; y++) { if (x < maze.width - 1 && ((maze.cells[x, y] & Maze.Passage.Right) == Maze.Passage.None)) { leftoverWalls.Add(new WallPosition(new CellPosition(x, y), new CellPosition(x + 1, y))); } if (y < maze.height - 1 && ((maze.cells[x, y] & Maze.Passage.Top) == Maze.Passage.None)) { leftoverWalls.Add(new WallPosition(new CellPosition(x, y), new CellPosition(x, y + 1))); } } } while (leftoverWalls.Count > wallCount) { int wallIdx = random.Next() % leftoverWalls.Count; WallPosition wall = leftoverWalls[wallIdx]; if (wall.cell.x == wall.next.x) { maze.cells[wall.cell.x, Math.Min(wall.cell.y, wall.next.y)] |= Maze.Passage.Top; } else { maze.cells[Math.Min(wall.cell.x, wall.next.x), wall.cell.y] |= Maze.Passage.Right; } leftoverWalls.RemoveAt(wallIdx); } return(maze); }