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

Java迷宫求解程序Timer的actionPerformed方法未执行问题排查

问题分析与修复方案

先直击最核心的问题:你代码里只声明了TimerListener,但完全没实现这个类的actionPerformed方法!这就是为什么你感觉能进入类但逻辑完全没执行的根本原因——这个类根本没有要执行的逻辑载体啊!

1. 先补全TimerListener类的实现

你需要把TimerListener写成实现ActionListener的内部类,并且在actionPerformed里触发迷宫求解的逻辑,比如:

class TimerListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        // 启动迷宫求解
        ArrayList<Integer> solution = findSolution(maze, startX, startY);
        if (solution != null) {
            // 找到解后停止Timer,避免重复求解
            ((Timer)e.getSource()).stop();
            // 将解传递给绘制组件,更新界面
            component.setSolutionPath(solution);
            repaint();
        }
    }
}

没有这个实现,Timer根本不知道要做什么,自然不会执行任何操作。

2. 修复findSolution方法的关键错误

你的搜索算法存在一堆逻辑问题,就算Timer工作了也找不到解,主要问题如下:

  • 边界判断错误:你用窗口的width/height(1000、700)判断迷宫边界,这完全不对!应该用迷宫数组的行列数:posx+1 < maze[0].length(列数)、posy+1 < maze.length(行数)。
  • 方向标记混乱:比如向上移动时你添加的是moveDown,完全搞反了,每个方向都要对应正确的标记。
  • 递归逻辑错误:你用else if判断四个方向,这意味着只会检查第一个满足条件的方向,不会回溯!应该改成独立的if分支,一个方向走不通就尝试下一个。
  • 终点判断逻辑颠倒:你现在判断的是当前位置是否为终点,但应该是判断移动后的位置是否为终点,或者先检查当前位置是否是终点再处理。
  • 已访问标记错误:应该先标记当前位置为已访问,避免重复走回头路。

修复后的findSolution示例:

private ArrayList<Integer> findSolution(int[][] board, int posx, int posy) {
    // 如果当前是终点,返回空列表表示到达
    if (board[posy][posx] == exitBlock) {
        return new ArrayList<>();
    }
    // 如果是墙或已访问,直接返回null
    if (board[posy][posx] == wallBlock || board[posy][posx] == visitedBlock) {
        return null;
    }

    // 标记当前位置为已访问
    int[][] newBoard = arrayCopy(board);
    newBoard[posy][posx] = visitedBlock;

    // 尝试四个方向,用独立if实现回溯
    // 向右
    if (posx + 1 < newBoard[0].length) {
        ArrayList<Integer> result = findSolution(newBoard, posx + 1, posy);
        if (result != null) {
            result.add(0, moveRight);
            return result;
        }
    }
    // 向下
    if (posy + 1 < newBoard.length) {
        ArrayList<Integer> result = findSolution(newBoard, posx, posy + 1);
        if (result != null) {
            result.add(0, moveDown);
            return result;
        }
    }
    // 向上
    if (posy - 1 >= 0) {
        ArrayList<Integer> result = findSolution(newBoard, posx, posy - 1);
        if (result != null) {
            result.add(0, moveUp);
            return result;
        }
    }
    // 向左
    if (posx - 1 >= 0) {
        ArrayList<Integer> result = findSolution(newBoard, posx - 1, posy);
        if (result != null) {
            result.add(0, moveLeft);
            return result;
        }
    }

    // 四个方向都走不通,返回null
    return null;
}

3. 补全DrawComponent的绘制逻辑

你贴的代码里DrawComponent没写完,连最核心的paintComponent方法都没有,这部分必须补全才能正确绘制迷宫和路径:

class DrawComponent extends JComponent {
    private int[][] maze;
    private ArrayList<Integer> solutionPath;

    private DrawComponent(int[][] maze) {
        this.maze = maze;
        this.solutionPath = new ArrayList<>();
    }

    private static final long serialVersionUID = 1L; // 补全序列化ID

    public void setSolutionPath(ArrayList<Integer> path) {
        this.solutionPath = path;
        repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        int blockWidth = getWidth() / maze[0].length;
        int blockHeight = getHeight() / maze.length;

        // 绘制迷宫基础块
        for (int y = 0; y < maze.length; y++) {
            for (int x = 0; x < maze[0].length; x++) {
                Color color;
                switch (maze[y][x]) {
                    case wallBlock: color = Color.BLACK; break;
                    case charBlock: color = Color.GREEN; break; // 起点
                    case exitBlock: color = Color.RED; break; // 终点
                    case visitedBlock: color = Color.LIGHT_GRAY; break;
                    default: color = Color.WHITE; // 空块
                }
                g.setColor(color);
                g.fillRect(x * blockWidth, y * blockHeight, blockWidth, blockHeight);
                // 绘制方块边框
                g.setColor(Color.BLACK);
                g.drawRect(x * blockWidth, y * blockHeight, blockWidth, blockHeight);
            }
        }

        // 绘制求解路径
        if (!solutionPath.isEmpty()) {
            int currentX = startX;
            int currentY = startY;
            g.setColor(Color.BLUE);
            for (int move : solutionPath) {
                switch (move) {
                    case moveRight: currentX++; break;
                    case moveDown: currentY++; break;
                    case moveUp: currentY--; break;
                    case moveLeft: currentX--; break;
                }
                g.fillRect(currentX * blockWidth, currentY * blockHeight, blockWidth, blockHeight);
                g.setColor(Color.BLACK);
                g.drawRect(currentX * blockWidth, currentY * blockHeight, blockWidth, blockHeight);
            }
        }
    }
}

4. 其他小细节修复

  • 添加主方法启动程序:
public static void main(String[] args) {
    SwingUtilities.invokeLater(() -> {
        homework11and12 frame = new homework11and12();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    });
}
  • loadMaze方法的循环改成动态判断迷宫大小:y < maze.length、x < maze[y].length,避免硬编码。
  • 类名遵循Java规范改成大驼峰:Homework11And12,提升代码可读性。

总结:最核心的问题是缺失TimerListener的actionPerformed实现,导致Timer没有触发求解逻辑;其次是搜索算法的逻辑错误。先解决这两个核心问题,再补全其他缺失代码,程序就能正常运行了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:12:23