Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
创建一个蛇游戏,当你按两个方向时,蛇会很快地吃掉自己[Java]_Java_User Interface - Fatal编程技术网

创建一个蛇游戏,当你按两个方向时,蛇会很快地吃掉自己[Java]

创建一个蛇游戏,当你按两个方向时,蛇会很快地吃掉自己[Java],java,user-interface,Java,User Interface,我希望这是有意义的,但我正在尝试用Java制作一个蛇型游戏,如果你同时按两个方向/太快,蛇就会爬到自己的上面,让你输。 举个例子,如果你向下,然后很快地向上打,你会让蛇在同一根柱子上直线上升,然后自杀,但它应该先向右转一圈,然后再向上一圈。如果有人能帮我,那太好了,谢谢 package tk.sketchistgames.Snake; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import

我希望这是有意义的,但我正在尝试用Java制作一个蛇型游戏,如果你同时按两个方向/太快,蛇就会爬到自己的上面,让你输。 举个例子,如果你向下,然后很快地向上打,你会让蛇在同一根柱子上直线上升,然后自杀,但它应该先向右转一圈,然后再向上一圈。如果有人能帮我,那太好了,谢谢

package tk.sketchistgames.Snake; 
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.IOException;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Board extends JPanel implements ActionListener{
        /**
         * Main graphical area for Snake
         */
        private static final long serialVersionUID = 4085437479211945011L;

        private final int WIDTH = 600;
        private final int HEIGHT = 600;
        private final int DOT_SIZE = 10;
        private final int ALL_DOTS = 1200;
        private final int RAND_POS = 59;
        public static int DELAY = 90;


        private int x[] = new int[ALL_DOTS];
        private int y[] = new int[ALL_DOTS];

        private int dots, food_x, food_y, pdown_x, pdown_y, rdouble_x, rdouble_y, powerUp_x, powerUp_y, half_x, half_y;

        private boolean left = false;
        private boolean right = true;
        private boolean up = false;
        private boolean down = false;
        private boolean inGame = true;
        private int score = 0;
        private int fruitEaten = 0;
        private boolean Bonus = false;
        private boolean RDouble = false;
        private boolean bpower = false;
        private boolean halfpower = false;

        private Timer timer;
        private Image food;
        private Image head;
        private Image body;
        private Image pdown;
        private Image rdouble;
        private Image powerUp;
        private Image half;


        public Board() {
        addKeyListener(new TAdapter());

        setBackground(Color.decode("0x3F919E"));

        ImageIcon iid = new ImageIcon(this.getClass().getResource("/images/body.png"));
        body = iid.getImage();

        ImageIcon iia = new ImageIcon(this.getClass().getResource("/images/food.png"));
        food = iia.getImage();

        ImageIcon iih = new ImageIcon(this.getClass().getResource("/images/head.png"));
        head = iih.getImage();

        ImageIcon iipd = new ImageIcon(this.getClass().getResource("/images/pdown.png"));
        pdown = iipd.getImage();
        ImageIcon iird = new ImageIcon(this.getClass().getResource("/images/pup2.png"));
        rdouble = iird.getImage();
        ImageIcon iipu1 = new ImageIcon(this.getClass().getResource("/images/pup1.png"));
        powerUp = iipu1.getImage();
        ImageIcon iihd = new ImageIcon(this.getClass().getResource("/images/halfDown.png"));
        half = iihd.getImage();
        setFocusable(true);
        initGame();
    }


    public void initGame() {

        dots = 5;
        for (int z = 0; z < dots; z++) {
            x[z] = 50 - z*10;
            y[z] = 50;
        }

        locateFood();

        timer = new Timer(DELAY, this);
        timer.start();
    }
    public void checkApple() throws UnsupportedAudioFileException, IOException, LineUnavailableException {
        if ((x[0] == pdown_x) && (y[0] == pdown_y)){
                dots -= 1;
                score -= 50;
                AudioInputStream audioIn = AudioSystem.getAudioInputStream(Board.class.getResource("/sounds/powerdown.wav"));
            Clip clip = AudioSystem.getClip();
            clip.open(audioIn);
            clip.start();
                bpower = false;
        }
        if ((x[0] == half_x) && (y[0] == half_y)){
                dots = dots /2;
                score = score /2;
                AudioInputStream audioIn = AudioSystem.getAudioInputStream(Board.class.getResource("/sounds/powerdown.wav"));
            Clip clip = AudioSystem.getClip();
            clip.open(audioIn);
            clip.start();
            clip.start();
                halfpower = false;
        }
        if ((x[0] == powerUp_x) && (y[0] == powerUp_y)){
                dots += 4;
                score += 100;
                AudioInputStream audioIn = AudioSystem.getAudioInputStream(Board.class.getResource("/sounds/powerup1.wav"));
            Clip clip = AudioSystem.getClip();
            clip.open(audioIn);
            clip.start();
                Bonus = false;
        }
        if ((x[0] == rdouble_x) && (y[0] == rdouble_y)){
                dots = dots * 2;
                score += 1000;
                AudioInputStream audioIn = AudioSystem.getAudioInputStream(Board.class.getResource("/sounds/powerup2.wav"));
            Clip clip = AudioSystem.getClip();
            clip.open(audioIn);
            clip.start();
                RDouble = false;
        }
        if ((x[0] == food_x) && (y[0] == food_y)) {
            dots++;
            long r = Math.round(Math.random() * 10);
            if(r == 4){
                locatePowerUp();
                Bonus = true;
            }
            long half = Math.round(Math.random() * 175);
            System.out.println(half);
            if(half == 89){
                locateHalfDown();
                halfpower = true;
            }
            long rdouble = Math.round(Math.random() * 100);
            if(rdouble == 50){
                locateDoubleUp();
                RDouble = true;
            }
            long badpower = Math.round(Math.random() * 25);
            if(badpower == 25 || badpower == 20 || badpower == 15|| badpower == 10 || badpower == 5|| badpower == 0){
                locatePowerDown();
                bpower = true;
            }
            score += (50 + fruitEaten);
            AudioInputStream audioIn = AudioSystem.getAudioInputStream(Board.class.getResource("/sounds/eat.wav"));
            Clip clip = AudioSystem.getClip();
            clip.open(audioIn);
            clip.start();
            fruitEaten++;
            locateFood();
        }
    }


    public void paint(Graphics g) {
        super.paint(g);

        if (inGame) {
                if(halfpower){
                        g.drawImage(half, half_x, half_y, this);
                }
            if(Bonus){
                         g.drawImage(powerUp, powerUp_x, powerUp_y, this);

                }
            if(RDouble){
                g.drawImage(rdouble, rdouble_x, rdouble_y, this);
            }
            if(dots <= 0) gameOver(g);
            g.setColor(Color.white);
            Font small1 = new Font("arcadepix", Font.PLAIN, 20);

            g.setFont(small1);
            g.drawString("Score: " + score +  "  Food Eaten: " + fruitEaten + " Length: " + dots, 15, 15);

            g.drawImage(food, food_x, food_y, this);
            if(bpower){
                g.drawImage(pdown, pdown_x, pdown_y, this);
            }
            for (int z = 0; z < dots; z++) {
                if (z == 0)
                    g.drawImage(head, x[z], y[z], this);
                else g.drawImage(body, x[z], y[z], this);
            }
            if(Menu.pause){
                g.drawString("Paused! 'P' To unpause!", 20, 100);
                for (int z = 0; z < dots; z++) {
                    x[z] = 50 - z*10;
                    y[z] = 50;
                }
            }

            Toolkit.getDefaultToolkit().sync();
            g.dispose();

        }else{
                gameOver(g);
        }
        }


    public void gameOver(Graphics g) {
        if(dots >= 300){
                String msg = "You won!";
            Font small = new Font("arcadepix", Font.PLAIN, 20);
            FontMetrics metr = this.getFontMetrics(small);
            g.setColor(Color.white);
            g.setFont(small);
            g.drawString(msg, (WIDTH - metr.stringWidth(msg)) / 2, HEIGHT / 2);
            g.drawString("Total Score: " + score +"!", (WIDTH - metr.stringWidth(msg)) /2 - 12, (HEIGHT / 2) - 18);
            g.drawString("Total Food Eaten: " + dots + "!", (WIDTH - metr.stringWidth(msg)) /2 - 72, (HEIGHT / 2) - 38);
            g.drawString("Press Space to play again!", (WIDTH - metr.stringWidth(msg)) /2 - 77, (HEIGHT / 2) + 18);
            setBackground(Color.red);


        }else{
        String msg = "Game Over";
        Font small = new Font("arcadepix", Font.PLAIN, 20);
        FontMetrics metr = this.getFontMetrics(small);
        g.setColor(Color.white);
        g.setFont(small);
        g.drawString(msg, (WIDTH - metr.stringWidth(msg)) / 2, HEIGHT / 2);
        g.drawString("Total Score: " + score, (WIDTH - metr.stringWidth(msg)) /2 - 12, (HEIGHT / 2) - 18);
        g.drawString("Press Space to Continue", (WIDTH - metr.stringWidth(msg)) /2 - 77, (HEIGHT / 2) + 18);
        setBackground(Color.decode("0x3F919E"));
    }
    }



    public void move() {

        for (int z = dots; z > 0; z--) {
            x[z] = x[(z - 1)];
            y[z] = y[(z - 1)];
        }

        if (left) {
            x[0] -= DOT_SIZE;
        }

        if (right) {
            x[0] += DOT_SIZE;
        }

        if (up) {
            y[0] -= DOT_SIZE;
        }

        if (down) {
            y[0] += DOT_SIZE;
        }
    }


    public void checkCollision() {

          for (int z = dots; z > 0; z--) {

              if ((z > 4) && (x[0] == x[z]) && (y[0] == y[z])) {
                  inGame = false;
              }
          }

        if (y[0] > HEIGHT) {
            inGame = false;
        }

        if (y[0] < 0) {
            inGame = false;
        }

        if (x[0] > WIDTH) {
            inGame = false;
        }

        if (x[0] < 0) {
            inGame = false;
        }
    }

    public void locateFood() {
        int r = (int) (Math.random() * RAND_POS);
        food_x = ((r * DOT_SIZE));
        r = (int) (Math.random() * RAND_POS);
        food_y = ((r * DOT_SIZE));
    }
    public void locatePowerDown() {
        int r = (int) (Math.random() * RAND_POS);
        pdown_x = ((r * DOT_SIZE));
        r = (int) (Math.random() * RAND_POS);
        pdown_y = ((r * DOT_SIZE));
    }
    public void locateDoubleUp() {
        int r = (int) (Math.random() * RAND_POS);
        rdouble_x= ((r * DOT_SIZE));
        r = (int) (Math.random() * RAND_POS);
        rdouble_y = ((r * DOT_SIZE));
    }
    public void locatePowerUp() {
        int r = (int) (Math.random() * RAND_POS);
        powerUp_x= ((r * DOT_SIZE));
        r = (int) (Math.random() * RAND_POS);
        powerUp_y = ((r * DOT_SIZE));
    }
    public void locateHalfDown() {
        int r = (int) (Math.random() * RAND_POS);
        half_x= ((r * DOT_SIZE));
        r = (int) (Math.random() * RAND_POS);
        half_y = ((r * DOT_SIZE));
    }

    public void actionPerformed(ActionEvent e) {

        if (inGame) {
                if(Menu.pause){

                }
            try {
                                checkApple();
                        } catch (UnsupportedAudioFileException e1) {
                                e1.printStackTrace();
                        } catch (IOException e1) {
                                e1.printStackTrace();
                        } catch (LineUnavailableException e1) {
                                e1.printStackTrace();
                        }
            checkCollision();
            move();
                }

        repaint();
}


    public void reset(){
        left = false;
        right = true;
        up = false;
        down = false;
        inGame = true;
        score = 0;
        fruitEaten = 0;
        for (int z = 0; z < dots; z++) {
            x[z] = 50 - z*10;
            y[z] = 50;
        }
        dots = 5;
        bpower = false;
        locatePowerDown();
        RDouble = false;
        locateDoubleUp();
        locatePowerUp();
        locateFood();
        repaint();

    }
    private class TAdapter extends KeyAdapter {

        public void keyPressed(KeyEvent e) {

            int key = e.getKeyCode();
            if(key == KeyEvent.VK_SPACE){
                if(inGame){
                        if(Menu.pause){
                                Menu.pause = false;
                        }else if(!Menu.pause){
                                Menu.pause = true;
                        }
                }
                if(!inGame){
                        reset();
                }
            }

            if(key == KeyEvent.VK_P){
                if(Menu.pause){
                        Menu.pause = false;
                }else if(!Menu.pause){
                        Menu.pause = true;
                }
            }
            if ((key == KeyEvent.VK_LEFT || key == KeyEvent.VK_A) && (!right)) {
                left = true;
                up = false;
                down = false;
            }

            if ((key == KeyEvent.VK_RIGHT ||key == KeyEvent.VK_D) && (!left)) {
                right = true;
                up = false;
                down = false;
            }

            if ((key == KeyEvent.VK_UP || key == KeyEvent.VK_W) && (!down)) {
                up = true;
                right = false;
                left = false;
            }

            if ((key == KeyEvent.VK_DOWN || key == KeyEvent.VK_S) && (!up)) {
                down = true;
                right = false;
                left = false;
            }
        }


                }
    }

