【问题标题】:Snake game issue !!! java - swing - Jframe蛇游戏问题!!! java - 摆动 - Jframe
【发布时间】:2016-04-17 20:31:22
【问题描述】:

我是一名高中生,目前正在java swing(JFrame)上做蛇游戏(吃食物版);在 NetBeans IDE 8.0.2 中。到目前为止,我能够移动蛇并随机生成食物;这条蛇虽然正在吃食物,但在撞到棋盘周围的边界/边界时会停下来。但说实话,我真的不知道如何从头开始养蛇。人们建议我使用 ArrayList 以便我可以添加相同块的片段(Jpanel)。说实话,我对 ArrayList 不是很熟悉。那么你们会帮我解决如何制作 ArrayList 并用它来种植蛇吗?另外,当蛇向前移动时(在任何方向),我如何阻止蛇向后移动(与前进按钮相反),它不应该只能左右移动吗?我希望你们明白我的意思。最后,由于我的食物是随机生成的,它有时会与蛇重叠,我该如何阻止食物重叠在蛇身上。

此链接将向您展示我的游戏是什么样子(红色块是我的蛇): http://i.stack.imgur.com/xko2n.jpg

在上面的链接中,红色块是我的蛇,黄色块是我的食物,额外的一块是我想添加到蛇并让它生长的块。那里的蓝线是我的边界/边界。

到目前为止,这是我的代码:

package culminating;

import java.util.Random;
import javax.swing.JLabel;
import javax.swing.Timer;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Rectangle;
import javax.swing.JOptionPane;

