【问题标题】:Snake game in Java but my restart button does not workJava中的蛇游戏,但我的重启按钮不起作用
【发布时间】:2022-01-13 18:53:28
【问题描述】:

我的游戏重新启动按钮不起作用,并且在单击时会倍增。我不完全理解 Java 我认为自己很好。

游戏主线

package snake_game;

public class snake {

  public static void main(String arg[]) {

    new GameFrame();
    // is exacly the same as frame f = new frame();
    // this is shorter and does the same job

  }
}

GamePanel

package snake_game;

// import java.awt.event.ActionEvent;
// import java.awt.event.ActionListener;
// import java.awt.Graphics;
// import java.awt.event.KeyAdapter;
// import java.awt.event.KeyEvent;
// or I could write simply 
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;

import javax.swing.JPanel;

public class GamePanel extends JPanel implements ActionListener {

  // panal dimentions
  static final int SCREEN_WIDTH = 600;
  static final int SCREEN_HEIGHT = 600;
  // panal dimentions
  // size
  static final int UNIT_SIZE = 25;
  // size to make 600 * 600 = 1200 px equel between 25 px
  static final int GAME_UNITS = (SCREEN_WIDTH * SCREEN_HEIGHT) / UNIT_SIZE;
  // size
  // delay how fast the game will be
  static final int DELAY = 75;
  // delay
  // dimentions
  final int x[] = new int[GAME_UNITS];
  final int y[] = new int[GAME_UNITS];
  // dimentions
  // snake
  int bodyParts = 6;
  // snake
  // apple
  int appleEaten;
  int appleX;
  int appleY;
  // apple
  char direction = 'R';
  boolean running = false;
  Timer timer;
  Random random;
  GamePanel game;
  JButton resetButton;

