/// <summary> /// Returns a two dimensional grid where each field contains the distance from the start point (the empty field). /// </summary> /// <returns>The path.</returns> /// <param name="gameGrid">Game grid.</param> /// <param name="fromLocation">the location to start from.</param> /// <param name="currentActiveTreasure">The current active treasre can always be stepped onto.</param> public static Grid2D<int> PreparePathGrid(GameFieldGrid gameGrid, GridLocation fromLocation, TreasureType currentActiveTreasure) { if(gameGrid == null) { throw new ArgumentNullException ("gameGrid"); } if(fromLocation == null) { throw new ArgumentNullException ("fromLocation"); } // Create a grid as big as the game field. The content of each item is the distance from the staring point (the empty spot). var pathGrid = new Grid2D<int> (gameGrid.Rows, gameGrid.Columns, pathFindingMaxVal); // Use a Disjkstra algorithm to find a path from the empty spot to the current active treasure. // First, set the presumed target location to a distance of 0. pathGrid.SetItem (fromLocation, 0); // Start calculating distances. while(true) { // Set to true if at least one field was changed. If nothing is changed during one loop, we're done. bool gridChanged = false; // Loop all fields until each field contains a distance value. for (int row = 0; row < gameGrid.Rows; row++) { for (int col = 0; col < gameGrid.Columns; col++) { // Distance is one more than it was at the current location. Set for the surrounding fields. int newDistance = pathGrid.GetItem (row, col); if(newDistance != pathFindingMaxVal) { newDistance++; } var checkLocations = AIHelpers.GetAccessibleAdjacentLocations(gameGrid, new GridLocation(row, col), currentActiveTreasure); foreach(var checkLocation in checkLocations) { // Remember the distance to the start point. int currentDistance = pathGrid.GetItem (checkLocation); if(newDistance < currentDistance) { pathGrid.SetItem (checkLocation, newDistance); gridChanged = true; } } } } // Bail out of the algorithm if we visited all nodes. if(!gridChanged) { break; } } return pathGrid; }