public class Visual extends javax.swing.JFrame {
 JLabel[] food = new JLabel[10];
 JLabel[] border = new JLabel[4];
 Timer s_timer;
 boolean[] keys = new boolean[525];
 boolean up = false, down = false;
 int count;
 static int X,Y, lcount;
  public Visual() {
    initComponents();
}


@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">                          
private void initComponents() {

    jPanel1 = new javax.swing.JPanel();
    snake = new javax.swing.JLabel();
    jLabel8 = new javax.swing.JLabel();
    jLabel2 = new javax.swing.JLabel();
    jLabel10 = new javax.swing.JLabel();
    jLabel7 = new javax.swing.JLabel();
    jLabel4 = new javax.swing.JLabel();
    jLabel5 = new javax.swing.JLabel();
    jLabel9 = new javax.swing.JLabel();
    jLabel3 = new javax.swing.JLabel();
    jLabel6 = new javax.swing.JLabel();
    jLabel1 = new javax.swing.JLabel();
    jLabel11 = new javax.swing.JLabel();
    jLabel12 = new javax.swing.JLabel();
    jLabel13 = new javax.swing.JLabel();
    jLabel14 = new javax.swing.JLabel();
    jLabel15 = new javax.swing.JLabel();
    jLabel18 = new javax.swing.JLabel();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    addComponentListener(new java.awt.event.ComponentAdapter() {
        public void componentShown(java.awt.event.ComponentEvent evt) {
            formComponentShown(evt);
        }
    });
    addKeyListener(new java.awt.event.KeyAdapter() {
        public void keyPressed(java.awt.event.KeyEvent evt) {
            formKeyPressed(evt);
        }
    });

    jPanel1.setBackground(new java.awt.Color(0, 0, 0));
    jPanel1.addKeyListener(new java.awt.event.KeyAdapter() {
        public void keyPressed(java.awt.event.KeyEvent evt) {
            jPanel1KeyPressed(evt);
        }
    });
    jPanel1.setLayout(null);

    snake.setBackground(new java.awt.Color(255, 51, 0));
    snake.setOpaque(true);
    jPanel1.add(snake);
    snake.setBounds(230, 230, 20, 20);

    jLabel8.setBackground(new java.awt.Color(255, 255, 0));
    jLabel8.setOpaque(true);
    jPanel1.add(jLabel8);
    jLabel8.setBounds(100, 184, 10, 10);

    jLabel2.setBackground(new java.awt.Color(255, 255, 0));
    jLabel2.setOpaque(true);
    jPanel1.add(jLabel2);
    jLabel2.setBounds(225, 137, 10, 10);

    jLabel10.setBackground(new java.awt.Color(255, 255, 0));
    jLabel10.setOpaque(true);
    jPanel1.add(jLabel10);
    jLabel10.setBounds(419, 305, 10, 10);

    jLabel7.setBackground(new java.awt.Color(255, 255, 0));
    jLabel7.setOpaque(true);
    jPanel1.add(jLabel7);
    jLabel7.setBounds(301, 137, 10, 10);

    jLabel4.setBackground(new java.awt.Color(255, 255, 0));
    jLabel4.setOpaque(true);
    jPanel1.add(jLabel4);
    jLabel4.setBounds(158, 325, 10, 10);

    jLabel5.setBackground(new java.awt.Color(255, 255, 0));
    jLabel5.setForeground(new java.awt.Color(51, 0, 51));
    jLabel5.setOpaque(true);
    jPanel1.add(jLabel5);
    jLabel5.setBounds(412, 381, 10, 10);

    jLabel9.setBackground(new java.awt.Color(255, 255, 0));
    jLabel9.setOpaque(true);
    jPanel1.add(jLabel9);
    jLabel9.setBounds(503, 325, 10, 10);

    jLabel3.setBackground(new java.awt.Color(255, 255, 0));
    jLabel3.setOpaque(true);
    jPanel1.add(jLabel3);
    jLabel3.setBounds(410, 220, 10, 10);

    jLabel6.setBackground(new java.awt.Color(255, 255, 0));
    jLabel6.setOpaque(true);
    jPanel1.add(jLabel6);
    jLabel6.setBounds(432, 99, 10, 10);

    jLabel1.setBackground(new java.awt.Color(255, 255, 0));
    jLabel1.setOpaque(true);
    jPanel1.add(jLabel1);
    jLabel1.setBounds(510, 400, 10, 10);

    jLabel11.setBackground(new java.awt.Color(51, 51, 255));
    jLabel11.setOpaque(true);
    jPanel1.add(jLabel11);
    jLabel11.setBounds(0, 0, 20, 460);

    jLabel12.setBackground(new java.awt.Color(51, 51, 255));
    jLabel12.setOpaque(true);
    jPanel1.add(jLabel12);
    jLabel12.setBounds(0, 450, 560, 0);

    jLabel13.setBackground(new java.awt.Color(51, 51, 255));
    jLabel13.setOpaque(true);
    jPanel1.add(jLabel13);
    jLabel13.setBounds(0, 0, 560, 20);

    jLabel14.setBackground(new java.awt.Color(51, 51, 255));
    jLabel14.setOpaque(true);
    jPanel1.add(jLabel14);
    jLabel14.setBounds(540, 0, 20, 460);

    jLabel15.setBackground(new java.awt.Color(51, 51, 255));
    jLabel15.setOpaque(true);
    jPanel1.add(jLabel15);
    jLabel15.setBounds(0, 450, 560, 14);

    jLabel18.setIcon(new   javax.swing.ImageIcon(getClass().getResource("/culminating/snake body.jpg"))); // NOI18N
    jLabel18.setText("jLabel17");
    jPanel1.add(jLabel18);
    jLabel18.setBounds(150, 350, 20, 20);

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 556, Short.MAX_VALUE)
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 463, Short.MAX_VALUE)
    );

    pack();
}// </editor-fold>                        

