三个类:Food,食物即一个方格;GameWin:窗口;Snake:蛇效果图:
http://hi.csdn.net/space-2565159-do-album-picid-428275-goto-up.html
Food.java:import java.awt.*;
import java.util.*;public class Food {

private boolean live=true;
private int x;
private int y;
public static final int FOOD_WIDTH=10;
public static final int FOOD_HEIGTH=10;
    
public static Random r=new Random();

public Food(){
this.x=3+r.nextInt(29)*10;
this.y=27+r.nextInt(26)*10;
}

public int getX(){
return this.x;
}

public int getY(){
return this.y;
}

public boolean isLive() {
return live;
}

public void setLive(boolean live){
this.live=live;
}

public Rectangle getRec(){
return new Rectangle(this.x,this.y,Food.FOOD_WIDTH,Food.FOOD_HEIGTH);
}

public void draw(Graphics g){
Color c=g.getColor();
g.setColor(Color.red);
g.fill3DRect(this.x,this.y,Food.FOOD_WIDTH,Food.FOOD_WIDTH,true);
g.setColor(c);
}}
GameWin.java:import java.awt.*;
import java.awt.event.*;
import java.util.List;
import java.util.ArrayList;;public class GameWin extends Frame{

public static final int GAME_WIDTH=297;
public static final int GAME_HEIGTH=300;

private Food food;
private Snake snake;
private PaintThread paintTrd;
private boolean isPause=true;

public boolean isPause() {
return isPause;
} Image offScreenImage = null;

public GameWin(){
this.launchFrame();
//food=new Food(); //之前是在这里,但是在这里之前窗口已经画了一次了,所以会有NullPointerExcption

    this.paintTrd=new PaintThread();
paintTrd.start();
}

public void launchFrame(){
snake=new Snake(this);
food=new Food();  //放到这里,在窗口画出来之前new一个Food

        this.setTitle("EightSnake 1.1");
        this.setLayout(null);
        this.setSize(GameWin.GAME_WIDTH,GameWin.GAME_HEIGTH);
        this.setLocation(300,200);
    this.setResizable(false);
    this.setVisible(true);
    this.setBackground(Color.gray);
    this.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e) {
System.exit(0);
}
    
    });
    this.addKeyListener(new KeyAdapter(){ public void keyPressed(KeyEvent e) {
                if(e.getKeyCode()==KeyEvent.VK_SPACE){
                   if(!isPause){
                   paintTrd.suspend();
                      isPause=true;
                   }else{
                    paintTrd.resume();
                    isPause=false;
                   }
                }
snake.setDir(e);

    
    });
}

   public void paint(Graphics g){
   food.draw(g);
   Color c=g.getColor();
   g.setColor(Color.blue);
       g.drawString("snake length:"+snake.units.size(),90,100);
       g.drawString("by pcenshao for me",3,38);
       g.setColor(c);
       snake.draw(g);
       if(snake.eatFood(food)){
        food.setLive(false);
       }
   }
   
public void update(Graphics g) {
if (offScreenImage == null) {
offScreenImage = this.createImage(300, 300);
}
Graphics gOffScreen = offScreenImage.getGraphics();
Color c = gOffScreen.getColor();
gOffScreen.setColor(Color.gray);
gOffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGTH);
gOffScreen.setColor(c);
paint(gOffScreen);
g.drawImage(offScreenImage, 0, 0, null);
if(!this.food.isLive()){
   this.food=new Food();
 }
}
   
   private class PaintThread extends Thread{
   public void run(){
   while(true){
      repaint();
      try {
Thread.sleep(180);
      } catch (InterruptedException e) {
  e.printStackTrace();
  }
  
   }
   }
   }

