private HashSet <Cave> GetConnectionsHashSet(Cave currentCave) { HashSet <Cave> caveConnections = new HashSet <Cave>(); // We iterate i number of times through the CaveConnection jagged array, // i being the number of caves. Doing this, we can find out what caves can currentCave // move to, and we add them to the caveConnection HashSet. for (int i = 0; i < CavesGrid.NumberCaves; i++) { if (CavesGrid.CaveConnections[i][currentCave.CaveNumber - 1] == 1) { caveConnections.Add(HashCave.ElementAt(i)); } } return(caveConnections); }
public string SearchPath(int startingCave, int finishingCave) { // We iterate throughout all the caves and assign them a null parent, the cave number, calculate the F cost, // and add them to the HashSet HashCave. for (int i = 1; i <= finishingCave; i++) { Cave Cave = GetCaveObject(i); Cave.Parent = null; Cave.CalculateFCost(); Cave.CaveNumber = i; HashCave.Add(Cave); } // We then set the starting cave as the first element in the HashSet, and the finishing cave // as the last element in the HashSet Cave fromCave = HashCave.ElementAt(startingCave - 1); Cave toCave = HashCave.ElementAt(finishingCave - 1); // We set the boolean to true to be able to identify the goal cave toCave.IsLastCave = true; // We set the G Cost of the starting cave to 0, since it has no cost to travel from start cave // to start cave. We also calculate the H cost and the F cost. fromCave.GCost = 0; fromCave.HCost = Euclidean(fromCave, toCave); fromCave.CalculateFCost(); // We initialise the OpenList and add the initial cave to it. We also initialise // the ClosedList OpenList = new HashSet <Cave> { fromCave }; ClosedList = new HashSet <Cave>(); // Here is where the algorithm takes place. // While the OpenList is not empty we will keep running the algorithm. If the OpenList is empty, // that means we didn't find a valid path from start to end cave. while (OpenList.Count > 0) { // We set the currentCave as the one with lowest f cost from the OpenList. // If the cave with the lowest f cost is the last cave, that means we found a valid path // so we call the function CalculatePath passing the last cave parameter in order to // track the path backwards, from the last cave to the initial cave Cave currentCave = GetLowestFCostCave(OpenList); if (currentCave.IsLastCave == true) { return(CalculatePath(toCave)); } // If the currentCave is not the last cave, we remove it from the OpenList and // add it to the ClosedList, this way we won't have to visit that node again, unless // it proves to have a lower f cost than the current cave. OpenList.Remove(currentCave); ClosedList.Add(currentCave); // We search for all the caves that have a connection with the currentCave foreach (Cave connectedCave in GetConnectionsHashSet(currentCave)) { // If the connectedCave is already in the ClosedList, we check if the f cost of the stored version // has a lower or equal f cost, then we discard the currentCave. If no better version has been found, then // we remove it from the ClosedList and set it as a parent of currentCave. if (ClosedList.Contains(connectedCave)) { continue; } // We set the travellingCost as the currentCave G cost plus the Euclidean heuristic from the currentCave to the connectedCave double travellingCost = currentCave.GCost + Euclidean(currentCave, connectedCave); // We check if the travellingCost is inferior to the G cost of the connectedCave. If true, we update the G Cost of the connectedCave // to the travellingCost, calculate the H Cost and F Cost of the conectedCave, and set // the currentCave as a pconnectedCave's parent. if (travellingCost < connectedCave.GCost) { connectedCave.GCost = travellingCost; connectedCave.HCost = Euclidean(connectedCave, toCave); connectedCave.CalculateFCost(); connectedCave.Parent = currentCave; // If the OpenList doesn't contain the connectedCave, we add it to the OpenList. if (!OpenList.Contains(connectedCave)) { OpenList.Add(connectedCave); } } } } // If the OpenList is empty, we return 0 as we didn't find a valid path. return("0"); }