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

Java贪吃蛇游戏showGameOverDialog随机触发问题求助

Java贪吃蛇游戏随机触发Game Over对话框问题求助

我花了一整天开发了这个Java贪吃蛇游戏,这是我第一个稍复杂的编程项目。游戏包含高分系统和可用菜单,是跟随教程逐步完成的。但当前存在一个异常问题:showGameOverDialog会随机触发,无论游戏处于何种状态——比如在菜单界面、吃苹果时都会弹出。我尝试调整该对话框相关代码,但未能找到解决方法,希望有人能帮忙排查修复。

以下是完整代码:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class SnakeGame extends JFrame {

    private CardLayout cardLayout;
    private JPanel mainPanel;
    private GamePanel gamePanel;
    private MainMenuPanel mainMenuPanel;
    private HighScorePanel highScorePanel;
    private OptionsPanel optionsPanel;
    private boolean fullscreen = false;

    public SnakeGame() {
        setTitle("Snake Game");
        setSize(800, 800);
        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        cardLayout = new CardLayout();
        mainPanel = new JPanel(cardLayout);

        gamePanel = new GamePanel(this);
        mainMenuPanel = new MainMenuPanel(this);
        highScorePanel = new HighScorePanel(this);
        optionsPanel = new OptionsPanel(this);

        mainPanel.add(mainMenuPanel, "MainMenu");
        mainPanel.add(gamePanel, "Game");
        mainPanel.add(highScorePanel, "HighScores");
        mainPanel.add(optionsPanel, "Options");

        add(mainPanel);
        cardLayout.show(mainPanel, "MainMenu");

        setLocationRelativeTo(null);
        setVisible(true);
    }

    public void showCard(String card) {
        cardLayout.show(mainPanel, card);
    }

    public void toggleFullscreen() {
        dispose();
        if (fullscreen) {
            setUndecorated(false);
            setExtendedState(JFrame.NORMAL);
            setSize(800, 800);
        } else {
            setUndecorated(true);
            setExtendedState(JFrame.MAXIMIZED_BOTH);
        }
        fullscreen = !fullscreen;
        setVisible(true);
    }

    public static void main(String[] args) {
        new SnakeGame();
    }
}

class MainMenuPanel extends JPanel {

    public MainMenuPanel(SnakeGame frame) {
        setLayout(new GridLayout(4, 1));
        JButton startButton = new JButton("Spiel starten");
        JButton highScoreButton = new JButton("Highscores");
        JButton optionsButton = new JButton("Optionen");
        JButton exitButton = new JButton("Spiel beenden");

        startButton.addActionListener(e -> frame.showCard("Game"));
        highScoreButton.addActionListener(e -> frame.showCard("HighScores"));
        optionsButton.addActionListener(e -> frame.showCard("Options"));
        exitButton.addActionListener(e -> System.exit(0));

        add(startButton);
        add(highScoreButton);
        add(optionsButton);
        add(exitButton);
    }
}

class OptionsPanel extends JPanel {

    public OptionsPanel(SnakeGame frame) {
        setLayout(new GridLayout(2, 1));
        JButton toggleFullscreenButton = new JButton("Vollbild / Fenster");
        JButton backButton = new JButton("Zurück zum Hauptmenü");

        toggleFullscreenButton.addActionListener(e -> frame.toggleFullscreen());
        backButton.addActionListener(e -> frame.showCard("MainMenu"));

        add(toggleFullscreenButton);
        add(backButton);
    }
}

class HighScorePanel extends JPanel {

    private SnakeGame frame;
    private JTextArea highScoreArea;
    private static final String HIGHSCORE_FILE = "highscore.txt";

    public HighScorePanel(SnakeGame frame) {
        this.frame = frame;
        setLayout(new BorderLayout());

        highScoreArea = new JTextArea();
        highScoreArea.setEditable(false);

        JButton backButton = new JButton("Zurück zum Hauptmenü");
        backButton.addActionListener(e -> frame.showCard("MainMenu"));

        add(new JScrollPane(highScoreArea), BorderLayout.CENTER);
        add(backButton, BorderLayout.SOUTH);

        loadHighScores();
    }

    private void loadHighScores() {
        try (BufferedReader reader = new BufferedReader(new FileReader(HIGHSCORE_FILE))) {
            highScoreArea.read(reader, null);
        } catch (IOException e) {
            highScoreArea.setText("Keine Highscores gefunden.");
        }
    }
}

class GamePanel extends JPanel implements ActionListener {

    private static final int TILE_SIZE = 25;
    private static final int BOARD_WIDTH = 30;
    private static final int BOARD_HEIGHT = 30;
    private static final int DELAY = 140;
    private static final String HIGHSCORE_FILE = "highscore.txt";

