Java迷宫项目:能否为方法设置运行时长实现小球自动寻路?
Hey there! Let's figure out how to make your CBallMaze auto-move the ball to the finish line with timed direction methods. Based on your existing Timer code, here are a few practical solutions tailored to your needs:
Before handling timing, you'll need to calculate a valid path from the ball's start position to the end. Breadth-First Search (BFS) is perfect for grid mazes like this—it guarantees the shortest path. Once you have a sequence of directions (e.g., UP → RIGHT → DOWN), you can feed these steps into a scheduler to execute them with delays.
Swing's Timer is ideal for UI-related tasks since it runs on the Event Dispatch Thread (EDT), avoiding UI glitches. Here's how to adapt it to execute timed moves:
Step 1: Add Path & State Variables
First, add these to your class to track the auto-move sequence:
private enum Direction { UP, DOWN, LEFT, RIGHT } private List<Direction> autoMovePath; private int currentStep = 0; private Timer moveTimer;
Step 2: Update the Run Button Code
Replace your existing button logic with this to trigger auto-movement with custom intervals:
if (source == buttonRun) { // 1. Calculate the path to the end (implement BFS here) autoMovePath = calculateShortestPath(); currentStep = 0; // 2. Set up Timer to execute each move every 800ms (adjust as needed) int moveDelay = 800; moveTimer = new Timer(moveDelay, e -> { if (currentStep < autoMovePath.size()) { Direction nextMove = autoMovePath.get(currentStep); // Call your existing direction methods switch (nextMove) { case UP: moveUp(); // Your existing upward movement method break; case DOWN: moveDown(); break; case LEFT: moveLeft(); break; case RIGHT: moveRight(); break; } currentStep++; } else { // Stop Timer once path is complete moveTimer.stop(); System.out.println("Ball reached the finish!"); } }); moveTimer.start(); System.out.println("Auto-movement started..."); }
If you want each direction method to run for a specific duration (e.g., 500ms of smooth upward movement instead of an instant jump), modify your movement methods to use a frame-based animation Timer:
Example Smooth Move Method
private void moveUp(int durationMs) { int startY = ball.getY(); int targetY = startY - 20; // Adjust based on your maze's cell size int frameRate = 16; // ~60 frames per second int totalFrames = durationMs / frameRate; int yStep = (targetY - startY) / totalFrames; Timer animationTimer = new Timer(frameRate, e -> { int currentY = ball.getY(); if (Math.abs(currentY - targetY) <= Math.abs(yStep)) { // Final position adjustment ball.setLocation(ball.getX(), targetY); ((Timer) e.getSource()).stop(); } else { // Update position incrementally ball.setLocation(ball.getX(), currentY + yStep); } repaint(); // Refresh the UI to show the movement }); animationTimer.start(); }
Then call it with a duration in your main Timer:
moveUp(500); // Move upward smoothly over 500ms
If you need more complex scheduling (e.g., varying delays between moves), ScheduledExecutorService is a robust alternative to Swing Timer. Just make sure to wrap UI updates in SwingUtilities.invokeLater() to stay on the EDT:
private ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); private ScheduledFuture<?> currentTask; // In your Run button handler: if (source == buttonRun) { autoMovePath = calculateShortestPath(); currentStep = 0; Runnable moveTask = () -> { SwingUtilities.invokeLater(() -> { if (currentStep < autoMovePath.size()) { Direction nextMove = autoMovePath.get(currentStep); switch (nextMove) { case UP: moveUp(600); break; // Handle other directions } currentStep++; } else { currentTask.cancel(false); System.out.println("Finish line reached!"); } }); }; // Execute moveTask every 1 second, starting immediately currentTask = scheduler.scheduleAtFixedRate(moveTask, 0, 1000, TimeUnit.MILLISECONDS); }
- Path-Finding: Don't skip implementing BFS (or Dijkstra if your maze has weighted paths)—randomly calling direction methods won't reliably get the ball to the end.
- EDT Safety: Always update UI components from the Event Dispatch Thread (Swing Timer does this automatically; for ExecutorService, use
invokeLater). - Adjust Timings: Tweak
moveDelayanddurationMsvalues to match your maze's speed and feel.
内容的提问来源于stack exchange,提问作者user9660895

