贪吃蛇java版

主要的蛇的类

import java.awt.Color;
import java.awt.Graphics;
import java.awt.HeadlessException;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.util.Random;


public class Snake {
    
    private Node head = null;
    private Node tail = null;
    int size = 0;
    private boolean live = true;
    
    /**
     * 判断蛇是否活着
     * @return true则活着 false则死亡
     */
    public boolean isLive() {
        return live;
    }
    /**
     * 设置蛇的生死
     * @param live true则活着 false则死亡
     */
    void setLive(boolean live){
        this.live = live;
    }
    
    
    private Yard y;
    
    Node n = new Node(15, 15, Dir.L);
    /**
     * 构造方法 
     * @param y
     */
    public Snake(Yard y){
        this.y = y;
        head = n;
        tail = n;
        size++;
    }
    
    /**
     * 将一个结点添加到蛇的链表中
     */
    void addToTail(){
        Node node = null;
        switch (tail.dir) {
        case L:
            node = new Node(tail.row, tail.col+1, tail.dir);
            break;
        case U:
            node = new Node(tail.row+1, tail.col, tail.dir);
            break;
        case R:
            node = new Node(tail.row, tail.col-1, tail.dir);
            break;
        case D:
            node = new Node(tail.row-1, tail.col, tail.dir);
            break;
        }
        tail.next = node;
        node.prev = tail;
        tail = node;
        size++;
    }
    
    /**
     * 将一个结点从蛇的尾巴处删除
     */
    void deleteFromTail(){
        if(size == 0) return;
        tail = tail.prev;
        tail.next = null;
        size--;
    }
    
    /**
     * 设置使蛇的位置向前移动一步
     */
    void move(){
        addToHead();
        deleteFromTail();
        checkDead();
    }
    /**
     * 蛇的重画方法
     * @param g
     */
    void draw(Graphics g){
        if(!isLive() || size == 0) {
            return;
        }
        move();
        for(Node node = head ; node != null ; node = node.next){
            node.draw(g);
        }
        
    }
    /**
     * 将一个结点加到蛇链表的头部
     */
    void addToHead(){
        Node node = null;
        switch (head.dir) {
        case L:
            node = new Node(head.row, head.col-1, head.dir);
            break;
        case U:
            node = new Node(head.row-1, head.col, head.dir);
            break;
        case R:
            node = new Node(head.row, head.col+1, head.dir);
            break;
        case D:
            node = new Node(head.row+1, head.col, head.dir);
            break;
        }
        node.next = head;
        head.prev = node ;
        head = node ;
        size++;
    }
    
    /**
     * 保存蛇单个结点信息的类
     */
    private class Node{
        int w = Yard.BLOCK_SIZE;
        int h = Yard.BLOCK_SIZE;
        Dir dir = Dir.L;
        int row,col;
        
        Node next = null;
        Node prev = null;
        
        public Node(int row,int col,Dir dir){
            this.row = row;
            this.col = col;
            this.dir = dir;
        }
        //蛇单个节点的画法
        public void draw(Graphics g){
            Color c = g.getColor();
            g.setColor(Color.BLACK);
            g.fillRect(col*Yard.BLOCK_SIZE, row*Yard.BLOCK_SIZE, w, h);
            g.setColor(c);
        }

    }
    /**
     * 键盘监听
     * @param e
     */
    public void keyPressed(KeyEvent e) {
        int key = e.getKeyCode();
        switch(key){
        case KeyEvent.VK_LEFT:
            if(head.dir != Dir.R) head.dir = Dir.L;
            break;
        case KeyEvent.VK_UP:
            if(head.dir != Dir.D) head.dir = Dir.U;
            break;
        case KeyEvent.VK_RIGHT:
            if(head.dir != Dir.L) head.dir = Dir.R;
            break;
        case KeyEvent.VK_DOWN:
            if(head.dir != Dir.U) head.dir = Dir.D;
            break;
        case KeyEvent.VK_F2:
            if(!this.isLive()){
                y.snake = new Snake(y);
            }
            break;
        }
    }
    
    /**
     * 吃食物
     * @param f
     */
    public void eatFood(Food f){
        if(this.getRect().intersects(f.getRect())){
            f.setPos();
            y.setScore();
            this.addToTail();
        }
    }
    
    /**
     * 通过检测来设置蛇的生死
     */
    public void checkDead(){
        if(head.col < 0 || head.col > Yard.COLS || head.row < 3 || head.row > Yard.ROWS-1){
            setLive(false);
        }
        if(size >= 4){
            for(Node node = head.next;node != null ; node = node.next){
                if(head.row == node.row && head.col == node.col){
                    setLive(false);
                }
            }
        }
    }
    
    public Rectangle getRect(){
        return new Rectangle(head.col*Yard.BLOCK_SIZE,head.row*Yard.BLOCK_SIZE,Yard.BLOCK_SIZE,Yard.BLOCK_SIZE);
    }
}

吃的食物的类

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.Random;


