Beispiel #1
0
            /// <summary>
            /// Returns the center square of the given sqaure's partition.
            /// </summary>
            /// <param name="sq"></param>
            /// <returns></returns>
            private MazeSquare ReferenceSquare(MazeSquare sq)
            {
                // x and y index of the current square's partition
                int px = sq.XPos * xPartitions / xSize, py = sq.YPos * yPartitions / ySize;

                // x and y coordinates of the selected partition's center square
                int xCenter = (2 * px + 1) * xSize / (2 * xPartitions);
                int yCenter = (2 * py + 1) * ySize / (2 * yPartitions);

                // Apply this partition's offset.
                if (xOffCenter != null && yOffCenter != null)
                {
                    xCenter += xOffCenter[px, py];
                    yCenter += yOffCenter[px, py];
                }

                // If defined: Find the vertex closest to the given square.
                if (vertices != null)
                {
                    MazeSquare closestVertex   = vertices[0];
                    double     closestDistance = Maze.Distance(sq, closestVertex);

                    for (int i = 1; i < vertices.Length; i++)
                    {
                        double d = Maze.Distance(sq, vertices[i]);
                        if (d < closestDistance)
                        {
                            closestVertex   = vertices[i];
                            closestDistance = d;
                        }
                    }

                    xCenter = closestVertex.XPos;
                    yCenter = closestVertex.YPos;
                }

                return(new MazeSquare(xCenter, yCenter));
            }
Beispiel #2
0
            public override bool[] PreferredDirections(MazeSquare sq)
            {
                bool[] result = new bool[4] {
                    false, false, false, false
                };

                #region Collect the distances of all neighbor squares (including diagonals) from the reference square.

                // Actually, this is the (absolute) difference between the distances of a neighbor square and sq itself.
                double[,] distances = new double[3, 3];

                // The distance of the current square to the reference square should be approximated.
                MazeSquare sq0 = this.ReferenceSquare(sq);
                double     d0  = Maze.Distance(sq, sq0);
                // Rounding to the next integer will approximate circles in 1 unit steps.
                if (approximateCircles)
                {
                    d0 = Math.Round(d0);
                }

                for (int i = -1; i <= +1; i++)
                {
                    for (int j = -1; j <= +1; j++)
                    {
                        // Note: this[x,y] is not defined outside the maze size.
                        MazeSquare sq1 = new MazeSquare(sq.XPos + i, sq.YPos + j);
                        distances[i + 1, j + 1] = (minimizeDistance ? +1 : -1) * Math.Abs(Maze.Distance(sq1, sq0) - d0);
                    }
                }

                #endregion

                #region Find a range of distances including the current square and two of the neighbors.

                double d1 = double.MaxValue, d2 = double.MaxValue;
                for (int i = 0; i < 3; i++)
                {
                    for (int j = 0; j < 3; j++)
                    {
                        if (i == 1 && j == 1)       // Discard the current square.
                        {
                            continue;
                        }
                        if (distances[i, j] >= d2)  // Discard distances greater than the current second best.
                        {
                            continue;
                        }
                        if (distances[i, j] >= d1)  // This is a new second best distance.
                        {
                            d2 = distances[i, j];
                        }
                        else                        // This is a new best distance.
                        {
                            d2 = d1;
                            d1 = distances[i, j];
                        }
                    }
                }

                #endregion

                #region Add the directions to the two best neighbors to the result.

                if (distances[1, 0] <= d2) // straight north
                {
                    result[(int)WallPosition.WP_N] = true;
                }
                if (distances[0, 1] <= d2) // straight west
                {
                    result[(int)WallPosition.WP_W] = true;
                }
                if (distances[1, 2] <= d2) // straight south
                {
                    result[(int)WallPosition.WP_S] = true;
                }
                if (distances[2, 1] <= d2) // straight east
                {
                    result[(int)WallPosition.WP_E] = true;
                }

                // For approximating a diagonal connection, we follow the closer path (unless this logic is inverted).
                if (distances[0, 0] <= d2) // north-west
                {
                    result[(int)((distances[1, 0] < distances[0, 1] == followDiagonals) ? WallPosition.WP_N : WallPosition.WP_W)] = true;
                }
                if (distances[2, 0] <= d2) // north-east
                {
                    result[(int)((distances[1, 0] < distances[2, 1] == followDiagonals) ? WallPosition.WP_N : WallPosition.WP_E)] = true;
                }
                if (distances[0, 2] <= d2) // south-west
                {
                    result[(int)((distances[1, 2] < distances[0, 1] == followDiagonals) ? WallPosition.WP_S : WallPosition.WP_W)] = true;
                }
                if (distances[2, 2] <= d2) // south-east
                {
                    result[(int)((distances[1, 2] < distances[2, 1] == followDiagonals) ? WallPosition.WP_S : WallPosition.WP_E)] = true;
                }

                #endregion
                return(result);
            }