You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

8拼图AI游戏BFS算法实现出现无限循环问题如何解决

问题根因

  • 第一,无解状态判断缺失:8拼图只有当初始状态和目标状态的逆序数奇偶性一致时才有解,如果你传入的初始状态本身无解,BFS会遍历完所有可达状态才退出,过程中看起来就是无限循环。
  • 第二,状态查重效率极低:你用list存储explored已访问集合和frontier队列,Python中列表的in操作是*O(n)*时间复杂度,8拼图总共有9! = 362880种合法状态,当状态量上来后,每次查重要遍历数万甚至数十万元素,运行速度会指数级变慢,看起来和无限循环没有区别。
  • 第三,队列操作效率低:用普通列表的pop(0)实现出队也是*O(n)*时间复杂度,队列越长操作越慢,进一步加剧性能问题。

修复方案

1. 新增逆序数校验逻辑

8拼图的可解性判断规则:去掉空位0,统计所有数字前面比它大的数字的总个数,初始和目标的逆序数奇偶性相同才有解,在BFS开始前加这个校验,无解直接返回避免无意义遍历。

2. 替换查重存储结构

把explored从列表改成集合,状态存成不可变的tuple类型(列表无法存入集合),集合的in操作是*O(1)*时间复杂度,可将查重效率提升上千倍。

3. 替换队列实现

用Python内置的collections.deque实现队列,popleft()操作是*O(1)*时间复杂度,大幅提升出队效率。

4. 优化状态生成逻辑避免分支写错

以下是修复后的可运行代码:

from collections import deque

goalState = [0, 1, 2, 3, 4, 5, 6, 7, 8]

# 计算逆序数奇偶性 用于判断可解性
def count_inversion(state):
    nums = [x for x in state if x != 0]
    count = 0
    for i in range(len(nums)):
        for j in range(i):
            if nums[j] > nums[i]:
                count += 1
    return count % 2

def switch(lst, index1, index2):
    newList = lst.copy()
    newList[index1], newList[index2] = newList[index2], newList[index1]
    return tuple(newList)

def getNextStates(state):
    nextStates = []
    state_list = list(state)
    emptyTile = state_list.index(0)
    # 上下左右四个方向的位置偏移量
    dirs = [-3, 3, -1, 1]
    for d in dirs:
        new_pos = emptyTile + d
        if 0 <= new_pos < 9:
            # 避免左右移动跨行的非法情况
            if d == -1 and emptyTile % 3 == 0:
                continue
            if d == 1 and emptyTile % 3 == 2:
                continue
            nextStates.append(switch(state_list, emptyTile, new_pos))
    return nextStates

def breadthFirst(initialState, goal):
    global exploredCount, visitedCount
    # 先校验是否有解
    if count_inversion(initialState) != count_inversion(goal):
        print("当前初始状态无解")
        return None
    exploredCount = 1
    visitedCount = 0
    initial = tuple(initialState)
    goal_tuple = tuple(goal)
    frontier = deque([initial])
    explored = set()
    print("开始遍历....")
    while frontier:
        state = frontier.popleft()
        if state == goal_tuple:
            print("找到目标状态")
            return list(state)
        explored.add(state)
        visitedCount += 1
        nextStates = getNextStates(state)
        for next_state in nextStates:
            if next_state not in explored and next_state not in frontier:
                frontier.append(next_state)
                exploredCount += 1
    return initialState

内容的提问来源于stack exchange,提问作者h0sny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 06:57:03