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
相关产品推荐
相关产品推荐

