Java 蛇与自身碰撞的问题(蛇游戏)

Java 蛇与自身碰撞的问题(蛇游戏),java,swing,timer,keypress,paintcomponent,Java,Swing,Timer,Keypress,Paintcomponent,我的蛇游戏有个问题,比如说,当你向左快速向上和向右快速按时,它会自动运行,因为我只告诉游戏,如果它向左,我不能向右按,因此,如果我在向右按之前向右按,它允许我向上按,这会使蛇进入自身 因此,当你运行程序时,只需按“下一步”和“空格”,游戏就应该开始了。当你向左移动时,只需快速按“上一步”和“右一步”,然后自己查看。不幸的是,我不知道如何解决这个问题,因为我们只学了6个月的Java,我们只真正学到了基础知识,如if等。如果您有任何问题,我会很快回答。这不是正确的解决方案吗 如果有人转向太快,比如说

我的蛇游戏有个问题,比如说,当你向左快速向上和向右快速按时,它会自动运行,因为我只告诉游戏,如果它向左,我不能向右按,因此,如果我在向右按之前向右按,它允许我向上按,这会使蛇进入自身


因此,当你运行程序时,只需按“下一步”和“空格”,游戏就应该开始了。当你向左移动时,只需快速按“上一步”和“右一步”,然后自己查看。不幸的是,我不知道如何解决这个问题,因为我们只学了6个月的Java,我们只真正学到了基础知识,如if等。如果您有任何问题,我会很快回答。

这不是正确的解决方案吗

如果有人转向太快,比如说向左行驶时,“向上”和“向右”的速度太快,则snake仍在同一个y轴上,因为它还没有随着向上移动而改变,并且按下“向右”键,snake试图在x轴上移动,而y轴值仍然相同

我在你的程序中捕捉到了x和y值,在第一次关机时正常运行时它们看起来是这样的。启动后,我让蛇一直跑到右边的墙上,然后在它撞到墙上之前向下转弯:

x[0],y[0] | x[1],y[1]
720 , 0   | 680, 0     <-- coordinates before turn
720 , 40  | 720, 0     <-- coordinates after turn
x[0],y[0]| x[1],y[1]

720,0 | 680,0我对您的代码做了一些更改,现在它可以像您预期的那样正常工作

基本上,问题是如果在计时器滴答作响之前按两个键足够快,并且调用
snakeMove
,则会覆盖
direction
变量,因此会“错过”一个键