private void formComponentShown(java.awt.event.ComponentEvent evt) {                                    
  this.requestFocusInWindow();
    food[0]=jLabel1;
    food[1]=jLabel2;
    food[2]=jLabel3;
    food[3]=jLabel4;
    food[4]=jLabel5;
    food[5]=jLabel6;
    food[6]=jLabel7;
    food[7]=jLabel8;
    food[8]=jLabel9;
    food[9]=jLabel10;

    Random h = new Random();
    Random v = new Random();

    border[0]=jLabel11;
    border[1]=jLabel13;
    border[2]=jLabel14;
    border[3]=jLabel15;

    System.out.println(jLabel1.getX());
    System.out.println(jLabel1.getY());
    this.setBounds(0, 0, 570, 500);

    food[0].setLocation(h.nextInt(490)+20, v.nextInt(412)+20);
    food[1].setLocation(h.nextInt(490)+20, v.nextInt(412)+20);
    food[2].setLocation(h.nextInt(490)+20, v.nextInt(412)+20);
    food[3].setLocation(h.nextInt(490)+20, v.nextInt(412)+20);
    food[4].setLocation(h.nextInt(490)+20, v.nextInt(412)+20);
    food[5].setLocation(h.nextInt(490)+20, v.nextInt(412)+20);
    food[6].setLocation(h.nextInt(490)+20, v.nextInt(412)+20);
    food[7].setLocation(h.nextInt(490)+20, v.nextInt(412)+20);
    food[8].setLocation(h.nextInt(490)+20, v.nextInt(412)+20);
    food[9].setLocation(h.nextInt(490)+20, v.nextInt(412)+20);

   s_timer = new Timer(50, new SnakeAction());
   s_timer.start();
   X=snake.getX();
   Y=snake.getY();

}                                   

private void jPanel1KeyPressed(java.awt.event.KeyEvent evt) {                                   

}                                  

private void formKeyPressed(java.awt.event.KeyEvent evt) {                                
    System.out.println(evt.getKeyCode());
      switch( evt.getKeyCode()){
    case 37:
    case 39:
    case 32:
    case 38:
    case 40:
    if (keys[evt.getKeyCode()]==false){
         keys[37]=false;
         keys[39]=false;
         keys[32]=false;
         keys[38]=false;
         keys[40]=false;
        keys[evt.getKeyCode()] = true;
    }
    break;
}           
}                               




 class SnakeAction implements ActionListener {
    public void actionPerformed(ActionEvent e) {
    String infoMessage, titleBar;
    if(keys[37]){       //left arrow
    up =false;
    down = false;
    checkCollision();
        if(!borderCollision(snake.getX()-10,snake.getY(),snake.getWidth(),snake.getHeight())){
    X-=10;
    snake.setLocation(X, Y);
    }

    }

    if(keys[39]){       //right arrow
    up = false;
    down = false;
    checkCollision();
    if(!borderCollision(snake.getX()+10,snake.getY(),snake.getWidth(),snake.getHeight())){
    X+=10;
    snake.setLocation(X, Y);
    }
    }

    if(keys[38]){       // up
    up=true;
    checkCollision();
    if(!borderCollision(snake.getX(),snake.getY()-7,snake.getWidth(),snake.getHeight())){
    Y-=10;
    snake.setLocation(X, Y);
    }
    }

    if(keys[40]){       //down
    down=true;
    checkCollision();
    if(!borderCollision(snake.getX(),snake.getY()+7,snake.getWidth(),snake.getHeight())){
    Y+=10;
    snake.setLocation(X, Y);
    }

  }

    }
  }
public void checkCollision(){
boolean collision=false;
Rectangle c1,c2=snake.getBounds();
for(int i=0;i<=9;i++){
c1=food[i].getBounds();
if(c1.intersects(c2))food[i].setVisible(false);
}

}
public boolean borderCollision(int x, int y, int w, int h){
boolean collide = false;
Rectangle r1,r2=snake.getBounds();
r2.x=x;
r2.y=y;
r2.width=w;
r2.height=h;
for(int c=0; c<=3;c++){
r1=border[c].getBounds();
if(r1.intersects(r2)){
collide=true;
}
}
return collide;
}
public static void main(String args[]) {

    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            new Visual().setVisible(true);
        }
    });
}

// Variables declaration - do not modify                     
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel10;
private javax.swing.JLabel jLabel11;
private javax.swing.JLabel jLabel12;
private javax.swing.JLabel jLabel13;
private javax.swing.JLabel jLabel14;
private javax.swing.JLabel jLabel15;
private javax.swing.JLabel jLabel18;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
private javax.swing.JLabel jLabel5;
private javax.swing.JLabel jLabel6;
private javax.swing.JLabel jLabel7;
private javax.swing.JLabel jLabel8;
private javax.swing.JLabel jLabel9;
private javax.swing.JPanel jPanel1;
private javax.swing.JLabel snake;
// End of variables declaration                   

}