public class Food {
    int row,col;
    int h = Yard.BLOCK_SIZE;
    int w = Yard.BLOCK_SIZE;
    private static Random rd = new Random();
    int step = 0;

    public Food(int row ,int col) {
        this.row = row;
        this.col = col;
    }
    
    public void draw(Graphics g){
        Color c = g.getColor();
        if(step == 0){
            g.setColor(Color.RED);
            step++;
        }else if(step == 1){
            g.setColor(Color.green);
            step++;
        }else {
            g.setColor(Color.WHITE);
            step = 0;
        }
        
        g.fillOval(col*Yard.BLOCK_SIZE, row*Yard.BLOCK_SIZE, w, h);
        g.setColor(c);
    }
    
    public Rectangle getRect(){
        return new Rectangle(col*Yard.BLOCK_SIZE, row*Yard.BLOCK_SIZE, w, h);
    }
    
    void setPos(){
        this.row = rd.nextInt(Yard.ROWS-3)+3; 
        this.col = rd.nextInt(Yard.COLS);
    }
}

方向的枚举

public enum Dir {
    L,U,R,D
}

主界面的类

import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
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;


class Yard extends Frame{
    

    PaintThread pt = null;
    /**
     * 速度 设置数字越大 越慢
     */
    public static final int SPEED = 4;
    /**
     * 行数
     */
    public static final int ROWS = 30;
    /**
     * 列数
     */
    public static final int COLS = 30;
    /**
     * 行列的宽度
     */
    public static final int BLOCK_SIZE = 15;
    
    /**
     * 在游戏窗口中加入一条蛇
     */
    public Snake snake = new Snake(this);
    
    /**
     * 在游戏窗口中加入一个食物
     */
    public Food food = new Food(10,10);
    
    private Font font = new Font("宋体", Font.BOLD,30 );
    
    private Image offScreenImage = null;
    
    //分数
    private int score = 0;
    
    public int getScore() {
        return score;
    }

    public void setScore() {
        this.score += 5;
    }
    
    /**
     * 窗口构建函数
     */
    public void launch(){

        pt = new PaintThread();
        this.setLocation(200, 200);
        this.setSize(COLS * BLOCK_SIZE, ROWS * BLOCK_SIZE);
        this.addWindowListener(new WindowAdapter() {

            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
            
        });
        
        this.setVisible(true);
        this.addKeyListener(new KeyMonitor());
        this.setResizable(false);
        //开始重画线程
        new Thread(pt).start();
        
    }
    
    /**
     * 主方法
     * @param args
     */
    public static void main(String[] args){
         new Yard().launch();
    }
    
    /**
     * 重写的paint方法 用来画出各个元素
     */
    @Override
    public void paint(Graphics g) {
        
        Color c = g.getColor();
        g.setColor(Color.GRAY);
        g.fillRect(0, 0, COLS * BLOCK_SIZE, ROWS * BLOCK_SIZE);
        g.setColor(Color.DARK_GRAY);
        
        //画出横线
        for(int i=1; i<ROWS; i++) {
            g.drawLine(0, BLOCK_SIZE * i, COLS * BLOCK_SIZE, BLOCK_SIZE * i);
        }
        for(int i=1; i<COLS; i++) {
            g.drawLine(BLOCK_SIZE * i, 0, BLOCK_SIZE * i, BLOCK_SIZE * ROWS);
        }
        
        snake.eatFood(food);
        g.setColor(Color.YELLOW);
        g.drawString("score :" + score, 10, 50);
        food.draw(g);
        
        if(snake.isLive()) {
            snake.draw(g);
        }else{
            g.setColor(Color.YELLOW);
            g.setFont(font);
            g.drawString("Game Over!", 125, 225);
        }
        g.setColor(c);

    }

    /**
     * 重写的update用来防止屏幕闪烁
     */
    @Override
    public void update(Graphics g) {

        if(offScreenImage == null){
            offScreenImage = this.createImage(COLS*BLOCK_SIZE, ROWS*BLOCK_SIZE);
        }
        Graphics graphics = offScreenImage.getGraphics();
        paint(graphics);

        g.drawImage(offScreenImage, 0, 0,  null);
    }
    
    /**
     * 重画线程
     */
    private class PaintThread implements Runnable{
        private boolean flag = true;
        
        private boolean pause = false;
        @Override
        public void run() {
            while(flag){
                if(!pause)
                    repaint();
                try {
                    Thread.sleep(25*SPEED);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        
        public void stopPaintThread(){
            flag = !flag;
        }
        
        public void pausePaintThread(){
            pause = !pause;
        }
    }
    
    /**
     * 键盘监听类
     */
    private class KeyMonitor extends KeyAdapter{

        @Override
        public void keyPressed(KeyEvent e) {
            int key = e.getKeyCode();
            if(key == KeyEvent.VK_SPACE){
                pt.pausePaintThread();
            }
            snake.keyPressed(e);
        }
        
    }
}
原文地址:https://www.cnblogs.com/mengxingxinqing/p/3564260.html