Java 贪吃蛇 吃了不增长

imonkeyi 2019-01-11 08:41:30
我在写一个贪吃蛇小游戏,还没完成,遇到一个问题,我的蛇吃了食物增加的结点会和蛇最后一个结点重合,导致增加的结点绘制在一个格子里,蛇就没变长,下面是蛇移动位置的代码和蛇吃东西的代码

public void snakeMove()  //刷新蛇位置
{
for(int i=snake.size()-1;i>0;i--)
{
snake.get(i).setX(snake.get(i-1).getX());
snake.get(i).setY(snake.get(i-1).getY());
}
/*int tempx=snake.get(0).getX();
int tempy=snake.get(0).getY();
snake.get(0).setX(tempx+x);
snake.get(0).setY(tempy+y);*/

if(direction.equals("up"))
{
snake.get(0).setX(snake.get(0).getX()+0);
snake.get(0).setY(snake.get(0).getY()-size);
}
else if(direction.equals("down"))
{
snake.get(0).setX(snake.get(0).getX()+0);
snake.get(0).setY(snake.get(0).getY()+size);
}
else if(direction.equals("left"))
{
snake.get(0).setX(snake.get(0).getX()-size);
snake.get(0).setY(snake.get(0).getY()+0);
}
else if(direction.equals("right"))
{
snake.get(0).setX(snake.get(0).getX()+size);
snake.get(0).setY(snake.get(0).getY()+0);
}
}
public void foodChange() //刷新食物位置
{
food.setX(rand.nextInt(35)*size);
food.setY(rand.nextInt(22)*size+60);
}
/*
* 蛇吃了食物后会发生两件,1.刷新食物 2.蛇变长
*/
public void eatFood()
{
//蛇是否吃了食物
if(snake.get(0).getX()==food.getX()&&snake.get(0).getY()==food.getY())
{
//刷新食物
foodChange();
//蛇变长
Node1 newnode=snake.get(snake.size()-1);
snake.add(newnode);
}
}


下面是所有代码
package Mysnake2;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import java.awt.Toolkit;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Insets;
import java.util.Random;

public class Win2 extends JFrame{ //游戏窗口

//窗口大小
public static int width=800,height=500;
private Toolkit toolkit;
private Dimension screensize;
private String title;
private Image image;
private Gwin2 gwin2;
private Insets insets;
private Dimension jframesize;

public Win2()
{
this.setSize(width+6, height+35);
//窗口居中
toolkit=Toolkit.getDefaultToolkit();
screensize=toolkit.getScreenSize();
this.setLocation((screensize.width-width)/2, (screensize.height-height)/2);
//设置图标和标题
image=new ImageIcon(Win2.class.getResource("image/snake.jpg")).getImage();
this.setIconImage(image);
title="贪吃蛇";
this.setTitle(title);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//添加panel组件
gwin2=new Gwin2();
this.add(gwin2);
//设置布局管理器为空,否则在游戏区域中设置的坐标无效
this.setLayout(null);
//获取JFrame的内容面板和边框大小,要设置在窗口可见之前
this.setVisible(true);
insets=this.getInsets();
jframesize=this.getContentPane().getSize();
System.out.println("窗口边框上:"+insets.top);
System.out.println("窗口边框下:"+insets.bottom);
System.out.println("窗口边框左:"+insets.left);
System.out.println("窗口边框右:"+insets.right);
System.out.println("内容面板宽度:"+jframesize.width);
System.out.println("窗口边框高度:"+jframesize.height);
Random rand=new Random();
System.out.println(rand.nextInt(20));
System.out.println(Math.random());
}
public static void main(String[] arg)
{
new Win2();
}
}

