def a_star(board, heuristic):
    """
    A*算法主题

    :param board: 要解决的游戏
    :param heuristic: 选择的启发函数
    :return: 返回的解的路径
    """

    frontier = PriorityQueue()
    node = Node(board)
    frontier.add(node, heuristic(node.data) + len(node.path()) - 1)

    explored = []

    while frontier.has_next():
        node = frontier.pop()

        if node.data.is_solved():
            return node.path()

        for move in node.data.legal_moves():
            child = Node(node.data.forecast(move), node)
            if (not frontier.has(child)) and (child.data not in explored):
                frontier.add(child,
                             heuristic(child.data) + len(child.path()) - 1)
            elif frontier.has(child):
                child_value = heuristic(child.data) + len(child.path()) - 1
                if child_value < frontier.get_value(child):
                    frontier.remove(child)
                    frontier.add(child, child_value)

        explored.append(node.data)

    return None
Exemplo n.º 2
0
def a_star(board, heuristic):
    """
    solves the board using the A* approach accompanied by the heuristic function

    :param board: board to solve
    :param heuristic: heuristic function
    :return: path to solution, and number of explored nodes
    """

    frontier = PriorityQueue()
    node = Node(board)
    frontier.add(node, heuristic(node.data) + len(node.path()) - 1)

    explored = []

    while frontier.has_next():
        node = frontier.pop()

        # check if solved
        if node.data.is_solved():
            return node.path(), len(explored) + 1

        # add children to frontier
        for move in node.data.legal_moves():
            child = Node(node.data.forecast(move), node)
            # child must not have already been explored
            if (not frontier.has(child)) and (child.data not in explored):
                frontier.add(child,
                             heuristic(child.data) + len(child.path()) - 1)
            # if the child is already in the frontier, it can be added only if it's better
            elif frontier.has(child):
                child_value = heuristic(child.data) + len(child.path()) - 1
                if child_value < frontier.get_value(child):
                    frontier.remove(child)
                    frontier.add(child, child_value)

        explored.append(node.data)

    return None, len(explored)