/// <summary> /// A* search pathfinding. /// </summary> /// <returns>Shortest path</returns> public List <ButtonNode> FindPath() { // Reset the lists openNodes.Clear(); closedNodes.Clear(); nextNodes.Clear(); // Add the start node as the first node to evaluate openNodes.Add(new ButtonNode(gridManager.StartNode.Coordinates[0], gridManager.StartNode.Coordinates[1])); // Create a goal node from the goal button goalNode = new ButtonNode(gridManager.GoalNode.Coordinates[0], gridManager.GoalNode.Coordinates[1]); // As long as there is a possible path while (openNodes.Count != 0) { ButtonNode currentNode; int newNodeIndex = 0; if (openNodes.Count != 1) { // Get the index of the node with the lowest "f" distance int minDistance = 100000; for (int i = 0; i < openNodes.Count; i++) { currentNode = openNodes[i]; if (currentNode.CombinedDistance < minDistance) { minDistance = currentNode.DistanceToGoal; newNodeIndex = i; } } } // Pop it from the list currentNode = openNodes[newNodeIndex]; openNodes.RemoveAt(newNodeIndex); // Get neighbour nodes FindNextNodes(currentNode); // Check if any are possible paths for (int i = 0; i < nextNodes.Count; i++) { ButtonNode newNode = nextNodes[i]; // If the node is actually a goal node if (newNode.Equals(goalNode)) { // Get all the previous nodes from this path List <ButtonNode> pathNodes = new List <ButtonNode>(); ButtonNode pathNode = currentNode; while (pathNode.Parent != null) { pathNodes.Add(pathNode); pathNode = pathNode.Parent; } return(pathNodes); } // Calculate the distances needed to determine if this node is any good newNode.DistanceFromStart = currentNode.DistanceFromStart + 1; newNode.DistanceToGoal = Mathf.Abs(newNode.X - goalNode.X) + Mathf.Abs(newNode.Y - goalNode.Y); newNode.CombinedDistance = newNode.DistanceFromStart + newNode.DistanceToGoal; // If there is a node with the same coordinates in the "frontier" list // and it has a smaller combined distance skip this node if (CheckOpenList(newNode)) { continue; } // If there isn't a node with the same coordinates in the "closed" list // with a smaller combined distance, then add it to the "frontier" list if (!CheckClosedList(newNode)) { openNodes.Add(newNode); } } // Add the used node to the closed list closedNodes.Add(currentNode); } return(null); }