Beispiel #1
0
        /// <summary>
        /// Marks the square in the matrix to indicate the direction we're moving through the
        /// square.  This allows us to render the path simply using ASCII art.
        /// </summary>
        /// <param name="tracker">The current square in the maze that we're looking at</param>
        /// <param name="outDirection">The direction the path takes when leaving the current 
        /// tracker square (up, right, down or left).</param>
        private static void MarkTravelDirection(Square tracker, Direction outDirection)
        {
            SquareState currentSquareTravel = SquareState.OnThePath;

            if (outDirection == Direction.UP)
            {
                if (tracker.CurrentSquare == startingSquare.CurrentSquare)
                {
                    return;
                }
                else if (tracker.PreviousSquare.X == tracker.CurrentSquare.X)
                {
                    currentSquareTravel = SquareState.TravelNS;
                }
                else if (tracker.PreviousSquare.X - 1 == tracker.CurrentSquare.X)
                {
                    currentSquareTravel = SquareState.TravelNE;
                }
                else if (tracker.PreviousSquare.X + 1 == tracker.CurrentSquare.X)
                {
                    currentSquareTravel = SquareState.TravelNW;
                }
            }
            else if (outDirection == Direction.RIGHT)
            {
                if (tracker.CurrentSquare == startingSquare.CurrentSquare)
                {
                    return;
                }
                else if (tracker.PreviousSquare.Y == tracker.CurrentSquare.Y)
                {
                    currentSquareTravel = SquareState.TravelWE;
                }
                else if (tracker.PreviousSquare.Y - 1 == tracker.CurrentSquare.Y)
                {
                    currentSquareTravel = SquareState.TravelNE;
                }
                else if (tracker.PreviousSquare.Y + 1 == tracker.CurrentSquare.Y)
                {
                    currentSquareTravel = SquareState.TravelSE;
                }
            }
            else if (outDirection == Direction.DOWN)
            {
                if (tracker.CurrentSquare == startingSquare.CurrentSquare)
                {
                    return;
                }
                else if (tracker.PreviousSquare.X == tracker.CurrentSquare.X)
                {
                    currentSquareTravel = SquareState.TravelNS;
                }
                else if (tracker.PreviousSquare.X - 1 == tracker.CurrentSquare.X)
                {
                    currentSquareTravel = SquareState.TravelSE;
                }
                else if (tracker.PreviousSquare.X + 1 == tracker.CurrentSquare.X)
                {
                    currentSquareTravel = SquareState.TravelSW;
                }
            }
            else if (outDirection == Direction.LEFT)
            {
                if (tracker.CurrentSquare == startingSquare.CurrentSquare)
                {
                    return;
                }
                else if (tracker.PreviousSquare.Y == tracker.CurrentSquare.Y)
                {
                    currentSquareTravel = SquareState.TravelWE;
                }
                else if (tracker.PreviousSquare.Y - 1 == tracker.CurrentSquare.Y)
                {
                    currentSquareTravel = SquareState.TravelNW;
                }
                else if (tracker.PreviousSquare.Y + 1 == tracker.CurrentSquare.Y)
                {
                    currentSquareTravel = SquareState.TravelSW;
                }
            }

            matrix[tracker.CurrentSquare.X, tracker.CurrentSquare.Y] = currentSquareTravel;
        }
Beispiel #2
0
        /// <summary>
        /// Gets the state of a square adjacent to the specified one.
        /// </summary>
        /// <param name="direction">The direction to look in (left, right, up or down)</param>
        /// <param name="square">The reference square.</param>
        /// <returns>Whether the square is empty, the start or finish point, an obstacle or 
        /// one that's on the current path</returns>
        private static SquareState GetAdjoiningSquareState(Direction direction, Square square)
        {
            int xOffset = 0;
            int yOffset = 0;

            if (direction == Direction.UP && square.CurrentSquare.Y + 1 < SquareSize)
                yOffset = 1;
            else if (direction == Direction.DOWN && square.CurrentSquare.Y - 1 >= 0)
                yOffset = -1;
            else if (direction == Direction.RIGHT && square.CurrentSquare.X + 1 < SquareSize)
                xOffset = 1;
            else if (direction == Direction.LEFT && square.CurrentSquare.X - 1 >= 0)
                xOffset = -1;
            else
                return SquareState.InvalidSquare;

            return matrix[square.CurrentSquare.X + xOffset, square.CurrentSquare.Y + yOffset];
        }
Beispiel #3
0
        /// <summary>
        /// All good things have to start somewhere.
        /// </summary>
        /// <param name="args">None, ignored.</param>
        static void Main(string[] args)
        {
            // Setup a matrix to test with.
            matrix = SetupMatrixTest(grid1);

            // Open a log file so we can write out the paths we find.
            string logFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "WPC35-solutions.txt");
            sw = new StreamWriter(logFile);
            sw.WriteLine("Olimex Weekend Programming Challenge 35 - 30 Nov 2013");
            sw.WriteLine("-----------------------------------------------------");
            sw.WriteLine();

            // Starting square
            startingSquare = new Square(0, 0);
            startingSquare.PreviousSquare = new Point(-1, -1);
            startingSquare.SquareCounter = 1;

            // Start recursing...
            CheckSquare(startingSquare);

            // Finished.  Close the log file.
            string message = string.Format("Finished!!  Number of paths found = {0}", solutionsFound);
            Console.WriteLine();
            Console.WriteLine(message);
            sw.WriteLine();
            sw.WriteLine(message);
            sw.Close();

            // Wait for user to close the console.
            Console.ReadLine();
        }