public static void main(String args[]){
new GameWin();
}
}
Snake.java:import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.util.LinkedList;
import java.util.List;public class Snake {

public static final int SNAKE_UNIT_WIDTH=10;
public static final int SNAKE_UNIT_HEIGTH=10;
public static final int SNAKE_SPEED=10;

private boolean live=true;
private boolean start=false;

private GameWin win;

private Dir dir=Dir.STOP;
private Dir currentDir=Dir.D;

public List<SnakeUnit> units=new LinkedList<SnakeUnit>();
    
public Snake(GameWin gw){
this.win=gw;
        this.addUnit(133,97);
        this.addUnit(133,107);
        this.addUnit(133,117); }

public void addUnit(int x,int y){
this.units.add(new SnakeUnit(x,y));
}

public void delUnit(){
this.units.remove(0);
}

private Snake.SnakeUnit getFirstUnit(){
return this.units.get(this.units.size()-1);
}

public void draw(Graphics g){
Color c=g.getColor();
if(!isLive()){
g.setColor(Color.red);
g.drawString("Game Over",110,150);
return ;
}
this.move();  //改到这里就好了 同步了
g.setColor(Color.green);
g.fill3DRect(this.units.get(this.units.size()-1).x,this.units.get(this.units.size()-1).y,Snake.SNAKE_UNIT_WIDTH,Snake.SNAKE_UNIT_HEIGTH,true);
g.setColor(Color.yellow);
for(int i=this.units.size()-2;i>-1;i--){
g.fill3DRect(units.get(i).x,units.get(i).y,Snake.SNAKE_UNIT_WIDTH,Snake.SNAKE_UNIT_HEIGTH,true);
}
//this.move();  //第一次发上来的是用的这句移动,所以响应慢
g.setColor(c);
}

private static enum Dir{
U,D,L,R,STOP
}

private class SnakeUnit{ int x;
int y;

public SnakeUnit(int x, int y) {
this.x = x;
this.y = y;
}
} public void move(){
// if(this.dir==Dir.STOP) return;
if(this.win.isPause()) return ;
        if(this.currentDir==Dir.U){
         this.delUnit();
         SnakeUnit su=this.getFirstUnit();
         this.addUnit(su.x,su.y-Snake.SNAKE_UNIT_HEIGTH);
        }else if(this.currentDir==Dir.D){
         this.delUnit();
         SnakeUnit su=this.getFirstUnit();
         this.addUnit(su.x,su.y+Snake.SNAKE_UNIT_HEIGTH);
        }else if(this.currentDir==Dir.L){
         this.delUnit();
         SnakeUnit su=this.getFirstUnit();
         this.addUnit(su.x-Snake.SNAKE_UNIT_WIDTH,su.y);
        }else if(this.currentDir==Dir.R){
         this.delUnit();
         SnakeUnit su=this.getFirstUnit();
         this.addUnit(su.x+Snake.SNAKE_UNIT_WIDTH,su.y);
        }
}

public Rectangle getRec(){
int x;
int y;
SnakeUnit su=this.units.get(units.size()-1);
x=su.x;
y=su.y;
return new Rectangle(x,y,Snake.SNAKE_UNIT_HEIGTH,Snake.SNAKE_UNIT_WIDTH);
}

public boolean eatFood(Food f){
if(this.getRec().intersects(f.getRec())){
this.addUnit(f.getX(),f.getY());
return true;
}
return false;
} public void setDir(KeyEvent e) {
     if(this.start==false){
     this.start=true;
     }
        switch(e.getKeyCode()){
            case KeyEvent.VK_LEFT:
             if(this.currentDir!=Dir.R){
             this.currentDir=Dir.L;
             }
             break;
            case KeyEvent.VK_RIGHT:
             if(this.currentDir!=Dir.L){
             this.currentDir=Dir.R;
             }
             break;
            case KeyEvent.VK_UP:
             if(this.currentDir!=Dir.D){
             this.currentDir=Dir.U;
             }
             break;
            case KeyEvent.VK_DOWN:
             if(this.currentDir!=Dir.U){
             this.currentDir=Dir.D;
             }
             break;
         }
} private boolean isLive() {
int x=this.units.get(units.size()-1).x;
int y=this.units.get(units.size()-1).y;
if(x<0||x>290){
this.live=false;
return false;
}else if(y<27||y>290){
this.live=false;
return false;
} return true;
}
}