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