Example #1
0
        /// <summary>
        /// Solves the specified maze.
        /// </summary>
        /// <param name="maze">The maze.</param>
        /// <param name="start">The start.</param>
        /// <param name="end">The end.</param>
        /// <returns>The solution.</returns>
        public IEnumerable<Cell> Solve(bool[,] maze, Cell start, Cell end)
        {
            var stack = new Stack<Cell>();
            stack.Push(start);

            var visited = new bool[maze.GetLength(0), maze.GetLength(1)];
            var previousCell = new Cell[maze.GetLength(0), maze.GetLength(1)];

            Func<Cell, bool> hasRightWall = cell => maze[cell.I, cell.J + 1];
            Func<Cell, bool> hasLeftWall = cell => maze[cell.I, cell.J - 1];
            Func<Cell, bool> hasTopWall = cell => maze[cell.I - 1, cell.J];
            Func<Cell, bool> hasBottomWall = cell => maze[cell.I + 1, cell.J];

            while (stack.Count > 0)
            {
                var temp = stack.Pop();

                if (temp.Equals(end))
                {
                    var foundPath = new List<Cell>();
                    while (true)
                    {
                        foundPath.Add(temp);
                        if (temp.Equals(start))
                        {
                            break;
                        }

                        temp = previousCell[temp.I, temp.J];
                    }

                    foundPath.Reverse();
                    return foundPath;
                }

                visited[temp.I, temp.J] = true;

                if (!hasLeftWall(temp) && !visited[temp.I, temp.J - 2])
                {
                    stack.Push(new Cell(temp.I, temp.J - 2));
                    previousCell[temp.I, temp.J - 2] = temp;
                }

                if (!hasRightWall(temp) && !visited[temp.I, temp.J + 2])
                {
                    stack.Push(new Cell(temp.I, temp.J + 2));
                    previousCell[temp.I, temp.J + 2] = temp;
                }

                if (!hasTopWall(temp) && !visited[temp.I - 2, temp.J])
                {
                    stack.Push(new Cell(temp.I - 2, temp.J));
                    previousCell[temp.I - 2, temp.J] = temp;
                }

                if (!hasBottomWall(temp) && !visited[temp.I + 2, temp.J])
                {
                    stack.Push(new Cell(temp.I + 2, temp.J));
                    previousCell[temp.I + 2, temp.J] = temp;
                }
            }

            // no solution found
            return null;
        }
 /// <summary>
 /// Get the position for the specified cell.
 /// </summary>
 /// <param name="cell">
 /// The cell.
 /// </param>
 /// <param name="z">
 /// The z.
 /// </param>
 /// <returns>
 /// The position.
 /// </returns>
 private Point3D GetPosition(Cell cell, double z)
 {
     return this.GetPosition(cell.I, cell.J, z);
 }
Example #3
0
        /// <summary>
        /// Generates the maze.
        /// </summary>
        /// <returns>A maze.</returns>
        public bool[,] Generate()
        {
            int width = this.Width;
            int height = this.Height;

            if (width % 2 == 0)
            {
                throw new InvalidOperationException("Width must be an odd number");
            }

            if (height % 2 == 0)
            {
                throw new InvalidOperationException("Height must be an odd number");
            }

            bool[,] maze = new bool[height, width];

            // Initialize maze (all walls intact)
            for (int i = 0; i < height; i++)
            {
                for (int j = 0; j < width; j++)
                {
                    maze[i, j] = i % 2 == 0 || j % 2 == 0;
                }
            }

            var stack = new Stack<Cell>();
            var current = new Cell(1, 1);
            stack.Push(current);
            Func<int, int, bool> isVisited = (i, j) => maze[i - 1, j] && maze[i + 1, j] && maze[i, j - 1] && maze[i, j + 1];
            var random = new Random(this.Seed);

            while (stack.Count > 0)
            {
                var neighbours = new List<Cell>();
                int i = current.I;
                int j = current.J;

                // Find unvisited neighbours
                if (i > 1 && isVisited(i - 2, j))
                {
                    neighbours.Add(new Cell(i - 2, j));
                }

                if (j > 1 && isVisited(i, j - 2))
                {
                    neighbours.Add(new Cell(i, j - 2));
                }

                if (i + 2 < height && isVisited(i + 2, j))
                {
                    neighbours.Add(new Cell(i + 2, j));
                }

                if (j + 2 < width && isVisited(i, j + 2))
                {
                    neighbours.Add(new Cell(i, j + 2));
                }

                if (neighbours.Count > 0)
                {
                    var next = neighbours[random.Next(neighbours.Count)];

                    // break the wall between current and next cell
                    int ii = (next.I + current.I) / 2;
                    int jj = (next.J + current.J) / 2;
                    maze[ii, jj] = false;

                    stack.Push(current);
                    current = next;
                }
                else
                {
                    current = stack.Pop();
                }
            }

            return maze;
        }
        /// <summary>
        /// Creates the maze.
        /// </summary>
        private void CreateMaze()
        {
            // Generate the maze
            var mazeGenerator = new MazeGenerator2 { Width = 21, Height = 31 };
            this.maze = mazeGenerator.Generate();

            // Solve the maze
            var solver = new MazeSolver1();
            var start = new Cell(1, 1);
            var end = new Cell(this.maze.GetLength(0) - 2, this.maze.GetLength(1) - 2);
            var solution = solver.Solve(this.maze, start, end);

            int m = this.maze.GetUpperBound(0) + 1;
            int n = this.maze.GetUpperBound(1) + 1;
            this.offsetX = -m * 0.5;
            this.offsetY = -n * 0.5;

            this.WallsGeometry = this.CreateMazeGeometry(this.maze);
            this.GroundGeometry = this.CreateGroundGeometry(this.maze, 1, -0.005);
            this.SolutionGeometry = this.CreateSolutionGeometry(solution);
        }