  GamePanel() {

    random = new Random();
    this.setPreferredSize(new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT));
    this.setBackground(Color.black);
    this.setFocusable(true);
    this.addKeyListener(new MyKeyAdapter());
    startGame();
    // when we want to make the program to continie we must say what the programm
    // must execute next

  }

  public void startGame() {
    newApple();
    running = true;
    timer = new Timer(DELAY, this);
    timer.start();
  }

  public void paintComponent(Graphics g) {
    super.paintComponent(g);
    draw(g);

  }

  public void draw(Graphics g) {

    if (running) {

      for (int i = 0; i < SCREEN_HEIGHT / UNIT_SIZE; i++) {
        g.drawLine(i * UNIT_SIZE, 0, i * UNIT_SIZE, SCREEN_HEIGHT);
        g.drawLine(0, i * UNIT_SIZE, i * SCREEN_WIDTH, i * UNIT_SIZE);

      }
      g.setColor(Color.red);
      g.fillOval(appleX, appleY, UNIT_SIZE, UNIT_SIZE);

      for (int i = 0; i < bodyParts; i++) {
        if (i == 0) {
          g.setColor(Color.green);
          g.fillRect(x[i], y[i], UNIT_SIZE, UNIT_SIZE);
        } else {
          g.setColor(new Color(45, 180, 0));
          // random color
          g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
          // random color
          g.fillRect(x[i], y[i], UNIT_SIZE, UNIT_SIZE);
        }

      }
      g.setColor(Color.red);
      g.setFont(new Font("Ink Free", Font.BOLD, 30));
      FontMetrics metrics = getFontMetrics(g.getFont());
      g.drawString("SCORE:" + appleEaten, (SCREEN_WIDTH - metrics.stringWidth("SCORE:" + appleEaten)) / 2,
          g.getFont().getSize());
    } else {
      gameOver(g);
    }
  }

  public void newApple() {
    appleX = random.nextInt((int) (SCREEN_WIDTH / UNIT_SIZE)) * UNIT_SIZE;
    appleY = random.nextInt((int) (SCREEN_HEIGHT / UNIT_SIZE)) * UNIT_SIZE;
  }

  public void move() {

    for (int i = bodyParts; i > 0; i--) {
      x[i] = x[i - 1];
      y[i] = y[i - 1];

    }
    switch (direction) {
      case 'U':
        y[0] = y[0] - UNIT_SIZE;
        break;
      case 'D':
        y[0] = y[0] + UNIT_SIZE;
        break;
      case 'L':
        x[0] = x[0] - UNIT_SIZE;
        break;
      case 'R':
        x[0] = x[0] + UNIT_SIZE;
        break;
    }

  }

  public void checkApple() {
    if ((x[0] == appleX) && (y[0] == appleY)) {
      bodyParts++;
      appleEaten++;
      newApple();
    }
  }

  public void checkCollisions() {
    // check if head collides with body
    for (int i = bodyParts; i > 0; i--) {
      if ((x[0] == x[i]) && (y[0] == y[i])) {
        running = false;
      }

    }
    // check if head touches left border
    if (x[0] < 0) {
      running = false;
    }

    // check if head touches right border
    if (x[0] > SCREEN_WIDTH) {
      running = false;
    }
    // check if head touches top border
    if (y[0] < 0) {
      running = false;
    }
    // check if head touches bottom border
    if (y[0] > SCREEN_HEIGHT) {
      running = false;
    }
    if (!running) {
      timer.stop();
    }
  }

  public void gameOver(Graphics g) {
    // score
    g.setColor(Color.red);
    g.setFont(new Font("Ink Free", Font.BOLD, 30));
    FontMetrics metrics1 = getFontMetrics(g.getFont());
    g.drawString("SCORE:" + appleEaten, (SCREEN_WIDTH - metrics1.stringWidth("SCORE:" + appleEaten)) / 2,
        g.getFont().getSize());
    // game over text
    g.setColor(Color.red);
    g.setFont(new Font("Ink Free", Font.BOLD, 75));
    FontMetrics metrics2 = getFontMetrics(g.getFont());
    g.drawString("Game Over", (SCREEN_WIDTH - metrics2.stringWidth("Game Over")) / 2, SCREEN_HEIGHT / 2);
    // restart button
    resetButton = new JButton();
    resetButton.setText("Restart");
    resetButton.setSize(100, 50);
    resetButton.setLocation(150, 150);
    resetButton.addActionListener(this);

    game = new GamePanel();

    this.add(resetButton);
    this.add(game);
    this.setVisible(true);
    // restart button
  }

  @Override
  public void actionPerformed(ActionEvent e) {

    if (running) {
      move();
      checkApple();
      checkCollisions();

    }
    repaint();

    // restart button
    if (e.getSource() == resetButton) {
      this.remove(game);

      game = new GamePanel();
      this.add(game);
      resetButton.setVisible(false);
      SwingUtilities.updateComponentTreeUI(this);
      // restart button

    }

  }

  public class MyKeyAdapter extends KeyAdapter {

    @Override
    public void keyPressed(KeyEvent e) {

      switch (e.getKeyCode()) {
        case KeyEvent.VK_LEFT:
          if (direction != 'R') {
            direction = 'L';
          }
          break;
        case KeyEvent.VK_RIGHT:
          if (direction != 'L') {
            direction = 'R';
          }
          break;
        case KeyEvent.VK_UP:
          if (direction != 'D') {
            direction = 'U';
          }
          break;
        case KeyEvent.VK_DOWN:
          if (direction != 'U') {
            direction = 'D';
          }
          break;

      }

    }

  }

}

GameFrame

package snake_game;

import javax.swing.JFrame;

public class GameFrame extends JFrame {

  GameFrame() {
    GamePanel panel = new GamePanel();
    this.add(panel);
    this.setTitle("Snake");
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setResizable(false);
    this.pack();
    this.setVisible(true);
    this.setLocationRelativeTo(null);
    this.setUndecorated(false);
  }
}

【问题讨论】:

  • this.remove(game); game = new GamePanel(); this.add(game) 不!这将导致没有特殊处理的问题。最好创建一个SnakeGameModel,它可以传递给面板以设置它并显示当前视图。然后当用户重置时,将游戏模型设置回默认值(或创建一个新模型)并将其传递给单个 GamePanel

标签: java swing jbutton restart


【解决方案1】:

简介

我将您的代码复制到我的 Eclipse IDE 中并按原样运行。我收到以下运行时错误。

Exception in thread "main" java.awt.IllegalComponentStateException: The frame is displayable.
    at java.desktop/java.awt.Frame.setUndecorated(Frame.java:926)
    at com.ggl.testing.SnakeGame$GameFrame.<init>(SnakeGame.java:41)
    at com.ggl.testing.SnakeGame.main(SnakeGame.java:24)

