调试用JavaSwing编写的蛇游戏

调试用JavaSwing编写的蛇游戏,java,user-interface,debugging,Java,User Interface,Debugging,我在为snake swing应用程序制作主菜单时遇到问题。当我运行应用程序时,我希望用户能够单击开始游戏按钮并玩游戏。但是,当我单击开始游戏按钮时,卡会卡住,并且不会显示扩展JPanel的游戏类。修补之后,我发现如果我从GameFrame类中删除game.play()方法,它将加载下一张“卡”,因为我正在使用CardLayout显示不同的窗口。我不确定是什么原因导致我的游戏功能或游戏类停止工作。我肯定我错过了一些简单的东西 // GameFrame.java import java.awt

我在为snake swing应用程序制作主菜单时遇到问题。当我运行应用程序时,我希望用户能够单击开始游戏按钮并玩游戏。但是,当我单击开始游戏按钮时,卡会卡住,并且不会显示扩展JPanel的游戏类。修补之后,我发现如果我从GameFrame类中删除game.play()方法,它将加载下一张“卡”,因为我正在使用CardLayout显示不同的窗口。我不确定是什么原因导致我的游戏功能或游戏类停止工作。我肯定我错过了一些简单的东西

// GameFrame.java

  import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.JPanel;

// TODO: read up on layouts, add layout to the game
public class GameFrame{
    /**
    *
    */
    private static final long serialVersionUID = 1L;