根据您的描述,您的代码正在移动之前更改布尔变量。一个简单的解决方案是将所有移动存储在一个队列中,并通过删除它们进行处理,这样可以确保不会覆盖移动

换句话说,每次记录一个会改变布尔值的关键事件时,在队列中存储某种类型的信号,例如int、字符串、枚举等,在move方法中,只需从队列前面移除信号,并像处理布尔变量一样处理它。如果您要为上下左右使用枚举,那么它将是相当可读的,并且您可以使用开关案例来处理每个移动

其中,movement是从队列中移除的信号,上下左右是enum,因此它们可以是int常量,但正如Bloch在effectivejava中所建议的那样,更喜欢enum类型而不是int常量

private enum Movement { UP, DOWN, RIGHT, LEFT }
这允许您在上面的开关中引用这些类型,并按如下方式实例化队列:

Queue<Movement> movementQueue = new ArrayDeque<Movement>();
Movement movement = movementQueue.poll();
当您准备好使用它们时,请按如下方式访问它们:

Queue<Movement> movementQueue = new ArrayDeque<Movement>();
Movement movement = movementQueue.poll();
有关队列的详细信息: 有关枚举的详细信息:


另外,因为您说您是Java新手,所以我建议您首先使用Java作为开销视图,使用有效的Java来学习大量的最佳实践。

