在Java中玩蛇游戏,但我的重新启动按钮不起作用

2022-07-05 00:00:00 restart java swing jbutton

我的游戏重新启动按钮不起作用,当它被点击时它会加倍。我不太懂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);
  }
}

解决方案

简介

我将您的代码复制到我的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学习Swing一节。请密切关注Concurrency in Swing部分。

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

我做的第一件事是让你的蛇慢下来,这样我就可以测试游戏了。我把延迟从75改成了750。这是您当前图形用户界面的屏幕截图。

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

除非您有意,否则不要扩展Swing组件或任何Java类 重写一个或多个类方法。

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

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

您的想法很正确,创建了三个类。

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

说明

编写Swing图形用户界面时,我使用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应用程序都必须从调用SwingUtilitiesinvokeLater方法开始。此方法确保在事件调度线程上创建和执行Swing组件。

我创建了一个JFrame、一个绘图JPanel和一个单独的按钮JPanel。通常,将Swing组件添加到绘图JPanel不是一个好主意。通过创建一个单独的按钮JPanel,我几乎不需要额外的成本就可以获得";Start Game";按钮的附加功能。该按钮在游戏运行时被禁用。

JFrame方法必须按特定顺序调用。必须上次调用setVisible方法。

我为分数添加了单独的区域,从而使绘图JPanel变得更加复杂。

我根据应用程序模型只绘制了游戏状态,从而使绘图JPanel变得不那么复杂。句号。别无他法。

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

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

另一个好处是我可以用四行额外的代码添加WASD键。

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

控制器

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

<2-41]>类实现ActionListenerButtonListener类初始化游戏模型并重新启动计时器。

<2-42]>类实现ActionListenerTimerListener类是游戏循环。这个类移动蛇,检查苹果是否被吃掉,检查蛇是否移动到游戏区域之外或触摸自己,并重新绘制绘图JPanel。我将您的代码用作此类代码的模型。

MovementAction类扩展AbstractActionAbstractAction类实现Action。此类根据按键更改蛇的方向。

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

图像

以下是您开始游戏时修改后的图形用户界面的外观。

这是游戏期间修改后的图形用户界面。

这是游戏结束后修改后的图形用户界面。

代码

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

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

在设置Swing图形用户界面项目时,我为模型、视图和控制器创建了单独的包。这有助于我保持代码的条理性。

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;
        }
        
    }

}

相关文章