static void Main(string[] args) { // Get the input values from the user. GetInputParameters(); // Setup the matrix of squares, indicating the start, finish and obstacle cells. matrix = new CellIs[matrixWidth, matrixHeight]; matrix[startPoint.X, startPoint.Y] = CellIs.StartPoint; matrix[finishPoint.X, finishPoint.Y] = CellIs.FinishPoint; foreach (Point o in obstacles) { matrix[o.X, o.Y] = CellIs.Obstacle; } // Keep track of how many paths we find. solutionsFound = 0; // Open a log file so we can write out the paths we find. string logFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "WPC25-PathsFound.txt"); sw = new StreamWriter(logFile); WriteLogFileHeader(); DrawMatrix(); Console.WriteLine("Press any key to proceed..."); Console.ReadLine(); // We use an object to keep track of values as we recurse back and forth along test paths. // This is the initial object containing the starting point A. Cell startingCell = new Cell(); startingCell.CurrentCell = startPoint; startingCell.PreviousCell = new Point(-1, -1); startingCell.MoveCount = 0; message = "Valid paths are shown below"; Console.WriteLine(message); sw.WriteLine(message); // Start recursing... CheckCell(startingCell); // Write messages to user an log. message = string.Format("Success!! Number of paths found = {0}", solutionsFound); Console.WriteLine(message); sw.WriteLine(); sw.WriteLine(message); sw.Close(); // Wait for user to close the console. Console.ReadLine(); }
private static StreamWriter sw; // To write paths found to a log file #endregion Fields #region Methods /// <summary> /// The interesting bit that checks whether a cell is suitable for a candidate path. /// </summary> /// <param name="tracker">An object that keeps track of key variables for a cell /// along a candidate path. It allows us to use recursion to go forwards and /// backwards along the path.</param> /// <returns>True if we reached the target (finish) cell; false otherwise.</returns> private static bool CheckCell(Cell tracker) { Cell clone; #if SHOWPATHSCHECKED DrawMatrix(); #endif // Check if we've reached the finish point if (tracker.CurrentCell == finishPoint) { // We've reached the finish cell so check whether the path consists of the required // number of cells. if (tracker.MoveCount == pathLength) { // It's a real McCoy. solutionsFound++; DrawMatrix(); } return true; } if (tracker.MoveCount >= pathLength) { // Reset the current cell to an empty one matrix[tracker.CurrentCell.X, tracker.CurrentCell.Y] = CellIs.Empty; #if SHOWPATHSCHECKED DrawMatrix(); #endif return false; } // Get the state of the cells adjoining the current one CellIs cellAboveState = GetAdjoiningCellState(Direction.UP, tracker); CellIs cellRightState = GetAdjoiningCellState(Direction.RIGHT, tracker); CellIs cellBelowState = GetAdjoiningCellState(Direction.DOWN, tracker); CellIs cellLeftState = GetAdjoiningCellState(Direction.LEFT, tracker); // If it's ok to move up, do so if (cellAboveState == CellIs.Empty || cellAboveState == CellIs.FinishPoint) { // Mark the cell as on the path if (cellAboveState == CellIs.Empty) matrix[tracker.CurrentCell.X, tracker.CurrentCell.Y + 1] = CellIs.PathCell; clone = new Cell(tracker); // Bump the counter that keeps track of how many cells are along the path. if (++clone.MoveCount > pathLength) return false; // As we're moving, set the previous cell to the current one. clone.PreviousCell.X = clone.CurrentCell.X; clone.PreviousCell.Y = clone.CurrentCell.Y; // And then move to the cell above clone.CurrentCell.Y++; // And check that. if (CheckCell(clone)) { // Reset the current cell matrix[tracker.CurrentCell.X, tracker.CurrentCell.Y] = CellIs.Empty; #if SHOWPATHSCHECKED // Draw the matrix for checking purposes if we're in debug mode DrawMatrix(); #endif return false; } } // If it's OK to move right, do so if (cellRightState == CellIs.Empty || cellRightState == CellIs.FinishPoint) { // Mark the cell as on the path if (cellRightState == CellIs.Empty) matrix[tracker.CurrentCell.X + 1, tracker.CurrentCell.Y] = CellIs.PathCell; clone = new Cell(tracker); // Bump the counter that keeps track of how many cells are along the path. if (++clone.MoveCount > pathLength) return false; // As we're moving, set the previous cell to the current one. clone.PreviousCell.X = clone.CurrentCell.X; clone.PreviousCell.Y = clone.CurrentCell.Y; // And then move to the cell to the right clone.CurrentCell.X++; // And check that. if (CheckCell(clone)) { // Reset the current cell matrix[tracker.CurrentCell.X, tracker.CurrentCell.Y] = CellIs.Empty; #if SHOWPATHSCHECKED // Draw the matrix for checking purposes if we're in debug mode DrawMatrix(); #endif return false; } } // If it's ok to move down, do so if (cellBelowState == CellIs.Empty || cellBelowState == CellIs.FinishPoint) { // Mark the cell as on the path if (cellBelowState == CellIs.Empty) matrix[tracker.CurrentCell.X, tracker.CurrentCell.Y - 1] = CellIs.PathCell; clone = new Cell(tracker); // Bump the counter that keeps track of how many cells are along the path. if (++clone.MoveCount > pathLength) return false; // As we're moving, set the previous cell to the current one. clone.PreviousCell.X = clone.CurrentCell.X; clone.PreviousCell.Y = clone.CurrentCell.Y; // And then move to the cell below clone.CurrentCell.Y--; // And check that. if (CheckCell(clone)) { // Reset the current cell matrix[tracker.CurrentCell.X, tracker.CurrentCell.Y] = CellIs.Empty; #if SHOWPATHSCHECKED // Draw the matrix for checking purposes if we're in debug mode DrawMatrix(); #endif return false; } } // If it's OK to move left, do so if (cellLeftState == CellIs.Empty || cellLeftState == CellIs.FinishPoint) { // Mark the cell as on the path if (cellLeftState == CellIs.Empty) matrix[tracker.CurrentCell.X - 1, tracker.CurrentCell.Y] = CellIs.PathCell; clone = new Cell(tracker); // Bump the counter that keeps track of how many cells are along the path. if (++clone.MoveCount > pathLength) return false; // As we're moving, set the previous cell to the current one. clone.PreviousCell.X = clone.CurrentCell.X; clone.PreviousCell.Y = clone.CurrentCell.Y; // And then move to the cell to the left clone.CurrentCell.X--; // And check that. if (CheckCell(clone)) { // Reset the current cell matrix[tracker.CurrentCell.X, tracker.CurrentCell.Y] = CellIs.Empty; #if SHOWPATHSCHECKED // Draw the matrix for checking purposes if we're in debug mode DrawMatrix(); #endif return false; } } // Reset the current cell to an empty one if (matrix[tracker.CurrentCell.X, tracker.CurrentCell.Y] != CellIs.StartPoint) matrix[tracker.CurrentCell.X, tracker.CurrentCell.Y] = CellIs.Empty; #if SHOWPATHSCHECKED // Draw the matrix for checking purposes if we're in debug mode DrawMatrix(); #endif return false; }
/// <summary> /// Gets the state of a cell adjacent to the specified one. /// </summary> /// <param name="direction">The direction to look in (left, right, up or down)</param> /// <param name="cell">The reference cell.</param> /// <returns>Whether the cell is empty, the start or finish point, an obstacle or /// one that's on the current path</returns> private static CellIs GetAdjoiningCellState(Direction direction, Cell cell) { int xOffset = 0; int yOffset = 0; if (direction == Direction.UP && cell.CurrentCell.Y + 1 < matrix.GetLength(1)) yOffset = 1; else if (direction == Direction.DOWN && cell.CurrentCell.Y - 1 >= 0) yOffset = -1; else if (direction == Direction.RIGHT && cell.CurrentCell.X + 1 < matrix.GetLength(0)) xOffset = 1; else if (direction == Direction.LEFT && cell.CurrentCell.X - 1 >= 0) xOffset = -1; else return CellIs.InvalidCell; return matrix[cell.CurrentCell.X + xOffset, cell.CurrentCell.Y + yOffset]; }