    private final List<Point> snake = new ArrayList<>();
    private Point food;
    private char direction = 'R';
    private Timer timer;
    private int score = 0;
    private int highScore = 0;
    private SnakeGame frame;

    public GamePanel(SnakeGame frame) {
        this.frame = frame;
        setPreferredSize(new Dimension(TILE_SIZE * BOARD_WIDTH, TILE_SIZE * BOARD_HEIGHT));
        setBackground(Color.BLACK);
        setFocusable(true);
        loadHighScore();
        initGame();
        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                int key = e.getKeyCode();
                if (key == KeyEvent.VK_LEFT && direction != 'R') {
                    direction = 'L';
                } else if (key == KeyEvent.VK_RIGHT && direction != 'L') {
                    direction = 'R';
                } else if (key == KeyEvent.VK_UP && direction != 'D') {
                    direction = 'U';
                } else if (key == KeyEvent.VK_DOWN && direction != 'U') {
                    direction = 'D';
                }
            }
        });
        timer = new Timer(DELAY, this);
        timer.start();
    }

    private void loadHighScore() {
        try (BufferedReader reader = new BufferedReader(new FileReader(HIGHSCORE_FILE))) {
            highScore = Integer.parseInt(reader.readLine());
        } catch (IOException | NumberFormatException e) {
            highScore = 0;
        }
    }

    private void saveHighScore() {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(HIGHSCORE_FILE))) {
            writer.write(String.valueOf(highScore));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void initGame() {
        snake.clear();
        snake.add(new Point(5, 5));
        snake.add(new Point(4, 5));
        snake.add(new Point(3, 5));
        score = 0;
        placeFood();
    }

    private void placeFood() {
        int x = (int) (Math.random() * BOARD_WIDTH);
        int y = (int) (Math.random() * BOARD_HEIGHT);
        food = new Point(x, y);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        drawBoard(g);
        drawSnake(g);
        drawFood(g);
        drawScore(g);
    }

    private void drawBoard(Graphics g) {
        g.setColor(Color.GREEN);
        for (int x = 0; x < BOARD_WIDTH; x++) {
            for (int y = 0; y < BOARD_HEIGHT; y++) {
                g.drawRect(x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE, TILE_SIZE);
            }
        }
    }

    private void drawSnake(Graphics g) {
        g.setColor(Color.RED);
        for (Point point : snake) {
            g.fillRect(point.x * TILE_SIZE, point.y * TILE_SIZE, TILE_SIZE, TILE_SIZE);
        }
    }

    private void drawFood(Graphics g) {
        g.setColor(Color.YELLOW);
        g.fillRect(food.x * TILE_SIZE, food.y * TILE_SIZE, TILE_SIZE, TILE_SIZE);
    }

    private void drawScore(Graphics g) {
        g.setColor(Color.WHITE);
        g.setFont(new Font("Helvetica", Font.BOLD, 20));
        g.drawString("Score: " + score, 10, getHeight() - 10);
        g.drawString("Highscore: " + highScore, 10, getHeight() - 40);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        moveSnake();
        checkCollision();
        repaint();
    }

    private void moveSnake() {
        Point head = new Point(snake.get(0));
        switch (direction) {
            case 'L':
                head.x--;
                break;
            case 'R':
                head.x++;
                break;
            case 'U':
                head.y--;
                break;
            case 'D':
                head.y++;
                break;
        }
        snake.add(0, head);
        snake.remove(snake.size() - 1);
    }

    private void checkCollision() {
        Point head = snake.get(0);
        if (head.equals(food)) {
            snake.add(food);
            placeFood();
            score++;
            if (score > highScore) {
                highScore = score;
                saveHighScore();
            }
        }

        if (head.x < 0 || head.x >= BOARD_WIDTH || head.y < 0 || head.y >= BOARD_HEIGHT) {
            timer.stop();
            showGameOverDialog();
        }

        for (int i = 1; i < snake.size(); i++) {
            if (head.equals(snake.get(i))) {
                timer.stop();
                showGameOverDialog();
            }
        }
    }

    private void showGameOverDialog() {
        String message = String.format("Game Over\nScore: %d\nHighscore: %d", score, highScore);
        int option = JOptionPane.showOptionDialog(this, message, "Game Over", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, new String[]{"Zurück zum Hauptmenü", "Spiel beenden"}, "Zurück zum Hauptmenü");
        if (option == 0) {
            frame.showCard("MainMenu");
        } else {
            System.exit(0);
        }
        initGame();
        timer.start();
    }
}

我已尝试修改showGameOverDialog相关代码,但仍未找到问题所在。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 03:45:53