static void Main(string[] args) { int[,] matrix = MatrixHelper.ReadMap(); int size = matrix.GetLength(0); int[] startPosition = Surveyor.GetStartEndPositions(matrix, startEndValue: 2); int[] endPosition = Surveyor.GetStartEndPositions(matrix, startEndValue: 1); List <int[]> shortestPath; int[,] listToArray; // couldn't find another way to convert only once but use in 2 places, needed for easier List<int[]> to int[,] comparison. PrintHeader(width: size); PrintContent(matrix, pathList: listToArray = null); // Basic map representation; with color coded walls, start & end positions. PrintFooter(width: size); Console.Write($"\nThe designated starting position coordinates (x, y) are: [ {startPosition[1]} , {startPosition[0]} ].\n" + $"The designated ending position coordinates (x, y) are: [ {endPosition[1]} , {endPosition[0]} ].\n" + "--------------------\n"); int[,] weightedMatrix = Surveyor.Surveying(matrix); Console.WriteLine("Survey complete. Looking for optimal path..\n" + "--------------------\n" + $"Survey data integrity (OK if > 1): {weightedMatrix.Length} ."); shortestPath = PathFinder.PathCounter(weightedMatrix, startPosition, endPosition); PrintResult(weightedMatrix, startPosition, endPosition, pathList: shortestPath); Console.WriteLine("\n--------------------\n"); listToArray = ListToArray(shortestPath); PrintContent(matrix, pathList: listToArray); // Basic map representation; with color coded walls, start & end positions, plus the shortest path. Console.WriteLine("\n--------------------\nEnd.\n"); }
/// <summary> /// Look around the current cell clockwise, using the 4 primary directions: up (x, y+1), right (x+1, y), down (x, y-1) and left (x-1, y). /// </summary> /// <param name="mapData">The matrix previously extracted from the input file.</param> /// <returns>The surveyed copy of the map where instead of 0-s the passable cell values are the cell-step distance from the starting cell.</returns> public static int[,] Surveying(int[,] mapData) { int[,] surveyData = new int[mapData.GetLength(0), mapData.GetLength(0)]; addDefaultSurveyData(surveyData); int[] startPos = GetStartEndPositions(mapData, startEndValue: 2); // The "startEndValue" value is found inside the "MapData" file. int[] endPos = GetStartEndPositions(mapData, startEndValue: 1); // Buffer, put here the just checked clear cells (did not already have a cost, no walls) to peek around next cycle. Queue <int[]> waiting = new Queue <int[]>(); // ----- The below arrays are Declared & Initialized here because they are parameters for more than one following code brackets. ----- // // --------------------------------- // // Start cell row & column indexes. int srowi = startPos[0]; int scoli = startPos[1]; // Set current position to the coordinates where the Survey will start -- from the End Goal ("endPos"). int[] curPos = endPos; int rowi = curPos[0]; int coli = curPos[1]; // Store coordinates of the cell we are looking at at any given time, around the current cell we are at. int[] lookingAt = new int[2]; int xi = lookingAt[0]; int yi = lookingAt[1]; // --------------------------------- // bool lookAtIsStart, lessThanIntMaxSize, isInsideBounds, isPassableCell; surveyData[rowi, coli] = 0; // Surveyor start coordinate's cell cost ; also the first discovered cell. waiting.Enqueue(curPos); while (waiting.Count != 0) { Array.Copy(waiting.Dequeue(), curPos, 2); // Take the next one from the queue as the current position to look around. rowi = curPos[0]; coli = curPos[1]; for (int cy = 1; cy <= 4; cy++) // Looking cycle: up, right, down, left. { lookingAt = MatrixHelper.SwitchView(rowi, coli, cy); xi = lookingAt[0]; yi = lookingAt[1]; isInsideBounds = isInside(mapData, xi, yi); if (isInsideBounds == false) { isPassableCell = false; } else { isPassableCell = isPassable(mapData, surveyData, xi, yi); } if (isInsideBounds == true && isPassableCell == true) { // Booleans. lessThanIntMaxSize = (surveyData[rowi, coli] + 1 <= int.MaxValue); lookAtIsStart = (xi == srowi && yi == scoli); if (lookAtIsStart) { // Check against too large matrix size. // Since each cell is given an "integer" type weight, if the area is too big the value could reach past the type's maximum value. if (lessThanIntMaxSize) { surveyData[xi, yi] = surveyData[rowi, coli] + 1; return(surveyData); } else { throw new OverflowException("ERROR.. There are too many cells to map with BFS."); } } if (lessThanIntMaxSize) { surveyData[xi, yi] = surveyData[rowi, coli] + 1; int[] t = new int[2]; Array.Copy(lookingAt, t, lookingAt.Length); waiting.Enqueue(t); // Place what was just marked in the queue to be looked around later. } else { throw new OverflowException("ERROR.. There are too many cells to map with BFS."); } } } } lookAtIsStart = (xi == srowi && yi == scoli); if (lookAtIsStart) { Console.WriteLine($"FINALLY.. Print out weighted matrix; {yi}, {xi} ."); return(surveyData); } else { Console.WriteLine("ERROR.. Target coordinates cannot be reached!\n" + "Check \"MapData.txt\" making sure there is NO obstruction between the desired Start and End positions."); return(new int[0, 0]); } }