/// <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);
    }