想象一下这些步骤发生了:

  • 方向
    为V,蛇向左转
  • 计时器滴答作响,调用
    snakeMove
    ,该方法计算
    direction
    ,该方向为V,因此snake继续向左移动
  • 在计时器再次滴答作响之前,我同时按向上+向右键。因此,在计时器再次计时之前,会发生两个事件:
  • 第一个键被处理,因此
    方向
    被设置为设置
    方向==“U”
  • 第二个键被处理,因此
    direction
    被设置为right
    direction==“H”
  • 现在,只有计时器再次滴答作响并调用
    snakeMove
    。该方法在switch语句中计算
    direction
    ,并且
    direction==“H”
    ,因此我们“错过”了
    direction==“U”
    ,因为它在计时器勾选之前被
    方法中的第二次按键覆盖
  • 为了克服这个问题,正如我在前面的问题中建议的那样,使用FIFO(先进先出)列表来正确处理所有键,这样它们就不会“丢失”

    这可以使用具有我们需要的
    pop()
    函数的

    因此,在您的代码中,我将全局变量
    direction
    重命名为
    currentDirection

    private String currentDirection; 
    
    并删除了
    static
    修饰符,因为这是不需要的,我还删除了
    snakeMove
    上的
    static
    修饰符,因为这也是不需要的,并阻止我们访问实例变量,即
    currentDirection
    。我还将作用域更改为
    private
    ,正如您在代码片段中显示的那样,不需要将其设置为
    public
    ,但这些更改只是为了提高代码的正确性。然后我创建了一个全局变量:

    private LinkedList<String> directions = new LinkedList<>();
    
    这就解决了上述问题

    以下是实现了这些更改的代码:

    
    import javax.sound.sampled.*;
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import java.io.File;
    import java.util.LinkedList;
    
    public class FirstGraphic extends JPanel implements ActionListener, KeyListener {
    
        //Storlek på fönstret
        static int WIDTH = 800, HEIGHT = 840;
    
        Timer tmMove = new Timer(150, this);
    
        private JFrame window;
    
        static int bodySize = 40, xNormalFruit = 0, yNormalFruit = 0, gameSquares = (WIDTH * HEIGHT) / bodySize,
                snakeParts = 7, score = 0, restartButtonWIDTH = 190, restartButtonHEIGHT = 50;
    
        static int x[] = new int[gameSquares];
        static int y[] = new int[gameSquares];
    
        private String currentDirection;
        boolean gameRunning = false, gameStarted = false, instructions = false, isDead = false;
    
        public static JButton restartButton = new JButton("STARTA OM"), toInstructionsButton = new JButton("Nästa");
    
        private LinkedList<String> directions = new LinkedList<>();
    
        public static void main(String[] args) {
            JFrame window = new JFrame("Snake Game");
            FirstGraphic content = new FirstGraphic(window);
            window.setContentPane(content);
            window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            window.setResizable(false);
            window.pack();
            restartButton.setBounds((WIDTH / 2) - (restartButtonWIDTH) / 2, (HEIGHT - 40) / 2 + 100, restartButtonWIDTH, restartButtonHEIGHT);
            restartButton.setBackground(new Color(48, 165, 55));
            restartButton.setFont(new Font("Arial", Font.BOLD, 20));
            window.setLocationRelativeTo(null);
            window.setVisible(true);
            content.setUp();
        }
    
        public FirstGraphic(JFrame window) {
            super();
            setPreferredSize(new Dimension(WIDTH, HEIGHT));
            setFocusable(true);
            requestFocus();
            this.window = window;
        }
    
        public void setUp() {
            addKeyListener(this);
            setFocusable(true);
            setFocusTraversalKeysEnabled(false);
            restartButton.addActionListener(this);
            directions.add("H");
        }
    
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (gameRunning) {
                g.setColor(new Color(0, 0, 0));
                g.fillRect(0, 0, WIDTH, (HEIGHT - 40));
                g.setColor(new Color(63, 116, 41, 255));
                g.fillRect(0, HEIGHT - 40, WIDTH, (2));
                g.setColor(new Color(0, 0, 0, 240));
                g.fillRect(0, HEIGHT - 38, WIDTH, 38);
                g.setColor(new Color(0, 0, 0));
            }
            draw(g);
        }
    
        public void draw(Graphics g) {
            if (gameRunning) {
                g.setColor(new Color(35, 179, 52, 223));
                g.fillOval(xNormalFruit, yNormalFruit, bodySize, bodySize);
                g.setColor(new Color(44, 141, 23, 255));
                g.setFont(new Font("Arial", Font.BOLD, 18));
                for (int i = 0; i < snakeParts; i++) {
                    if (i == 0) {
                        g.setColor(Color.RED);
                        g.fillOval(x[i], y[i], bodySize, bodySize);
                    } else {
                        g.setColor(Color.PINK);
                        g.fillOval(x[i], y[i], bodySize, bodySize);
                    }
                }
            } else if (!gameRunning && gameStarted) {
                gameOver(g);
            } else if (!instructions) {
                startScene(g);
            } else {
                instructions(g);
            }
        }
    
        public void startScene(Graphics g) {
            g.setColor(Color.BLACK);
            g.fillRect(0, 0, WIDTH, HEIGHT);
            g.setColor(Color.WHITE);
            g.setFont(new Font("Arial", Font.BOLD, 85));
            g.drawString("Ormen Olle's", 150, 170);
            g.drawString("Äventyr", 235, 254);
            window.add(toInstructionsButton);
            toInstructionsButton.setBounds(240, 660, 300, 100);
            toInstructionsButton.setBackground(new Color(48, 165, 55));
            toInstructionsButton.setForeground(Color.BLACK);
            toInstructionsButton.setFont(new Font("Arial", Font.BOLD, 60));
            toInstructionsButton.addActionListener(this);
        }
    
        public void instructions(Graphics g) {
            g.setFont(new Font("Arial", Font.BOLD, 85));
            g.setColor(new Color(14, 69, 114));
            g.drawString("PRESS SPACE", 210, 720);
    
        }
    
        public void gameOver(Graphics g) {
            g.setColor(Color.BLACK);
            g.fillRect(0, 0, WIDTH, HEIGHT);
            g.setColor(Color.red);
            g.setFont(new Font("Arial", Font.BOLD, 65));
            FontMetrics metrics = getFontMetrics(g.getFont());
            g.drawString("Du dog!", (WIDTH - metrics.stringWidth("Du dog!")) / 2, (HEIGHT - 40) / 2);
            g.setColor(new Color(44, 141, 23, 255));
            g.setFont(new Font("Arial", Font.BOLD, 20));
            FontMetrics metrics2 = getFontMetrics(g.getFont());
            g.drawString("SCORE: " + score, (WIDTH - metrics2.stringWidth("SCORE:  " + score)) / 2, 50);
            window.add(restartButton);
        }
    
        public void checkFruit() {
            if ((x[0] == xNormalFruit) && (y[0] == yNormalFruit)) {
                snakeParts++;
                score++;
                newFruit();
            }
            for (int v = 1; v < snakeParts; v++) {
                if ((x[v] == xNormalFruit) && y[v] == yNormalFruit) {
                    newFruit();
                }
            }
        }
    
        public void checkCollisions() {
            for (int i = snakeParts; i > 0; i--) {
                if ((x[0] == x[i]) && (y[0] == y[i])) {
                    gameRunning = false;
                    isDead = true;
                }
            }
            if (x[0] < 0) {
                gameRunning = false;
                isDead = true;
            }
            if (x[0] == WIDTH) {
                gameRunning = false;
                isDead = true;
            }
            if (y[0] < 0) {
                gameRunning = false;
                isDead = true;
            }
            if (y[0] > (HEIGHT - 40) - bodySize) {
                gameRunning = false;
                isDead = true;
            }
            if (!gameRunning) {
                tmMove.stop();
            }
        }
    
        public void snakeMove() {
            for (int i = snakeParts; i > 0; i--) {
                x[i] = x[i - 1];
                y[i] = y[i - 1];
            }
    
            if (!directions.isEmpty()) {
                currentDirection = directions.pop();
            }
    
            switch (currentDirection) {
                case "H":
                    x[0] = x[0] + bodySize;
                    break;
                case "V":
                    x[0] = x[0] - bodySize;
                    break;
                case "U":
                    y[0] = y[0] - bodySize;
                    break;
                case "N":
                    y[0] = y[0] + bodySize;
                    break;
            }
        }
    
        public static void newFruit() {
            xNormalFruit = (rollDice(WIDTH / bodySize) * bodySize) - bodySize;
            yNormalFruit = (rollDice((HEIGHT - 40) / bodySize) * bodySize) - bodySize;
        }
    
        public static int rollDice(int numberOfSides) {
            //Kastar en tärning med ett specifikt antal sidor.
            return (int) (Math.random() * numberOfSides + 1);
        }
    
        @Override
        public void actionPerformed(ActionEvent actionEvent) {
            if (actionEvent.getSource() == restartButton && isDead) {
                isDead = false;
                for (int i = 0; i < snakeParts; i++) {
                    if (i == 0) {
                        x[i] = 0;
                        y[i] = 0;
                    } else {
                        x[i] = 0 - bodySize;
                        y[i] = 0;
                    }
                }
                gameRunning = true;
                tmMove.start();
                //direction = "H";
                directions.clear();
                directions.add("H");
                window.remove(restartButton);
                score = 0;
                snakeParts = 7;
                newFruit();
                repaint();
            }
            if (actionEvent.getSource() == toInstructionsButton && !instructions) {
                instructions = true;
                window.remove(toInstructionsButton);
                repaint();
            }
            if (actionEvent.getSource() == tmMove) {
                if (gameRunning) {
                    snakeMove();
                    checkFruit();
                    checkCollisions();
                } else {
                    repaint();
                }
                repaint();
            }
        }
    
        @Override
        public void keyTyped(KeyEvent ke) {
        }
    
        @Override
        public void keyPressed(KeyEvent ke) {
    
            if (ke.getKeyCode() == KeyEvent.VK_SPACE && !gameRunning && instructions) {
                snakeMove();
                checkFruit();
                checkCollisions();
                newFruit();
                gameRunning = true;
                instructions = false;
            }
            if (ke.getKeyCode() == KeyEvent.VK_SPACE && gameRunning) {
                if (gameStarted) {
                    gameStarted = false;
                    tmMove.stop();
                } else {
                    tmMove.start();
                    gameStarted = true;
                }
            }
            if (gameStarted) {
                switch (ke.getKeyCode()) {
                    case KeyEvent.VK_RIGHT:
                    case KeyEvent.VK_D:
                        directions.add("H");
                        break;
                    case KeyEvent.VK_LEFT:
                    case KeyEvent.VK_A:
                        directions.add("V");
                        break;
                    case KeyEvent.VK_UP:
                    case KeyEvent.VK_W:
                        directions.add("U");
                        break;
                    case KeyEvent.VK_DOWN:
                    case KeyEvent.VK_S:
                        directions.add("N");
                        break;
                    case KeyEvent.VK_E:
                        tmMove.setDelay(200);
                        break;
                    case KeyEvent.VK_M:
                        tmMove.setDelay(150);
                        break;
                    case KeyEvent.VK_H:
                        tmMove.setDelay(100);
                        break;
                }
            }
        }
    
        @Override
        public void keyReleased(KeyEvent ke) {
        }
    }
    
    
    导入javax.sound.sampled.*;
    导入javax.swing.*;
    导入java.awt.*;
    导入java.awt.event.ActionEvent;
    导入java.awt.event.ActionListener;
    导入java.awt.event.KeyEvent;
    导入java.awt.event.KeyListener;
    导入java.io.File;
    导入java.util.LinkedList;
    公共类FirstGraphic扩展JPanel实现ActionListener、KeyListener{
    //斯托莱克·潘斯特雷特
    静态整数宽度=800,高度=840;
    定时器tmMove=新定时器(150,此);
    私有JFrame窗口;
    静态int bodySize=40,xNormalFruit=0,ynnormalfruit=0,gameSquares=(宽度*高度)/体型,
    蛇形部分=7,分数=0,重启按钮宽度=190,重启按钮宽度=50;
    静态整数x[]=新整数[gameSquares];
    静态整数y[]=新整数[gameSquares];
    私有字符串方向;
    布尔gameRunning=false,gameStarted=false,instructions=false,isDead=false;
    公共静态JButton restartButton=newjbutton(“startaom”),toInstructionsButton=newjbutton(“Nästa”);
    私有LinkedList方向=新建LinkedList();
    公共静态void main(字符串[]args){
    JFrame窗口=新JFrame(“蛇游戏”);
    FirstGraphic内容=新的FirstGraphic(窗口);
    setContentPane(内容);
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.setresizeable(false);
    window.pack();
    restartButton.setBounds((宽度/2)-(restartButtonWIDTH)/2,(高度-40)/2+100,restartButtonWIDTH,restartButtonHEIGHT);
    restartButton.setBackground(新颜色(48165,55));
    setFont(新字体(“Arial”,Font.BOLD,20));
    window.setLocationRelativeTo(空);
    window.setVisible(true);
    content.setUp();
    }
    公共FirstGraphic(JFrame窗口){
    超级();
    setPreferredSize(新尺寸(宽度、高度));
    设置聚焦(真);
    requestFocus();
    this.window=窗口;
    }
    公共作废设置(){
    addKeyListener(此);
    设置聚焦(真);
    setFocusTraversalKeysEnabled(false);
    restartButton.addActionListener(此);
    指示。添加(“H”);
    }
    @凌驾
    公共组件(图形g){
    超级组件(g);
    如果(游戏运行){
    g、 setColor(新颜色(0,0,0));
    g、 fillRect(0,0,宽度,(高度-40));
    g、 setColor(新颜色(63116、41255));
    
    public void snakeMove() {
        ...
    
        if (!directions.isEmpty()) { // if its not empty we have a new key(s) to process
            // proccess the keys pressed from the oldest to the newest and set the new direction
            currentDirection = directions.pop(); // takes the first oldest key from the queue
        }
    
        switch (currentDirection) {
            ...
        }
    }
    
    
    import javax.sound.sampled.*;
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import java.io.File;
    import java.util.LinkedList;
    
    public class FirstGraphic extends JPanel implements ActionListener, KeyListener {
    
        //Storlek på fönstret
        static int WIDTH = 800, HEIGHT = 840;
    
        Timer tmMove = new Timer(150, this);
    
        private JFrame window;
    
        static int bodySize = 40, xNormalFruit = 0, yNormalFruit = 0, gameSquares = (WIDTH * HEIGHT) / bodySize,
                snakeParts = 7, score = 0, restartButtonWIDTH = 190, restartButtonHEIGHT = 50;
    
        static int x[] = new int[gameSquares];
        static int y[] = new int[gameSquares];
    
        private String currentDirection;
        boolean gameRunning = false, gameStarted = false, instructions = false, isDead = false;
    
        public static JButton restartButton = new JButton("STARTA OM"), toInstructionsButton = new JButton("Nästa");
    
        private LinkedList<String> directions = new LinkedList<>();
    
        public static void main(String[] args) {
            JFrame window = new JFrame("Snake Game");
            FirstGraphic content = new FirstGraphic(window);
            window.setContentPane(content);
            window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            window.setResizable(false);
            window.pack();
            restartButton.setBounds((WIDTH / 2) - (restartButtonWIDTH) / 2, (HEIGHT - 40) / 2 + 100, restartButtonWIDTH, restartButtonHEIGHT);
            restartButton.setBackground(new Color(48, 165, 55));
            restartButton.setFont(new Font("Arial", Font.BOLD, 20));
            window.setLocationRelativeTo(null);
            window.setVisible(true);
            content.setUp();
        }
    
        public FirstGraphic(JFrame window) {
            super();
            setPreferredSize(new Dimension(WIDTH, HEIGHT));
            setFocusable(true);
            requestFocus();
            this.window = window;
        }
    
        public void setUp() {
            addKeyListener(this);
            setFocusable(true);
            setFocusTraversalKeysEnabled(false);
            restartButton.addActionListener(this);
            directions.add("H");
        }
    
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (gameRunning) {
                g.setColor(new Color(0, 0, 0));
                g.fillRect(0, 0, WIDTH, (HEIGHT - 40));
                g.setColor(new Color(63, 116, 41, 255));
                g.fillRect(0, HEIGHT - 40, WIDTH, (2));
                g.setColor(new Color(0, 0, 0, 240));
                g.fillRect(0, HEIGHT - 38, WIDTH, 38);
                g.setColor(new Color(0, 0, 0));
            }
            draw(g);
        }
    
        public void draw(Graphics g) {
            if (gameRunning) {
                g.setColor(new Color(35, 179, 52, 223));
                g.fillOval(xNormalFruit, yNormalFruit, bodySize, bodySize);
                g.setColor(new Color(44, 141, 23, 255));
                g.setFont(new Font("Arial", Font.BOLD, 18));
                for (int i = 0; i < snakeParts; i++) {
                    if (i == 0) {
                        g.setColor(Color.RED);
                        g.fillOval(x[i], y[i], bodySize, bodySize);
                    } else {
                        g.setColor(Color.PINK);
                        g.fillOval(x[i], y[i], bodySize, bodySize);
                    }
                }
            } else if (!gameRunning && gameStarted) {
                gameOver(g);
            } else if (!instructions) {
                startScene(g);
            } else {
                instructions(g);
            }
        }
    
        public void startScene(Graphics g) {
            g.setColor(Color.BLACK);
            g.fillRect(0, 0, WIDTH, HEIGHT);
            g.setColor(Color.WHITE);
            g.setFont(new Font("Arial", Font.BOLD, 85));
            g.drawString("Ormen Olle's", 150, 170);
            g.drawString("Äventyr", 235, 254);
            window.add(toInstructionsButton);
            toInstructionsButton.setBounds(240, 660, 300, 100);
            toInstructionsButton.setBackground(new Color(48, 165, 55));
            toInstructionsButton.setForeground(Color.BLACK);
            toInstructionsButton.setFont(new Font("Arial", Font.BOLD, 60));
            toInstructionsButton.addActionListener(this);
        }
    
        public void instructions(Graphics g) {
            g.setFont(new Font("Arial", Font.BOLD, 85));
            g.setColor(new Color(14, 69, 114));
            g.drawString("PRESS SPACE", 210, 720);
    
        }
    
        public void gameOver(Graphics g) {
            g.setColor(Color.BLACK);
            g.fillRect(0, 0, WIDTH, HEIGHT);
            g.setColor(Color.red);
            g.setFont(new Font("Arial", Font.BOLD, 65));
            FontMetrics metrics = getFontMetrics(g.getFont());
            g.drawString("Du dog!", (WIDTH - metrics.stringWidth("Du dog!")) / 2, (HEIGHT - 40) / 2);
            g.setColor(new Color(44, 141, 23, 255));
            g.setFont(new Font("Arial", Font.BOLD, 20));
            FontMetrics metrics2 = getFontMetrics(g.getFont());
            g.drawString("SCORE: " + score, (WIDTH - metrics2.stringWidth("SCORE:  " + score)) / 2, 50);
            window.add(restartButton);
        }
    
        public void checkFruit() {
            if ((x[0] == xNormalFruit) && (y[0] == yNormalFruit)) {
                snakeParts++;
                score++;
                newFruit();
            }
            for (int v = 1; v < snakeParts; v++) {
                if ((x[v] == xNormalFruit) && y[v] == yNormalFruit) {
                    newFruit();
                }
            }
        }
    
        public void checkCollisions() {
            for (int i = snakeParts; i > 0; i--) {
                if ((x[0] == x[i]) && (y[0] == y[i])) {
                    gameRunning = false;
                    isDead = true;
                }
            }
            if (x[0] < 0) {
                gameRunning = false;
                isDead = true;
            }
            if (x[0] == WIDTH) {
                gameRunning = false;
                isDead = true;
            }
            if (y[0] < 0) {
                gameRunning = false;
                isDead = true;
            }
            if (y[0] > (HEIGHT - 40) - bodySize) {
                gameRunning = false;
                isDead = true;
            }
            if (!gameRunning) {
                tmMove.stop();
            }
        }
    
        public void snakeMove() {
            for (int i = snakeParts; i > 0; i--) {
                x[i] = x[i - 1];
                y[i] = y[i - 1];
            }
    
            if (!directions.isEmpty()) {
                currentDirection = directions.pop();
            }
    
            switch (currentDirection) {
                case "H":
                    x[0] = x[0] + bodySize;
                    break;
                case "V":
                    x[0] = x[0] - bodySize;
                    break;
                case "U":
                    y[0] = y[0] - bodySize;
                    break;
                case "N":
                    y[0] = y[0] + bodySize;
                    break;
            }
        }
    
        public static void newFruit() {
            xNormalFruit = (rollDice(WIDTH / bodySize) * bodySize) - bodySize;
            yNormalFruit = (rollDice((HEIGHT - 40) / bodySize) * bodySize) - bodySize;
        }
    
        public static int rollDice(int numberOfSides) {
            //Kastar en tärning med ett specifikt antal sidor.
            return (int) (Math.random() * numberOfSides + 1);
        }
    
        @Override
        public void actionPerformed(ActionEvent actionEvent) {
            if (actionEvent.getSource() == restartButton && isDead) {
                isDead = false;
                for (int i = 0; i < snakeParts; i++) {
                    if (i == 0) {
                        x[i] = 0;
                        y[i] = 0;
                    } else {
                        x[i] = 0 - bodySize;
                        y[i] = 0;
                    }
                }
                gameRunning = true;
                tmMove.start();
                //direction = "H";
                directions.clear();
                directions.add("H");
                window.remove(restartButton);
                score = 0;
                snakeParts = 7;
                newFruit();
                repaint();
            }
            if (actionEvent.getSource() == toInstructionsButton && !instructions) {
                instructions = true;
                window.remove(toInstructionsButton);
                repaint();
            }
            if (actionEvent.getSource() == tmMove) {
                if (gameRunning) {
                    snakeMove();
                    checkFruit();
                    checkCollisions();
                } else {
                    repaint();
                }
                repaint();
            }
        }
    
        @Override
        public void keyTyped(KeyEvent ke) {
        }
    
        @Override
        public void keyPressed(KeyEvent ke) {
    
            if (ke.getKeyCode() == KeyEvent.VK_SPACE && !gameRunning && instructions) {
                snakeMove();
                checkFruit();
                checkCollisions();
                newFruit();
                gameRunning = true;
                instructions = false;
            }
            if (ke.getKeyCode() == KeyEvent.VK_SPACE && gameRunning) {
                if (gameStarted) {
                    gameStarted = false;
                    tmMove.stop();
                } else {
                    tmMove.start();
                    gameStarted = true;
                }
            }
            if (gameStarted) {
                switch (ke.getKeyCode()) {
                    case KeyEvent.VK_RIGHT:
                    case KeyEvent.VK_D:
                        directions.add("H");
                        break;
                    case KeyEvent.VK_LEFT:
                    case KeyEvent.VK_A:
                        directions.add("V");
                        break;
                    case KeyEvent.VK_UP:
                    case KeyEvent.VK_W:
                        directions.add("U");
                        break;
                    case KeyEvent.VK_DOWN:
                    case KeyEvent.VK_S:
                        directions.add("N");
                        break;
                    case KeyEvent.VK_E:
                        tmMove.setDelay(200);
                        break;
                    case KeyEvent.VK_M:
                        tmMove.setDelay(150);
                        break;
                    case KeyEvent.VK_H:
                        tmMove.setDelay(100);
                        break;
                }
            }
        }
    
        @Override
        public void keyReleased(KeyEvent ke) {
        }
    }