我写了一个贪吃蛇程序,但是在画窗口里显示出来的移动不对(在没有吃到东西是自动增加),下面是我Snake类的代码,里面包含,draw()方法和内部类Node表示蛇的每一节(这样所不是很清楚,我把全部代码都发过来了):package snakeGame;import java.util.Random;public class AddEggs implements Runnable {
private Random r = new Random(); Yard y; public AddEggs(Yard y) {
this.y = y;
} public void run() {
while (true) {
int count = r.nextInt(3) + 1;
if (y.eggs.size() == 0) {
try {
for (int i = 0; i < count; i++) {
Egg egg = new Egg(r.nextInt(Yard.COLS), r.nextInt(Yard.ROWS-2)+2);
y.eggs.add(egg);
}
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}}package snakeGame;public enum Direction {
    U, D, L, R
}package snakeGame;import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;public class Egg {
private int cols,rows;
private int w = Yard.BLOCK_SIZE;
private int h = Yard.BLOCK_SIZE;
private boolean live = true;

public Egg(int cols,int rows){
this.cols = cols;
this.rows = rows;
}

public void draw(Graphics g) {
if(!live)return;
Color c = g.getColor();
g.setColor(Color.MAGENTA);
g.fillOval(Yard.BLOCK_SIZE*cols, Yard.BLOCK_SIZE*rows, w, h);
g.setColor(c);
}

public Rectangle getRect() {
return new Rectangle(Yard.BLOCK_SIZE*cols, Yard.BLOCK_SIZE*rows);
} public boolean isLive() {
return live;
} public void setLive(boolean live) {
this.live = live;
}
}
package snakeGame;import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.util.List;/**
 * 类,蛇
 * 
 * @author hejie
 */
public class Snake {
// 蛇头节点
Node head = null; // 蛇尾节点
Node tail = null; // 蛇的长度
private int size; private Node node = new Node(15, 20, Direction.R); private Yard y; public Snake(Yard y) {
head = node;
tail = node;
this.y = y;
this.size = 1;
} public void draw(Graphics g) {
if (size == 0)
return;
move(); for (Node n = head; n!= tail; n = n.nextNode) {
n.draw(g);
} } // 把一个节点加到蛇尾
public void addNodeTail() {
Node node = null;
switch (tail.dir) {
case U:
node = new Node(tail.cols, tail.rows + 1, tail.dir);
break;
case D:
node = new Node(tail.cols, tail.rows - 1, tail.dir);
break;
case L:
node = new Node(tail.cols + 1, tail.rows, tail.dir);
break;
case R:
node = new Node(tail.cols - 1, tail.rows, tail.dir);
break;
}

tail.nextNode = node;
node.frontNode = tail;
tail = node;
size++;
} // 把一个节点加到蛇头
public void addNodeHead() {
Node node = null;
switch (head.dir) {
case U:
node = new Node(head.cols, head.rows - 1, head.dir);
break;
case D:
node = new Node(head.cols, head.rows + 1, head.dir);
break;
case L:
node = new Node(head.cols - 1, head.rows, head.dir);
break;
case R:
node = new Node(head.cols + 1, head.rows, head.dir);
break;
}

node.nextNode = head;
head.frontNode = node;
head = node;
size++;
} private void deletTail() {
if (size == 0)
return;
tail = tail.frontNode;
tail.nextNode = null;
size--;
} public void keyPressed(KeyEvent ke) {
int keyCode = ke.getKeyCode();
if (keyCode == ke.VK_UP || keyCode == ke.VK_W) {
if (head.dir != Direction.D)
head.dir = Direction.U;
} else if (keyCode == ke.VK_DOWN || keyCode == ke.VK_S) {
if (head.dir != Direction.U)
head.dir = Direction.D;
} else if (keyCode == ke.VK_LEFT || keyCode == ke.VK_A) {
if (head.dir != Direction.R)
head.dir = Direction.L;
} else if (keyCode == ke.VK_RIGHT || keyCode == ke.VK_D) {
if (head.dir != Direction.L)
head.dir = Direction.R;
}
} private void move() {
addNodeHead();
deletTail();
checkDead();
} public void eatEgg(List<Egg> eggs) {
Egg egg;
for (int i = 0; i < eggs.size(); i++) {
egg = eggs.get(i);
if (head.getRect().intersects(egg.getRect())) {
this.addNodeHead();
egg.setLive(false);
}
}
}

private void checkDead() {
if(head.rows < 0 || head.cols < 2 || head.rows > Yard.ROWS || head.cols > Yard.COLS)  {
y.stop();
}

for(Node n = head.nextNode; n != null; n = n.nextNode) {
if(head.rows == n.rows && head.cols == n.cols) {
y.stop();
}
}
} /**
 * 构成蛇的节点
 * 
 * @author hejie
 */
private class Node {
// 节点的起始位置
int cols, rows; // 节点宽度、高度
int w = Yard.BLOCK_SIZE, h = Yard.BLOCK_SIZE; // 节点方向
Direction dir = Direction.U; // 下一个节点
private Node nextNode = null; private Node frontNode = null; Node(int cols, int rows, Direction dir) {
this.cols = cols;
this.rows = rows;
this.dir = dir;
} // 画出本节点
public void draw(Graphics g) {
Color c = g.getColor();
g.setColor(Color.BLACK);
g.fillRect(Yard.BLOCK_SIZE * cols, Yard.BLOCK_SIZE * rows, w, h);
g.setColor(c);
} public Rectangle getRect() {
return new Rectangle(Yard.BLOCK_SIZE * cols, Yard.BLOCK_SIZE * rows);
} }}package snakeGame;import java.awt.Frame;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;public class Yard extends Frame{

public static final int ROWS = 40;
public static final int COLS = 60;
public static final int BLOCK_SIZE = 10;

private boolean flag = true;
Snake snake = new Snake(this);
Image image = null;
public List<Egg> eggs = new ArrayList<Egg>();

public Yard(){
super("贪吃蛇");
this.setBackground(Color.LIGHT_GRAY);
this.setBounds(200, 100, COLS*BLOCK_SIZE, ROWS*BLOCK_SIZE);
this.addKeyListener(new KeyMonitor());
this.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});

this.setVisible(true);
new Thread(new RepaintSnake()).start();
new Thread(new AddEggs(this)).start();
//System.out.println(eggs.size());
}

public void update(Graphics g) {
if(image==null){
image = this.createImage(COLS*BLOCK_SIZE, ROWS*BLOCK_SIZE);
}

Graphics gImage = image.getGraphics();
Color c = gImage.getColor();
gImage.setColor(Color.LIGHT_GRAY);
gImage.fillRect(0, 0, COLS*BLOCK_SIZE, ROWS*BLOCK_SIZE);
gImage.setColor(c);
paint(gImage);
g.drawImage(image, 0, 0, null);

} public void paint(Graphics g) {
Color c = g.getColor();
g.setColor(Color.BLUE);
/*g.setColor(Color.LIGHT_GRAY);
g.fillRect(0, 0, ROWS*BLOCK_SIZE, COLS*BLOCK_SIZE);*/
//竖线
for(int i=1;i<=COLS;i++){
g.drawLine(BLOCK_SIZE*i, 0, BLOCK_SIZE*i, BLOCK_SIZE*ROWS);
}
//横线
for(int i=1;i<=ROWS;i++){
g.drawLine(0, BLOCK_SIZE*i, BLOCK_SIZE*COLS, BLOCK_SIZE*i);
}

g.setColor(c);
for(int i=0;i<eggs.size();i++){
eggs.get(i).draw(g);
}
snake.draw(g);

snake.eatEgg(eggs);

} public static void main(String[] args) {
new Yard(); }

private class RepaintSnake implements Runnable{ public void run() {
while(flag){
repaint();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}

}

private class KeyMonitor extends KeyAdapter {
public void keyPressed(KeyEvent ke){
snake.keyPressed(ke);
}
} public void stop() {
flag = false;
}
}

解决方案 »

  1.   

    我没调试哇  但是我感觉如果是一直加Node的话就应该是这个东西的判断有问题if (head.getRect().intersects(egg.getRect()){}你把这个判断trace出来试试看哇
      

  2.   

    再提一句哇我个人觉得这种格子游戏用碰撞检测不好哇  格子游戏不是每个格子都有坐标嘛用坐标检测岂不是更好哇  而且逻辑也清楚  而且一般来说  游戏的碰撞检测都是有自己公司开发的API的
      

  3.   

    不知道问题出在哪,不过有两个地方不妥:for (Node n = head; n!= tail; n = n.nextNode) { //这里的循环条件应该是n!=null吧,尾节点也应该画出来的
                n.draw(g);
    }private void deletTail() {
            if (size == 0)
                return;
            tail = tail.frontNode;
            tail.nextNode.frontNode=null; //把被删的尾部与前面节点断开。
            tail.nextNode = null;
            size--;
        }