   public GameFrame() {

   JFrame frame = new JFrame();
   JPanel initMenu = new JPanel();
   JPanel mainPanel = new JPanel();
   Game game = new Game();

   frame.setSize(400, 400);
   frame.setVisible(true);
   frame.setTitle("SnEk");
   frame.add(mainPanel);

   CardLayout cl = new CardLayout();

   // add cardlayout to the mainPanel which will be the container for the the other two 'cards'
   mainPanel.setLayout(cl);

  // initMenu.setBackground(Color.BLACK);

   mainPanel.add(initMenu);
   mainPanel.add(game);

   JButton startButton = new JButton("Start Game");
   initMenu.add(startButton);

   startButton.addActionListener(new ActionListener() {
       public void actionPerformed(ActionEvent e) {
           cl.next(mainPanel);
       while(game.isAlive){
               game.play();
               }            
       }
       });
   }
   public static void main(String[] args){
           new GameFrame();
   }
}
//Game.java
导入javax.swing.JPanel;
导入java.awt.event.KeyListener;
导入java.util.array;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.event.KeyEvent;
导入java.awt.Color;
导入java.awt.Graphics;
导入java.util.Random;
公共类游戏扩展JPanel实现ActionListener、KeyListener{
私有静态最终长serialVersionUID=1L;
公共int板_宽度=400;
公共内板高度=400;
//跟踪蛇头撞击游戏板边界的字段
公共字符串isOnWhichBorder=“”;
int randX=(int)(Math.random()*((电路板宽度)+1));
int randY=(int)(Math.random()*((BOARD_HEIGHT)+1));
苹果=新苹果(randX,randY,20,20);
蛇=新蛇();
public int[]RIGHT=new int[]{snake.getOvalHeight(),0};
public int[]LEFT=new int[]{-snake.getOvalHeight(),0};
public int[]UP=new int[]{0,-snake.getOvalHeight()};
public int[]DOWN=new int[]{0,snake.getOvalHeight()};
公共布尔值为live=true;
//默认蛇方向向量向右移动
公共int[]方向=右;
公共游戏(){
//设置聚焦(真);
//TODO:检查keyListener实际需要在哪里使用g
//addKeyListener(此);
设置尺寸(板宽、板高);
挫折地面(颜色:白色);
}
@凌驾
公共组件(图形g){
超级组件(g);
if(apple.getIsEaten()){
apple.setX((int)(Math.random()*((BOARD_WIDTH)+1));
apple.setY((int)(Math.random()*((BOARD_HEIGHT)+1));
苹果树(假);
蛇。生长();
}
g、 setColor(Color.GREEN);
对于(int i=0;i如果((snake.getHead()[0]>=Math.abs(apple.getX()-apple.getWidth())&&(snake.getHead()[0]=Math.abs(apple.getY()-apple.getHeight())&(snake.getHead()[1]嘿@alexander,你能把代码简化一点吗?我建议去掉所有的游戏逻辑,给我们展示一个简单的问题示例,在这个示例中很容易看到有问题的一个组件(“开始游戏”按钮不起作用,其他什么都没有)。请查看此处,了解如何编写这些内容的详细说明:另外,最好向我们提供有关如何运行此程序的说明(即,您在shell或编辑器中调用什么来启动此程序?).Hey@alexander,你能把代码简化一点吗?我建议去掉所有的游戏逻辑,给我们展示一个简单的问题示例,在这个示例中很容易看到有问题的一个组件(“开始游戏”按钮不起作用,其他什么都没有)。请查看此处,了解如何编写这些内容的详细说明:另外,最好向我们提供有关如何运行此程序的说明(即,您在shell或编辑器中调用什么来启动此程序?)。
// Game.java

import javax.swing.JPanel;
import java.awt.event.KeyListener;
import java.util.Arrays;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;

public class Game extends JPanel implements ActionListener, KeyListener {

    private static final long serialVersionUID = 1L;

    public int BOARD_WIDTH = 400;
    public int BOARD_HEIGHT = 400;
    // field to keep track of snake head hitting the border of the game board
    public String isOnWhichBorder = "";

    int randX = (int)(Math.random() * ((BOARD_WIDTH) + 1));
    int randY = (int)(Math.random() * ((BOARD_HEIGHT) + 1));

    Apple apple = new Apple(randX, randY, 20, 20);
    Snake snake = new Snake();

    public int[] RIGHT = new int[]{snake.getOvalHeight(), 0};
    public int[] LEFT = new int[]{-snake.getOvalHeight(), 0};
    public int[] UP = new int[]{0,-snake.getOvalHeight()};
    public int[] DOWN = new int[]{0,snake.getOvalHeight()};

    public boolean isAlive = true;

    // default snake direction vector moves to the right
    public int[] direction = RIGHT;

    public Game(){

        //setFocusable(true);
        // TODO: check where keyListener actually needs to g
        //addKeyListener(this);    
        setSize(BOARD_WIDTH, BOARD_HEIGHT);
        setBackground(Color.WHITE);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if(apple.getIsEaten()){ 
            apple.setX((int)(Math.random() * ((BOARD_WIDTH) + 1)));
            apple.setY((int)(Math.random() * ((BOARD_HEIGHT) + 1)));
            apple.setIsEaten(false);
            snake.grow();
        }
        g.setColor(Color.GREEN);
        for(int i = 0; i < snake.getLength(); i++){
            g.fillOval(snake.getBodyXComponent(i), snake.getBodyYComponent(i), snake.getOvalHeight(), snake.getOvalWidth());
        }
        g.setColor(Color.RED);
        g.fillOval(apple.getX(), apple.getY(), apple.getWidth(), apple.getHeight());
    }
    /*
     * @param isOnWhichBorder the isOnWhichBorder to set
     */
    public void setIsOnWhichBorder(final String isOnWhichBorder) {
        this.isOnWhichBorder = isOnWhichBorder;
    }

    @Override
    public void keyTyped(final KeyEvent e) {
        // TODO Auto-generated method stub

    }

    // method to check if snake and apple are occupying the same point in the game board
    public boolean isCollision(Apple apple, Snake snake){
        if(((snake.getHead()[0] >= Math.abs(apple.getX() - apple.getWidth())) && (snake.getHead()[0] <= (apple.getX() + apple.getWidth()))) && ((snake.getHead()[1] >= Math.abs(apple.getY() - apple.getHeight())) && (snake.getHead()[1] <= (apple.getY() + apple.getHeight())))){
            return true;
        }
        return false;
    }
    /*
     Method to determine whether or not the snake head's x and y component are occupying the same coordinate as a body part 
    */
    // TODO: change isAlive variable to isGameOver
    public boolean isSnakeEatingItself(Snake snake){ 
        // grab head of the snake
        int[] head = snake.getHead();
        // check all body segments except the head
        for(int i = 0; i < snake.getLength() - 1; i++){
            // check if head x coord and head y coord equals body x coord and head y coord equals body y coord
            if((head[0] == snake.getBodyXComponent(i)) && (head[1] == snake.getBodyYComponent(i))){
                isAlive = false;
                return true;
            }
        }
        isAlive = true;
        return false;
    }
    // TODO: remove logic from keyPressed event, this method should only set the flags and do nothing else
    @Override
    public void keyPressed(KeyEvent e) {
    switch(e.getKeyCode()){
        case KeyEvent.VK_RIGHT:
            direction = RIGHT;
            break;
        case KeyEvent.VK_LEFT:
            direction = LEFT;
            break;
        case KeyEvent.VK_UP:
            direction = UP;
            break;
        case KeyEvent.VK_DOWN:
            direction = DOWN;
            break;
        }
    }

    public void play(){

        if(snake.getHead()[0] == 0 && !(snake.getSecondComponent()[0] == 400)){
            isOnWhichBorder = "LEFT";
         }
         if((snake.getHead()[0] == BOARD_WIDTH) && !(snake.getSecondComponent()[0] == 0)){
            isOnWhichBorder = "RIGHT";
         }
         if((snake.getHead()[1] == 0) && !(snake.getSecondComponent()[1] == 400)){
            isOnWhichBorder = "BOTTOM";
         }
         if((snake.getHead()[1] == BOARD_HEIGHT) && !(snake.getSecondComponent()[1] == 0)){
            isOnWhichBorder = "TOP";
         }
        if(isCollision(apple, snake)){
            apple.setIsEaten(true);
        }
        if(isSnakeEatingItself(snake)){
            System.out.println("eating itself");
        }
        snake.slither(isOnWhichBorder, direction);
        this.setIsOnWhichBorder("");
        repaint();
    }

    @Override
    public void keyReleased(final KeyEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void actionPerformed(final ActionEvent e) {

    }

}
Snake.java


// To store the snake class
// Goal of snake class: store direction, location of body parts
import java.util.ArrayList;
import java.util.Arrays;

public class Snake {
    // stores length of snake

    public static int OVAL_WIDTH = 10;
    public static int OVAL_HEIGHT = 10;

    public static String EMPTY = "";

    public int x;
    public int y;
    // arrayList holds the body elements of the snake
    public ArrayList<int[]> body = new ArrayList<>();

    public int[] directionVector = new int[]{};

    public Snake(){
        // add some initial body elements
        body.add(new int[]{100,100});
        body.add(new int[]{110,100});
        body.add(new int[]{120,100});
    }
    public int getOvalWidth(){
        return OVAL_WIDTH;
    }
    public int getOvalHeight(){
        return OVAL_HEIGHT;
    }
    public int getLength(){
        return body.size();
    }
    // method to return the head of the ArrayList representing Snake body
    public int[] getHead(){
        int xComponent = getBodyXComponent(body.size()-1);
        int yComponent = getBodyYComponent(body.size()-1);
        int[] head = new int[]{xComponent, yComponent};
        return head;
    }

    public int[] getSecondComponent(){
        return body.get(body.size()-2);
    }

    public int getBodyXComponent(int bodySegment){
        return body.get(bodySegment)[0];
    }

    public int getBodyYComponent(int bodySegment){
        return body.get(bodySegment)[1];
    }

    public void grow(){
        body.add(new int[]{this.getHead()[0] + directionVector[0], this.getHead()[1] + this.directionVector[1]});
        System.out.println("(\n");
        for(int[] part : body){
                System.out.println("( " + part[0] + "," + part[1] + ")");
            }
        }



    public void slither(String isWhichOnBorder, int[] direction){    
        // grab tail
        int[] tail = new int[]{body.get(0)[0], body.get(0)[1]};
        // logic to handle the case where the snake head is on the border of the map
        // TODO: make this conditional on the direction as well
        this.directionVector = direction;
        if(!isWhichOnBorder.equals(EMPTY)){
            System.out.println("hitting the isEmpty() statement");
            switch(isWhichOnBorder){
                case "TOP":
                    tail[1] = 0;
                    break;
                case "BOTTOM":
                    tail[1] = 400;
                    break;
                case "LEFT":
                    tail[0] = 400;
                    break;
                case "RIGHT":
                    tail[0] = 0;
                    break;
                default:
                    break;
            }
        }else{
            tail[0] = getHead()[0] + direction[0];
            tail[1] = getHead()[1] + direction[1];
            System.out.println("this is head of array: " + "( " + getHead()[0] + "," + getHead()[1] + ")");
        }

        body.remove(0);
        for(int[] part : body){
            System.out.println("( " + part[0] + "," + part[1] + ")");
        }
        body.add(tail);
        System.out.println("after adding new head: ");
        for(int[] part : body){
            System.out.println("( " + part[0] + "," + part[1] + ")");
        }
    }

}