Exemple #1
0
        /// <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;
        }
Exemple #2
0
        /// <summary>
        /// Gets the fields that have to be followed to come to a specific location.
        /// </summary>
        /// <returns>The path to location.</returns>
        /// <param name="fromLocation">the location from where to start path finding. Must be the same that was passed to PreparePathGrid()</param>
        /// <param name="toLocation">the location to find the path to starting at the unused location.</param>
        /// <param name="gameGrid">Game grid.</param>
        /// <param name="pathGrid">Populated path grid.</param>
        /// <param name="currentActiveTreasure">The current active treasre can always be stepped onto.</param>
        public static List<GridLocation> GetPathToLocation(GameFieldGrid gameGrid, Grid2D<int> pathGrid, GridLocation fromLocation, GridLocation toLocation, TreasureType currentActiveTreasure)
        {
            if(gameGrid == null)
            {
                throw new ArgumentNullException ("gameGrid");
            }

            if(pathGrid == null)
            {
                throw new ArgumentNullException ("pathGrid");
            }

            if(toLocation == null)
            {
                throw new ArgumentNullException ("toLocation");
            }

            // This will hold the reversed path.
            var path = new List<GridLocation> {
                // The target always belongs to the path.
                new GridLocation (toLocation.Row, toLocation.Column)
            };

            // Loop until the path has been completed.
            while(true)
            {
                // From the current target location check all possible moves. The algorithm works its way from the target to the start, so the path will be reversed.
                var checkLocations = AIHelpers.GetAccessibleAdjacentLocations (gameGrid, toLocation, currentActiveTreasure, fromLocation);

                // Loop the possible moves and remember the one with the lowest distance towards the start location.
                int lowestDistance = pathFindingMaxVal;
                GridLocation lowestLocation = null;

                foreach(var adjacentLocation in checkLocations)
                {
                    int distance = pathGrid.GetItem (adjacentLocation);
                    if(distance < lowestDistance)
                    {
                        lowestDistance = distance;
                        lowestLocation = adjacentLocation;
                        // The new target location is the lowest of the possible locations.
                        toLocation = lowestLocation;
                    }
                }

                if(lowestLocation != null)
                {
                    // Insert at 0 to have the path in the correct reversed order.
                    path.Insert(0, lowestLocation);
                    if(lowestLocation.Equals(fromLocation))
                    {
                        // Reached the start location.
                        break;
                    }
                }
                else
                {
                    // No lowest location found. Bail out.
                    break;
                }
            }

            return path;
        }