Oracle 有一个有用的教程,Creating a GUI With Swing。跳过使用 NetBeans IDE 学习摇摆部分。密切关注Concurrency in Swing 部分。

我已经编写 Swing 代码超过 10 年,并且我在浏览器中添加了 Oracle 网站的书签。我仍在查找如何使用某些组件以确保我正确使用它们。

我做的第一件事就是让你的蛇减速,这样我就可以测试游戏了。我将延迟 75 更改为延迟 750。这是您当前 GUI 的屏幕截图。

查看您的代码,您扩展了JFrame。您不需要扩展JFrame。您不会更改任何 JFrame 功能。使用JFrame 要简单得多。这导致了我的 Java 规则之一。

不要扩展 Swing 组件或任何 Java 类,除非你打算 覆盖一个或多个类方法。

您确实扩展了JPanel。这很好,因为您覆盖了 paintComponent 方法。

最后,你的JPanel 班级做的工作太多了。您还大量使用静态字段。尽管您只会创建一个JPanel,但将每个类都视为创建该类的多个实例是一个好习惯。这为您自己带来的问题更少。

你的想法是对的,创建了三个类。

因此,让我们使用一些基本模式和 Swing 最佳实践来重新编写您的代码。目前,我不知道我们最终会创建多少类。

说明

当我编写 Swing GUI 时,我使用 model–view–controller (MVC) 模式。顾名思义,您首先创建模型,然后是视图,然后是控制器。

一个应用程序模型由一个或多个普通的 Java getter/setter 类组成。

一个视图由一个JFrame、一个或多个JPanels以及任何其他必要的Swing组件组成。

控制器由一个或多个ActionsActionListeners组成。在 Swing 中,通常没有一个控制器可以“统辖所有”。

总结一下:

  • 视图从模型中读取信息
  • 视图不更新模型
  • 控制器更新模型并重新绘制/重新验证您的视图。

型号

我创建了两个模型类,SnakeModelSnake

SnakeModel 类是一个普通的 Java getter/setter 类,它包含一个 Snake 实例、苹果吃掉的数量、苹果的位置、游戏区域的大小和几个布尔值。一个布尔值表示游戏循环是否正在运行,另一个布尔值表示游戏是否结束。

游戏区域使用java.awt.Dimension 来保存游戏区域的宽度和高度。宽度和高度不必具有相同的值。游戏区域可以是矩形的。

游戏区域以单位测量。在视图中,我将单位转换为像素。这与你所做的相反。如果要更改游戏区域,只需更改SnakeModel 类中的尺寸即可。视图中的所有内容均基于游戏区域维度。

Snake 类包含 java.util.Listjava.awt.Point 对象和 char 方向。 java.awt.Point 对象包含一个 X 和 Y 值。由于我们处理的是对象,而不是 int 值,所以当我们想要一个新的Point 时,我们必须小心克隆对象。

查看

所有 Swing 应用程序都必须以调用 SwingUtilities invokeLater 方法开始。此方法确保在 Event Dispatch Thread 上创建和执行 Swing 组件。

我创建了一个JFrame,一个绘图JPanel,以及一个单独的按钮JPanel。通常,将 Swing 组件添加到绘图JPanel 并不是一个好主意。通过创建一个单独的按钮JPanel,我几乎无需额外费用即可获得“开始游戏”按钮的附加功能。该按钮在游戏运行时被禁用。

JFrame 方法必须按特定顺序调用。 setVisible 方法必须最后调用

我为乐谱添加了一个单独的区域,使JPanel 的绘图更加复杂。

我只根据应用程序模型绘制游戏状态,使绘图JPanel 变得不那么复杂。时期。没有别的了。

我将随机颜色限制在色谱的白色端,以保持蛇和绘图JPanel 背景之间的对比。

我使用键绑定而不是键侦听器。一个优点是绘图JPanel 不必成为焦点。因为我有一个单独的按钮JPanel,所以绘图JPanel 没有焦点。

另一个优点是我可以用四行附加代码添加 WASD 键。

一个缺点是键绑定代码看起来比键侦听器更复杂。一旦您编写了几个键绑定,您就会体会到其中的优势。

控制器

我创建了三个控制器类,ButtonListenerTimerListenerMovementAction