代码解释:我为我的食物和边界/边界制作了两个数组。每种食物都是在不同的位置随机生成的。从 Jlabel 1 到 10 是我的食物,而 Jlabel 11、13、14 和 15 是我的边界。我的蛇运动有一个计时器。我已经使用了向上[key 38]、向下[key 40]、向左[key 37] 和向右[key 39] 箭头进行移动。食物在不同的位置随机生成。当蛇与食物碰撞时,我使用 setvisible 函数隐藏食物,当蛇与边界/边界碰撞时,它停止移动。

【问题讨论】:

  • Swing 组件对于您正在尝试做的事情来说是一个糟糕的选择,将来您真的应该看看自定义绘画

标签: java arrays swing arraylist jframe


【解决方案1】:

关于养蛇,我建议使用下面的代码而不是ArrayList,因为你不必使用它。

首先,setVisible 在这个游戏中不起作用。你把它藏起来,但它仍然在那里。这意味着您在通过隐藏的食物时会继续吃它。 但你可以使用 setBounds 将其移出。

public void checkCollision()
{
    boolean collision=false;
    Rectangle c1,c2=snake.getBounds();
    for(int i=0;i<=9;i++)
    {
        c1=food[i].getBounds();
        if(c1.intersects(c2))
        {   // it cause the problem
            food[i].setVisible(false);
            // add 
            food[i].setBounds(0,0,0,0);
        }
    }
}

同样的方式,养蛇

//A variable to save direction
String direction = "";
//A variable to save how long you will grow
int grow = 5;

Switch(direction)
{
     case N:

     snake.setBounds(X, Y,(int)snake.getSize().getWidth() ,(int)snake.getSize().getHeight()+grow);
     break;

     case E:

     snake.setBounds(X, Y,(int)snake.getSize().getWidth()+grow ,(int)snake.getSize().getHeight());
     break;

     case W:

     snake.setBounds(X, Y,(int)snake.getSize().getWidth()+grow ,(int)snake.getSize().getHeight());
     break;

     case S:

     snake.setBounds(X, Y,(int)snake.getSize().getWidth() ,(int)snake.getSize().getHeight()+grow);
     break;
}

具体来说,注意如果你想要更好的效果,在代码中控制生长部分和蛇的位置会有所帮助。

正如@Younes Mgharfaoui 所说,你不能让蛇回去。因此,在变量中确定方向。如果你向左走,你不能像蛇一样立即向右走。

【讨论】:

    【解决方案2】:

    嗯,你的代码很……有趣。

    至于如何使用ArrayList,你应该试试这样的:

    JLabel snakeBody = new JLabel();
    
    snakeBody.setBackground(new java.awt.Color(255, 255, 0));
    snakeBody.setOpaque(true);
    snakeBody.setBounds(510, 400, 10, 10);
    
    ArrayList<JLabel> snake = new ArrayList<>();
    snake.add(snakeBody);
    

    并且每次蛇吃你添加一个身体元素(在正确的位置):

    snake.add(snakeBody);
    

    为了显示蛇,foreach 循环应该可以解决问题

    for(JLabel body : snake){
        jPanel.add(body);
    }
    

    为了防止蛇返回,你应该删除监听器的 up 和 key down 键,并使用循环使其前进(从它自己的角度来看)。否则,只需根据蛇的前进方向禁用侦听器。您可以创建一个方法来确定蛇所在的方向。

    class SnakeAction implements ActionListener{
        public void actionPerformed(ActionEvent e) {
            if(key[37] && snakeDirection()!="right"){
                //some code
            }
        }
    }
    

    为防止食物与蛇重叠,您应该在每次生成随机数时检查这些数字是否与蛇(及其身体)的位置不匹配。如果它确实生成另一个数字。

    【讨论】:

    • 我得到了你答案的第一部分和第三部分,但我不明白你的意思是防止蛇返回部分。你介意给我那部分的示例代码吗?
    • 我在想你可以通过它的视角移动蛇(所以他只能向右或向左走)。另一种方法是根据您的蛇在哪一侧禁用侦听器。
    猜你喜欢
    • 1970-01-01
    • 2015-03-18
    • 1970-01-01
    • 2014-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多