第一个建议是将您的方法分解为更简单、更易于阅读的方法。这将有助于缩小您的问题范围,并帮助我们更快地帮助您解决问题。在您的按键功能中,你正在检查以确保他们没有按与上次按下的键相反的方向-最好检查他们没有按与蛇实际移动方向相反的方向。顺便说一句,你不应该覆盖SwingComponents中的paint,paint Component阅读此内容,你是忍者你。我也希望发布一些关于队列的信息。我不想问你代码,因为我什么都学不到,但你能帮我多一点吗?我对Java非常陌生,所以我对它不太了解,比如如何使用队列?另外,当你评论向上代码、向左代码、向右代码或向下代码时,你指的是关键代码吗?如果我问得太多,我很抱歉,但正如我之前所说,我还在学习。一点问题都没有,至于向上的代码等等,我的意思是你把你的动作代码放在那些方向上-从左到右-那些注释所在的地方。至于使用队列,我想你从来没有见过一个是彻底的。队列是一种数据结构,您可以在其中向末尾添加一个元素,然后将它们从前端删除?这或多或少是一个等待名单。在java中,队列是一个接口,所以您可以使用实现它的任何类。具体来说,如果您真的选择了以下两个选项之一,则会将其分为两个注释。ArrayDeque-当您在内部需要数组时。LinkedList-当您需要链接列表时。通常,您会发现ArrayDeque速度更快,因此我将在这里使用它。要使用队列,您只需要一个实例变量,如下面的private queue movementQueue;您在构造函数中实例化它,使其成为您想要的实现,在本例中,movementQueue=new ArrayDeque;然后,只需调用offer在末尾添加一个动作,然后轮询从前面删除一个动作。要使用枚举类型,请参阅我将要在原始帖子中进行的编辑。好的,感谢所有帮助,但这似乎不起作用。它解决了这个问题,但也造成了一个新的问题。它走得太慢了。