0
点赞
收藏
分享

微信扫一扫

2.15_knight_tour_骑士周游问题 (深度优先 DFS)

def legal_moves(x, y, bd_size):
    """
    :param x: x 坐标
    :param y: y 坐标
    :param bd_size: 格子数
    :return: 当前格子下一步的所有合法走棋位置
    """

    new_moves = []
    # "马走日"的 8 个格子
    direction = [(-1, -2), (-1, 2), (-2, -1), (-2, 1),
                 (1, -2), (1, 2), (2, -1), (2, 1)]

    for d in direction:
        new_x = x + d[0]
        new_y = y + d[1]
        # 确认不会走出棋盘
        if 0 <= new_x < bd_size and 0 <= new_y < bd_size:
            new_moves.append((new_x, new_y))

    return new_moves
def knight_graph(bd_size):
    """构建走棋的关系图"""

    graph = Graph()

    # 遍历每个格子
    for row in range(bd_size):
        for col in range(bd_size):
            node_id = pos_to_node_id(row, col, bd_size)
            # 单步合法走棋
            new_pos = legal_moves(row, col, bd_size)
            print(new_pos)

            # 把"所有合法走棋的顶点"和"当前点"形成的边,添加进去
            for p in new_pos:
                new_id = pos_to_node_id(p[0], p[1], bd_size)
                graph.add_edge(node_id, new_id)

    return graph


def pos_to_node_id(row, col, bd_size):
    """给每个格子编号"""

    return row * bd_size + col

 

def knight_tour(n, path, u, limit):
    """
    :param n: 层次 (步数)
    :param path: 路径
    :param u: 当前顶点
    :param limit: 搜索总深度
    :return:
    """

    # 标记当前顶点,并加入路径列表
    u.set_color('gray')
    path.append(u)

    # 对所有合法走棋逐一深入
    if n < limit:
        nbr_list = list(u.get_connections())
        # print(nbr_list)
        # nbr_list.sort(key=lambda x: x[0])
        # print(nbr_list)
        i = 0
        done = False

        # 选择未发现 (white) 的顶点深入
        while i < len(nbr_list) and not done:
            if nbr_list[i].get_color() == 'white':
                # 递归调用,层次 += 1
                done = knight_tour(n + 1, path, nbr_list[i], limit)
            i += 1

        # 若都无法完成预期深度,回溯,试本层下一个顶点
        if not done:
            path.pop()
            u.set_color('white')
    else:
        done = True
    return done

 

举报

相关推荐

0 条评论