Beispiel #4
0
        /// <summary>
        /// The main recursion routine that checks whether a square is valid for the current path and
        /// moves the path along to that square.  Then we call ourself again to recurse further along 
        /// the path.
        /// </summary>
        /// <param name="tracker">The current square we're looking at in the maze.</param>
        /// <returns>true when a valid solutin is found (all squares occupied); false otherwise</returns>
        private static bool CheckSquare(Square tracker)
        {
            Square clone;

            // Check if we've reached the start/finish point
            if (tracker.CurrentSquare == startingSquare.CurrentSquare)
            {
                // Check whether all the squares in the maze are occupied.  If they are, we have
                // a valid solution.
                if (AllSquaresFilled())
                {
                    // It's a valid path!
                    solutionsFound++;
                    DrawSolutionPath();
                    return true;
                }
            }

            // We could have occupied all squares in the maze but hit a dead-end.  This detects that
            // and quits the recursion to back-track to the previous square.
            if (tracker.SquareCounter >= targetLength)
            {
                // Reset the current square to an empty one
                matrix[tracker.CurrentSquare.X, tracker.CurrentSquare.Y] = SquareState.Empty;
                return false;
            }

            // Get the state of the squares adjoining the current one
            SquareState squareAboveState = GetAdjoiningSquareState(Direction.UP,    tracker);
            SquareState squareRightState = GetAdjoiningSquareState(Direction.RIGHT, tracker);
            SquareState squareBelowState = GetAdjoiningSquareState(Direction.DOWN,  tracker);
            SquareState squareLeftState  = GetAdjoiningSquareState(Direction.LEFT,  tracker);

            // If it's OK to move up, do so
            if (squareAboveState == SquareState.Empty || squareAboveState == SquareState.StartFinish)
            {
                // Mark the square as being on the path.
                if (squareAboveState == SquareState.Empty || squareLeftState == SquareState.StartFinish)
                    MarkTravelDirection(tracker, Direction.UP);

                // Create a clone of the current square to pass into the next recursion
                clone = new Square(tracker);

                // Bump the counter that keeps track of the number of squares are along the path
                clone.SquareCounter++;

                // Move to the square above
                clone.PreviousSquare.X = clone.CurrentSquare.X;
                clone.PreviousSquare.Y = clone.CurrentSquare.Y;
                clone.CurrentSquare.Y++;

                // And check that.
                if (CheckSquare(clone))
                {
                    // Reset the current square
                    matrix[tracker.CurrentSquare.X, tracker.CurrentSquare.Y] = SquareState.Empty;
                    return false;
                }
            }

            // If it's OK to move right, do so
            if (squareRightState == SquareState.Empty || squareRightState == SquareState.StartFinish)
            {
                // Mark the square as being on the path.
                if (squareRightState == SquareState.Empty || squareLeftState == SquareState.StartFinish)
                    MarkTravelDirection(tracker, Direction.RIGHT);

                // Create a clone of the current square to pass into the next recursion
                clone = new Square(tracker);

                // Bump the counter that keeps track of the number of squares are along the path
                clone.SquareCounter++;

                // Move to the square to the right
                clone.PreviousSquare.X = clone.CurrentSquare.X;
                clone.PreviousSquare.Y = clone.CurrentSquare.Y;
                clone.CurrentSquare.X++;

                // And check that.
                if (CheckSquare(clone))
                {
                    // Reset the current square
                    matrix[tracker.CurrentSquare.X, tracker.CurrentSquare.Y] = SquareState.Empty;
                    return false;
                }
            }

            // If it's OK to move down, do so
            if (squareBelowState == SquareState.Empty || squareBelowState == SquareState.StartFinish)
            {
                // Mark the square as being on the path.
                if (squareBelowState == SquareState.Empty || squareLeftState == SquareState.StartFinish)
                    MarkTravelDirection(tracker, Direction.DOWN);

                // Create a clone of the current square to pass into the next recursion
                clone = new Square(tracker);

                // Bump the counter that keeps track of the number of squares are along the path
                clone.SquareCounter++;

                // Move to the square below
                clone.PreviousSquare.X = clone.CurrentSquare.X;
                clone.PreviousSquare.Y = clone.CurrentSquare.Y;
                clone.CurrentSquare.Y--;

                // And check that.
                if (CheckSquare(clone))
                {
                    // Reset the current square
                    matrix[tracker.CurrentSquare.X, tracker.CurrentSquare.Y] = SquareState.Empty;
                    return false;
                }
            }

            // If it's OK to move left, do so
            if (squareLeftState == SquareState.Empty || squareLeftState == SquareState.StartFinish)
            {
                // Mark the square as being on the path.
                if (squareLeftState == SquareState.Empty || squareLeftState == SquareState.StartFinish)
                    MarkTravelDirection(tracker, Direction.LEFT);

                // Create a clone of the current square to pass into the next recursion
                clone = new Square(tracker);

                // Bump the counter that keeps track of the number of squares are along the path
                clone.SquareCounter++;

                // Move to the square to the left
                clone.PreviousSquare.X = clone.CurrentSquare.X;
                clone.PreviousSquare.Y = clone.CurrentSquare.Y;
                clone.CurrentSquare.X--;

                // And check that.
                if (CheckSquare(clone))
                {
                    // Reset the current square
                    matrix[tracker.CurrentSquare.X, tracker.CurrentSquare.Y] = SquareState.Empty;
                    return false;
                }
            }

            // No more routes available from the current square so it's not viable.
            // As long as the current square is not the start/finish, clear it and go back to
            // the caller to try another route from the previous square along the path.
            if (matrix[tracker.CurrentSquare.X, tracker.CurrentSquare.Y] != SquareState.StartFinish)
            {
                matrix[tracker.CurrentSquare.X, tracker.CurrentSquare.Y] = SquareState.Empty;
            }

            return false;
        }