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

八数码问题A*算法提示生成器无限循环问题求助

八数码提示生成器无限循环问题排查与修复

核心问题及修复方案:

  • Node类未重写equals和hashCode方法
    HashSet判断对象是否存在依赖这两个方法,默认的Object.equals只比较引用地址,导致同一个棋盘状态的不同Node实例会被判定为不同对象,已访问节点无法被正确过滤,最终引发无限循环。
    修复:给Node类重写这两个方法,基于棋盘的内容来计算哈希值和判断相等。

  • 曼哈顿距离计算错误
    finalBoard中空格是0,但你的代码里把数字n的目标位置计算为(n-1)/3和(n-1)%3,比如数字1的目标位置会被算成(0,0),但finalBoard里1在(0,1),这会导致启发函数失效,A*算法无法向目标方向搜索,进而陷入循环。
    修复:根据finalBoard的实际布局计算每个数字的目标坐标。

  • 全局board变量被错误修改
    在Hintgenerate方法中,你执行了board = span.board;,这会把全局的board替换为当前节点的棋盘,后续生成新节点时会基于错误的棋盘操作,导致状态混乱。
    修复:去掉这个赋值,直接使用span.board即可。

  • 找到目标后直接return,路径回溯代码未执行
    当isFinal(board)为true时,你设置goal = span;后直接return,导致后面的路径回溯、输出提示的代码完全没运行。
    修复:找到目标后跳出循环,继续执行后续逻辑。

  • 路径输出逻辑错误
    你用step.get(1)来输出第一步要移动的数字,这是错误的,反转后的step列表第一个元素就是第一步应该移动的数字,而且当只有一步时step.size()>1会跳过输出。
    修复:改为判断列表非空时取第一个元素。

关键修复代码示例:

Node类重写equals和hashCode:

class Node {
    int[][] board;
    int coRow, coCol, cost, depth;
    Node parent;

    Node(int[][] b, int x, int y, int d, Node node) {
        this.board = new int[b.length][b.length];
        for (int i = 0; i < b.length; i++) {
            this.board[i] = b[i].clone();
        }
        coRow = x; coCol = y;
        cost = Manhattan(b) + d; depth = d;
        parent = node;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Node node = (Node) o;
        for (int i = 0; i < dimension; i++) {
            for (int j = 0; j < dimension; j++) {
                if (this.board[i][j] != node.board[i][j]) {
                    return false;
                }
            }
        }
        return true;
    }

    @Override
    public int hashCode() {
        StringBuilder sb = new StringBuilder();
        for (int[] row : board) {
            for (int num : row) {
                sb.append(num).append(",");
            }
        }
        return sb.toString().hashCode();
    }
}

修正后的曼哈顿距离方法:

private int Manhattan(int[][] b) {
    int distance = 0;
    for (int i = 0; i < dimension; i++) {
        for (int j = 0; j < dimension; j++) {
            int num = b[i][j];
            if (num == -1) continue;
            int targetRow = 0, targetCol = 0;
            outer:
            for (int x = 0; x < dimension; x++) {
                for (int y = 0; y < dimension; y++) {
                    if (finalBoard[x][y] == num) {
                        targetRow = x;
                        targetCol = y;
                        break outer;
                    }
                }
            }
            distance += Math.abs(targetRow - i) + Math.abs(targetCol - j);
        }
    }
    return distance;
}

修正后的Hintgenerate方法关键部分:

public void Hintgenerate() {
    PriorityQueue<Node> Tree = new PriorityQueue<>(
        Comparator.comparingInt(n -> n.cost)
    );
    HashSet<Node> DeadEnd = new HashSet<>();
    ArrayList<Integer> step = new ArrayList<>();

    int[] negCo = NegCoordinate(-1, board);
    Tree.add(new Node(board, negCo[0], negCo[1], 0, null));

    Node goal = null;

    while (!Tree.isEmpty()) {
        Node span = Tree.poll();

        if (DeadEnd.contains(span)) continue;

        if (isFinal(span.board)) {
            goal = span;
            break;
        }

        DeadEnd.add(span);

        for (int i = 0; i < 4; i++) {
            int nextRow = span.coRow + moveRow[i];
            int nextCol = span.coCol + moveCol[i];
            if (nextCol > -1 && nextCol < dimension && nextRow > -1 && nextRow < dimension) {
                int[][] instBoard = new int[dimension][dimension];
                for (int r = 0; r < dimension; r++) {
                    instBoard[r] = span.board[r].clone();
                }

                instBoard[span.coRow][span.coCol] = instBoard[nextRow][nextCol];
                instBoard[nextRow][nextCol] = -1;

                Node newNode = new Node(instBoard, nextRow, nextCol, span.depth + 1, span);
            
                if (!DeadEnd.contains(newNode)) {
                    Tree.add(newNode);
                }
            }
        }
    }

    if (goal == null) {
        System.out.println("无解");
        return;
    }

    Node cur = goal;
    while (cur.parent != null) {
        step.add(cur.parent.board[cur.coRow][cur.coCol]);
        cur = cur.parent;
    }

    Collections.reverse(step);
    if (!step.isEmpty()) {
        System.out.println("应移动数字:" + step.get(0));
    } else {
        System.out.println("已处于目标状态");
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 17:27:02