ButtonListener 类实现了ActionListenerButtonListener 类初始化游戏模型并重新启动计时器。

TimerListener 类实现了ActionListenerTimerListener 类是游戏循环。这个类移动蛇,检查苹果是否被吃掉,检查蛇是否已经移动到游戏区域之外或接触到自己,并重新绘制绘图JPanel。我用你的代码作为这个类代码的模型。

MovementAction 类扩展了 AbstractActionAbstractAction 类实现 Action。这个类根据按键改变蛇的方向。

我创建了MovementAction 类的四个实例,每个方向一个。这使得类的actionPerformed 方法更加简单。

图片

这是您开始游戏时修改后的 GUI 的样子。

这是游戏期间修改后的 GUI。

这是游戏结束后修改后的 GUI。

代码

这是完整的可运行代码。我将所有额外的类都设为内部类,这样我就可以将这段代码作为一个块发布。

您应该将单独的类放在单独的文件中。

在设置 Swing GUI 项目时,我为模型、视图和控制器创建单独的包。这有助于我保持代码井井有条。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.BorderFactory;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class SnakeGame implements Runnable {

    public static void main(String arg[]) {
        SwingUtilities.invokeLater(new SnakeGame());
    }
    
    private final GamePanel gamePanel;
    
    private final JButton restartButton;
    
    private final SnakeModel model;
    
    public SnakeGame() {
        this.model = new SnakeModel();
        this.restartButton = new JButton("Start Game");
        this.gamePanel = new GamePanel(model);
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("Snake");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        frame.add(gamePanel, BorderLayout.CENTER);
        frame.add(createButtonPanel(), BorderLayout.SOUTH);
        
        frame.pack();
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    
    private JPanel createButtonPanel() {
        JPanel panel = new JPanel();
        panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        panel.setBackground(Color.black);
        
        restartButton.addActionListener(new ButtonListener(this, model));
        panel.add(restartButton);
        
        return panel;
    }
    
    public JButton getRestartButton() {
        return restartButton;
    }

    public void repaint() {
        gamePanel.repaint();
    }
    
    public class GamePanel extends JPanel {

        private static final long serialVersionUID = 1L;
        
        private final int margin, scoreAreaHeight, unitSize;
        
        private final Random random;
        
        private final SnakeModel model;
        
        public GamePanel(SnakeModel model) {
            this.model = model;
            this.margin = 10;
            this.unitSize = 25;
            this.scoreAreaHeight = 36 + margin;
            this.random = new Random();
            this.setBackground(Color.black);
            
            Dimension gameArea = model.getGameArea();
            int width = gameArea.width * unitSize + 2 * margin;
            int height = gameArea.height * unitSize + 2 * margin + scoreAreaHeight;
            this.setPreferredSize(new Dimension(width, height));
            setKeyBindings();
        }
        
        private void setKeyBindings() {
            InputMap inputMap = this.getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
            ActionMap actionMap = this.getActionMap();
            
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "up");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "down");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "left");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "right");
            
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), "up");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0), "down");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), "left");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), "right");
            
            actionMap.put("up", new MovementAction(model, 'U', 'D'));
            actionMap.put("down", new MovementAction(model, 'D', 'U'));
            actionMap.put("left", new MovementAction(model, 'L', 'R'));
            actionMap.put("right", new MovementAction(model, 'R', 'L'));
        }
        
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            
            Dimension gameArea = model.getGameArea();
            drawHorizontalGridLines(g, gameArea);
            drawVerticalGridLines(g, gameArea);
            drawSnake(g);
            drawScore(g, gameArea);
            
            if (model.isGameOver) {
                drawGameOver(g, gameArea);
            } else {
                drawApple(g);
            }
        }

        private void drawHorizontalGridLines(Graphics g, Dimension gameArea) {
            int y1 = scoreAreaHeight + margin;
            int y2 = y1 + gameArea.height * unitSize;
            int x = margin;
            for (int index = 0; index <= gameArea.width; index++) {
                g.drawLine(x, y1, x, y2);
                x += unitSize;
            }
        }

        private void drawVerticalGridLines(Graphics g, Dimension gameArea) {
            int x1 = margin;
            int x2 = x1 + gameArea.width * unitSize;
            int y = margin + scoreAreaHeight;
            for (int index = 0; index <= gameArea.height; index++) {
                g.drawLine(x1, y, x2, y);
                y += unitSize;
            }
        }

        private void drawApple(Graphics g) {
            // Draw apple
            g.setColor(Color.red);
            Point point = model.getAppleLocation();
            if (point != null) {
                int a = point.x * unitSize + margin + 1;
                int b = point.y * unitSize + margin + scoreAreaHeight + 1;
                g.fillOval(a, b, unitSize - 2, unitSize - 2);
            }
        }

        private void drawScore(Graphics g, Dimension gameArea) {
            g.setColor(Color.red);
            g.setFont(new Font("Ink Free", Font.BOLD, 36));
            FontMetrics metrics = getFontMetrics(g.getFont());
            int width = 2 * margin + gameArea.width * unitSize;
            String text = "SCORE: " + model.getApplesEaten();
            int textWidth = metrics.stringWidth(text);
            g.drawString(text, (width - textWidth) / 2, g.getFont().getSize());
        }
        
        private void drawSnake(Graphics g) {
            // Draw snake
            Snake snake = model.getSnake();
            List<Point> cells = snake.getCells();
            Point cell = cells.get(0);
            drawSnakeCell(g, cell, Color.green);
            for (int index = 1; index < cells.size(); index++) {
//              Color color = new Color(45, 180, 0);
                // random color
                Color color = new Color(getColorValue(), getColorValue(), 
                        getColorValue());
                cell = cells.get(index);
                drawSnakeCell(g, cell, color);
            }
        }
        
        private void drawSnakeCell(Graphics g, Point point, Color color) {
            int x = margin + point.x * unitSize;
            int y = margin + scoreAreaHeight + point.y * unitSize;
            if (point.y >= 0) {
                g.setColor(color);
                g.fillRect(x, y, unitSize, unitSize);
            }
        }
        
        private int getColorValue() {
            // White has color values of 255
            return random.nextInt(64) + 191;
        }
        
        private void drawGameOver(Graphics g, Dimension gameArea) {
            g.setColor(Color.red);
            g.setFont(new Font("Ink Free", Font.BOLD, 72));
            FontMetrics metrics = getFontMetrics(g.getFont());
            String text = "Game Over";
            int textWidth = metrics.stringWidth(text);
            g.drawString(text, (getWidth() - textWidth) / 2, getHeight() / 2);
        }
        
    }
    
    public class ButtonListener implements ActionListener {
        
        private final int delay;
        
        private final SnakeGame view;
        
        private final SnakeModel model;
        
        private final Timer timer;

        public ButtonListener(SnakeGame view, SnakeModel model) {
            this.view = view;
            this.model = model;
            this.delay = 750;
            this.timer = new Timer(delay, new TimerListener(view, model));
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            JButton button = (JButton) event.getSource();
            String text = button.getText();
            
            if (text.equals("Start Game")) {
                button.setText("Restart Game");
            } 
            
            button.setEnabled(false);
            model.initialize();
            timer.restart();
        }
        
    }
    
    public class TimerListener implements ActionListener {
        
        private final SnakeGame view;
        
        private final SnakeModel model;

        public TimerListener(SnakeGame view, SnakeModel model) {
            this.view = view;
            this.model = model;
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            moveSnake();
            checkApple();
            model.checkCollisions();
            if (model.isGameOver()) {
                Timer timer = (Timer) event.getSource();
                timer.stop();
                model.setRunning(false);
                view.getRestartButton().setEnabled(true);
            }
            view.repaint();
        }
        
        private void moveSnake() {
            Snake snake = model.getSnake();
            Point head = (Point) snake.getHead().clone();
            
            switch (snake.getDirection()) {
            case 'U':
                head.y--;
                break;
            case 'D':
                head.y++;
                break;
            case 'L':
                head.x--;
                break;
            case 'R':
                head.x++;
                break;
            }
            
            snake.removeTail();
            snake.addHead(head);
            
//          System.out.println(Arrays.toString(cells.toArray()));
        }
        
        private void checkApple() {
            Point appleLocation = model.getAppleLocation();
            Snake snake = model.getSnake();
            Point head = snake.getHead();
            Point tail = (Point) snake.getTail().clone();
            
            if (head.x == appleLocation.x && head.y == appleLocation.y) {
                model.incrementApplesEaten();
                snake.addTail(tail);
                model.generateRandomAppleLocation();
            }
        }
        
    }
    
    public class MovementAction extends AbstractAction {

        private static final long serialVersionUID = 1L;
        
        private final char newDirection, oppositeDirection;
        
        private final SnakeModel model;

        public MovementAction(SnakeModel model, char newDirection,
                char oppositeDirection) {
            this.model = model;
            this.newDirection = newDirection;
            this.oppositeDirection = oppositeDirection;
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            if (model.isRunning()) {
                Snake snake = model.getSnake();
                char direction = snake.getDirection();
                if (direction != oppositeDirection && direction != newDirection) {
                    snake.setDirection(newDirection);
//                  System.out.println("New direction: " + newDirection);
                }
            }
        }
        
    }
    
    public class SnakeModel {
        
        private boolean isGameOver, isRunning;
        
        private int applesEaten;
        
        private Dimension gameArea;
        
        private Point appleLocation;
        
        private Random random;
        
        private Snake snake;
        
        public SnakeModel() {
            this.random = new Random();
            this.snake = new Snake();
            this.gameArea = new Dimension(24, 24);
        }
        
        public void initialize() {
            this.isRunning = true;
            this.isGameOver = false;
            this.snake.initialize();
            this.applesEaten = 0;
            
            Point point = generateRandomAppleLocation();
            // Make sure first apple isn't under snake
            int y = (point.y == 0) ? 1 : point.y;
            this.appleLocation = new Point(point.x, y);
        }
        
        public void checkCollisions() {
            Point head = snake.getHead();
            
            // Check for snake going out of the game area
            if (head.x < 0 || head.x > gameArea.width) {
                isGameOver = true;
                return;
            }
            
            if (head.y < 0 || head.y > gameArea.height) {
                isGameOver = true;
                return;
            }
            
            // Check for snake touching itself
            List<Point> cells = snake.getCells();
            for (int index = 1; index < cells.size(); index++) {
                Point cell = cells.get(index);
                if (head.x == cell.x && head.y == cell.y) {
                    isGameOver = true;
                    return;
                }
            }
        }
        
        public Point generateRandomAppleLocation() {
            int x = random.nextInt(gameArea.width);
            int y = random.nextInt(gameArea.height);
            this.appleLocation = new Point(x, y);
            return getAppleLocation();
        }
        
        public void incrementApplesEaten() {
            this.applesEaten++;
        }
        
        public boolean isRunning() {
            return isRunning;
        }

        public void setRunning(boolean isRunning) {
            this.isRunning = isRunning;
        }

        public boolean isGameOver() {
            return isGameOver;
        }

        public void setGameOver(boolean isGameOver) {
            this.isGameOver = isGameOver;
        }

        public Dimension getGameArea() {
            return gameArea;
        }

        public int getApplesEaten() {
            return applesEaten;
        }

        public Point getAppleLocation() {
            return appleLocation;
        }

        public Snake getSnake() {
            return snake;
        }
        
    }
    
    public class Snake {
        
        private char direction;
        
        private List<Point> cells;
        
        public Snake() {
            this.cells = new ArrayList<>();
            initialize();
        }
        
        public void initialize() {
            this.direction = 'R';
            cells.clear();
            for (int x = 5; x >= 0; x--) {
                cells.add(new Point(x, 0));
            }
        }

        public void addHead(Point head) {
            cells.add(0, head);
        }
        
        public void addTail(Point tail) {
            cells.add(tail);
        }
        
        public void removeTail() {
            cells.remove(cells.size() - 1);
        }
        
        public Point getHead() {
            return cells.get(0);
        }
        
        public Point getTail() {
            return cells.get(cells.size() - 1);
        }

        public char getDirection() {
            return direction;
        }

        public void setDirection(char direction) {
            this.direction = direction;
        }

        public List<Point> getCells() {
            return cells;
        }
        
    }

}

【讨论】:

  • 非常感谢您的帮助,我无话可说!我将查看 Oracle 的 GUI,并尝试更好地理解它们!再次感谢您提供了固定的游戏代码,并为我的问题所在以及如何解决问题提供了有用的解释!
猜你喜欢
  • 1970-01-01
  • 2023-01-10
  • 1970-01-01
  • 2021-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-03
  • 1970-01-01
相关资源
最近更新 更多