package Mysnake2;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import javax.swing.JPanel;
import javax.swing.JButton;
/*
* 比较字符串是否相等
*
*
*
*/
public class Gwin2 extends JPanel implements ActionListener,KeyListener{//游戏区域

//定义区域大小和坐标,格子大小
private int width,height;
public static final int size=20;
private JButton but_start;
private JButton but_stop;
private Thread thread;
private Mythread mythread;
private Snake1 snake1;
ArrayList<Node1> snake;
private boolean flag;
private Node1 food;

public Gwin2()
{
//格子大小为20像素
snake1=new Snake1();
snake=snake1.getSnake();
food=snake1.getFood();
flag=false;
/*
* 700/20=35
* 按钮要占空间
* 第一条线下移60像素,500-60=440,440/20=22
* 横排有35个格子要画竖线36条线,竖线第1条和第36条不要画
* 纵排有22个格子要画横线23条线,横线第23条不要画
* 则要画竖线34条,横线22条
* 0-700 60-500
* 设置区域大小和位置
*/
width=700;
height=500;
this.setSize(width, height);
this.setLocation((Win2.width-width)/2, (Win2.height-height)/2);
this.setBackground(Color.black);
//添加按钮组件
but_start=new JButton("开始");
but_stop=new JButton("暂停");
but_start.addActionListener(this);
but_stop.addActionListener(this);
this.add(but_start);
this.add(but_stop);
this.addKeyListener(this);
//启动线程
mythread=new Mythread();
thread=new Thread(mythread);
thread.start();
}
public void paint(Graphics g) //绘制
{
super.paint(g);

g.setColor(Color.red);
for(int i=1;i<35;i++) //竖线
{
g.drawLine(size*i, 60, size*i, 500);
}
for(int i=0;i<22;i++) //横线
{
g.drawLine(0, 60+size*i, 700, 60+size*i);
}

g.setColor(Color.white);
g.fillRect(food.getX(), food.getY(), size, size); //画食物
for(int i=0;i<snake.size();i++)
{
g.fillRect(snake.get(i).getX(), snake.get(i).getY(), size, size); //画蛇
}
}
public void actionPerformed(ActionEvent e)
{
Object source=e.getSource();
if(source==but_start)
{
flag=true;
}
else if(source==but_stop)
{
flag=false;
}
this.requestFocus(); //为jpanel获取事件,防止键盘监听无效
}
public void keyPressed(KeyEvent e)
{
switch(e.getKeyCode())
{
case KeyEvent.VK_UP:snake1.setString("up");break;
case KeyEvent.VK_DOWN:snake1.setString("down");break;
case KeyEvent.VK_LEFT:snake1.setString("left");break;
case KeyEvent.VK_RIGHT:snake1.setString("right");break;
}
//System.out.println(direction);
System.out.println(snake1.getString());
System.out.println(snake.size());
for(Node1 i:snake)
{
System.out.println(i.getX()+" "+i.getY());
}
}
public void keyTyped(KeyEvent e) {}
public void keyReleased(KeyEvent e) {}
//内部类为线程类
class Mythread implements Runnable
{
public void run()
{
while(true)
{
if(flag)
{
snake1.eatFood();
snake1.snakeMove();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
repaint();
}
}
}
}

package Mysnake2;

import java.util.ArrayList;
import java.util.Random;

public class Snake1 {

private ArrayList<Node1> snake;
private int snakex=10*size,snakey=10*size+60; //初始蛇头位置
private int foodx=size*3,foody=60+size*5; //初始食物位置
public static final int length=3; //初始贪吃始长度
private Node1 food; //食物结点
private static final int size=Gwin2.size;
private Random rand;
private String direction="right"; //方向
public Snake1()
{
snake=new ArrayList<Node1>(length);
food=new Node1(foodx,foody);
rand=new Random();
initial();
}

public ArrayList<Node1> getSnake()
{
return snake;
}
public Node1 getFood()
{
return food;
}
public String getString()
{
return direction;
}
public void setString(String str)
{
this.direction=str;
}

public void initial() //初始化蛇位置和食物位置
{
snake.add(new Node1(snakex,snakey)); //添加蛇头
for(int i=1;i<length;i++)
{
int tempx=snakex-size*i;
int tempy=snakey;
snake.add(new Node1(tempx,tempy));
}
}

public void snakeMove() //刷新蛇位置
{
for(int i=snake.size()-1;i>0;i--)
{
snake.get(i).setX(snake.get(i-1).getX());
snake.get(i).setY(snake.get(i-1).getY());
}
/*int tempx=snake.get(0).getX();
int tempy=snake.get(0).getY();
snake.get(0).setX(tempx+x);
snake.get(0).setY(tempy+y);*/

if(direction.equals("up"))
{
snake.get(0).setX(snake.get(0).getX()+0);
snake.get(0).setY(snake.get(0).getY()-size);
}
else if(direction.equals("down"))
{
snake.get(0).setX(snake.get(0).getX()+0);
snake.get(0).setY(snake.get(0).getY()+size);
}
else if(direction.equals("left"))
{
snake.get(0).setX(snake.get(0).getX()-size);
snake.get(0).setY(snake.get(0).getY()+0);
}
else if(direction.equals("right"))
{
snake.get(0).setX(snake.get(0).getX()+size);
snake.get(0).setY(snake.get(0).getY()+0);
}
}
public void foodChange() //刷新食物位置
{
food.setX(rand.nextInt(35)*size);
food.setY(rand.nextInt(22)*size+60);
}
/*
* 蛇吃了食物后会发生两件,1.刷新食物 2.蛇变长
*/
public void eatFood()
{
//蛇是否吃了食物
if(snake.get(0).getX()==food.getX()&&snake.get(0).getY()==food.getY())
{
//刷新食物
foodChange();
//蛇变长
Node1 newnode=snake.get(snake.size()-1);
snake.add(newnode);
}
}

}

package Mysnake2;

public class Node1 {

private int x,y;
public Node1() {}
public Node1(int x,int y)
{
this.x=x;
this.y=y;
}
public int getX()
{
return x;
}
public int getY()
{
return y;
}
public void setX(int x)
{
this.x=x;
}
public void setY(int y)
{
this.y=y;
}
}
这是我运行的测试输出,里面是蛇的长度和各个结点坐标
...全文
340 3 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
浆果 2019-01-12
  • 打赏
  • 举报
回复
楼主好厉害!
imonkeyi 2019-01-12
  • 打赏
  • 举报
回复
哪位帅哥看了麻烦回复一下,我好结个贴
imonkeyi 2019-01-12
  • 打赏
  • 举报
回复
问题我已经找到了,我添加的结点不应该用蛇尾结点赋值,因为结点是一个类,栈中存的是堆中实例的地址,如果直接用蛇尾结点赋值会使得它们两个指向同一片内存空间,此时不管是谁改变了x,y的指都会同时改变另外一个的值,应该重新new一个结点,而仅仅把蛇尾结点的x,y的值传进去

62,635

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