我是一名高中生,目前正在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是我的边界/边界。我有一个计时器用于我的蛇运动。我用完[键38],向下[键40],向左[键37]和向右[键39]箭头移动。食物在不同的位置随机产生。当蛇与食物碰撞时,我使用了可见的功能来隐藏食物,当蛇与边界/边界碰撞时,它会停止移动。
答案 0 :(得分: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);
}
为了防止蛇回来你应该只删除密钥并按下监听器并使用循环使其前进(从它自己的角度来看)。否则,只需根据蛇的行进方向禁用侦听器。您可以创建一种方法来确定蛇的方向。
class SnakeAction implements ActionListener{
public void actionPerformed(ActionEvent e) {
if(key[37] && snakeDirection()!="right"){
//some code
}
}
}
为了防止食物与蛇重叠,如果这些数字与蛇(及其身体)的位置不匹配,则应在每次生成随机数时进行检查。如果确实产生了另一个数字。
答案 1 :(得分: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所说,你不能让蛇回去。所以在变量中做出方向。如果你走到左边,就不能马上直接走蛇。