自己用java弄的一个贪吃蛇游戏

今天无聊了,自己弄了个贪吃蛇的游戏。很早以前就有这个愿望,可惜一直没有时间,今天终于弄好了,源代码如下:

实体类:

 Snake.java

package  com.nilaiya.snake.entities;

import  java.awt.Color;
import  java.awt.Graphics;
import  java.awt.Point;
import  java.util.HashSet;
import  java.util.LinkedList;
import  java.util.Set;

import  com.nilaiya.snake.listener.SnakeListener;
import  com.nilaiya.snake.util.Global;

/**
 * 
@author yellow
 *
 
*/

public   class  Snake  {

    
//判断蛇是否死掉
    boolean lift;

    
//蛇的最后一个节点
    private Point oldTail;

    
//表示方向的常量
    public static final int UP = -1;

    
public static final int DOWN = 1;

    
public static final int LEFT = 2;

    
public static final int RIGHT = -2;

    
//保存蛇的方向 
    private int oldDirection, newDirection;

    
//保存蛇的所有坐标,用集合表示
    private LinkedList<Point> body = new LinkedList<Point>();

    
//蛇的监听器,可以注册多个监听器
    private Set<SnakeListener> listeners = new HashSet<SnakeListener>();

    
/**
     * 构造器
     *
     
*/

    
public Snake() {
        init();
    }


    
/**
     * 蛇死掉的方法
     *
     
*/

    
public void die() {
        lift 
= false;
        System.out.println(
"蛇死掉了!");
    }


    
/**
     * 得到蛇头的坐标
     * 
@return Point
     * 
@return the body.getFirst()
     
*/

    
public Point getHead() {
        
return body.getFirst();
    }


    
/**
     * 初始化蛇
     *
     
*/

    
public void init() {
        
int x = Global.WIDTH / 2;
        
int y = Global.HEIGHT / 2;
        
for (int i = 0; i < 3; i++{
            body.addLast(
new Point(x--, y));//蛇头在右边(最中间)
        }

        
//蛇头默认移动方向向右
        oldDirection = newDirection = RIGHT;

        lift 
= true;//蛇一开始是活的
    }


    
/**
     * 添加监听器的方法
     * 
@param l
     
*/

    
public void addSnakeListener(SnakeListener l) {
        
if (l != null{
            
this.listeners.add(l);
        }

    }


    
/**
     * 蛇的移动方法
     *
     
*/

    
public void move() {
        System.out.println(
"蛇移动了!");
        
if (!(oldDirection + newDirection == 0)) {
            oldDirection 
= newDirection;
        }

        
//1.去掉尾部
        oldTail = body.removeLast();

        
//得到蛇头的坐标
        int x = body.getFirst().x;
        
int y = body.getFirst().y;

        
//根据方向计算蛇头的新坐标
        switch (oldDirection) {
        
case UP:
            y
--;
            
if (y < 0{
                y 
= Global.HEIGHT - 1;
            }

            
break;
        
case DOWN:
            y
++;
            
if (y >= Global.HEIGHT) {
                y 
= 0;
            }

            
break;
        
case LEFT:
            x
--;
            
if (x < 0{
                x 
= Global.WIDTH - 1;
            }

            
break;
        
case RIGHT:
            x
++;
            
if (x >= Global.WIDTH) {
                x 
= 0;
            }

            
break;
        }

        
//新的蛇头坐标 
        Point newHead = new Point(x, y);
        
//2.加头
        body.addFirst(newHead);
    }


    
/**
     * 蛇改变方向的方法
     * 
@param direction
     
*/

    
public void changeDirection(int direction) {
        System.out.println(
"蛇改变方向了!");
        newDirection 
= direction;
    }


    
/**
     * 蛇吃食物的方法
     *
     
*/

    
public void eatFood() {
        System.out.println(
"蛇吃食物了!");

        body.addLast(oldTail);
    }


    
/**
     * 判断蛇是否吃到了自己的身体
     * 
@return boolean
     
*/

    
public boolean isEatBody() {
        System.out.println(
"蛇吃到自己的身体了!");

        
for (int i = 1; i < body.size(); i++{
            
if (body.get(i).equals(this.getHead())) {
                
return true;
            }

        }

        
return false;
    }


    
/**
     * 显示蛇的方法
     * 
@param g
     
*/

    
public void drawMe(Graphics g) {
        System.out.println(
"显示蛇的方法");
        g.setColor(Color.BLUE);
        
//填充格子
        for (Point p : body) {
            g.fill3DRect(p.x 
* Global.CELL_SIZE, p.y * Global.CELL_SIZE,
                    Global.CELL_SIZE, Global.CELL_SIZE, 
true);
        }


    }


    
/**
     * 内部类
     * 蛇一开始要不停的移动
     * 
@author yellow
     *
     
*/

    
private class SnakeMove implements Runnable {

        
public void run() {
            
while (lift) {
                move();
                
//循环所有的遍历
                for (SnakeListener l : listeners) {
                    l.snakeMoved(Snake.
this);
                }

                
try {
                    Thread.sleep(
300);
                }
 catch (InterruptedException e) {
                    e.printStackTrace();
                    System.out.println(
"线程延迟出错!");
                }

            }

        }

    }


    
/**
     * 启动线程的方法
     *
     
*/

    
public void start() {
        
new Thread(new SnakeMove()).start();
    }

}

Food.java

package  com.nilaiya.snake.entities;

import  java.awt.Graphics;
import  java.awt.Point;

import  com.nilaiya.snake.util.Global;

/**
 * 
@author yellow
 *
 
*/

public   class  Food  extends  Point  {

    
private static final long serialVersionUID = 1L;

    
/**
     * 放食物的坐标方法
     * 
@param p
     
*/

    
public void newFood(Point p) {
        
this.setLocation(p);
    }


    
/**
     * 判断蛇是否吃到了食物
     * 
@param snake
     * 
@return boolean
     * 
@return this.equals(snake.getHead())
     
*/

    
public boolean isSnakeEatFood(Snake snake) {
        System.out.println(
"蛇吃到了食物!");
        
return this.equals(snake.getHead());
    }


    
/**
     * 显示食物的方法
     * 
@param g
     
*/

    
public void drawMe(Graphics g) {
        System.out.println(
"显示食物!");
        g.fill3DRect(x 
* Global.CELL_SIZE, y * Global.CELL_SIZE,
                Global.CELL_SIZE, Global.CELL_SIZE, 
true);
    }

}

Ground.java

package  com.nilaiya.snake.entities;

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

import  com.nilaiya.snake.util.Global;

/**
 * 
@author yellow
 *
 
*/

public   class  Ground  {

    
//用数组来保存石头
    private int[][] rockes = new int[Global.WIDTH][Global.HEIGHT];

    
/**
     * 构造器
     *
     
*/

    
public Ground() {
        
for (int x = 0; x < Global.WIDTH; x++{
            rockes[x][
0= 1;
            rockes[x][Global.HEIGHT 
- 1= 1;
        }

    }


    
/**
     * 食物随机产生
     * 
@return Point
     * 
@return the new Point(x, y)
     
*/

    
public Point getPoint() {
        Random random 
= new Random();
        
int x = 0;
        
int y = 0;
        
do {
            x 
= random.nextInt(Global.WIDTH);
            y 
= random.nextInt(Global.HEIGHT);
        }
 while (rockes[x][y] == 1);
        
return new Point(x, y);
    }


    
/**
     * 判断蛇吃否吃到了石头
     * 
@param snake
     * 
@return boolean
     
*/

    
public boolean isSnakeEatRock(Snake snake) {
        System.out.println(
"蛇吃到了石头!");

        
for (int x = 0; x < Global.WIDTH; x++{
            
for (int y = 0; y < Global.HEIGHT; y++{
                
if (rockes[x][y] == 1
                        
&& (x == snake.getHead().x && y == snake.getHead().y)) {
                    
return true;
                }

            }

        }

        
return false;
    }


    
/**
     * 显示石头的方法
     * 
@param g
     
*/

    
public void drawMe(Graphics g) {
        System.out.println(
"显示石头的方法!");

        g.setColor(Color.DARK_GRAY);

        
//画石头
        for (int x = 0; x < Global.WIDTH; x++{
            
for (int y = 0; y < Global.HEIGHT; y++{
                
if (rockes[x][y] == 1{
                    g.fill3DRect(x 
* Global.CELL_SIZE, y * Global.CELL_SIZE,
                            Global.CELL_SIZE, Global.CELL_SIZE, 
true);
                }

            }

        }

    }

}

 

视图类

GamePanel.java

package  com.nilaiya.snake.view;

import  java.awt.Color;
import  java.awt.Graphics;

import  javax.swing.JPanel;

import  com.nilaiya.snake.entities.Food;
import  com.nilaiya.snake.entities.Ground;
import  com.nilaiya.snake.entities.Snake;
import  com.nilaiya.snake.util.Global;

/**
 * 
@author yellow
 * 
 
*/

public   class  GamePanel  extends  JPanel  {

    
private static final long serialVersionUID = 1L;

    
// 定义对象
    private Snake snake;

    
private Food food;

    
private Ground ground;

    
/**
     * GamePanel的显示方法
     * 
     * 
@param snake
     * 
@param food
     * 
@param ground
     
*/

    
public void display(Snake snake, Food food, Ground ground) {
        System.out.println(
"GamePanel 显示了");
        
this.snake = snake;
        
this.food = food;
        
this.ground = ground;

        
this.repaint();// 这个方法调用paintComponent()方法重新显示
    }


    
/**
     * 重新显示的方法
     
*/

    @Override
    
protected void paintComponent(Graphics g) {
        
// 重新显示
        g.setColor(new Color(0xcfcfcf));
        g.fillRect(
00, Global.WIDTH * Global.CELL_SIZE, Global.HEIGHT
                
* Global.CELL_SIZE);
        
if (snake != null && ground != null && food != null{
            
this.snake.drawMe(g);
            
this.food.drawMe(g);
            
this.ground.drawMe(g);
        }

    }

}

Globale.java

package  com.nilaiya.snake.util;

/**
 * 
@author yellow
 * 
 
*/

public   class  Global  {

    
// 格子的参数 高 、 宽
    
// 一个格子的宽度
    public static final int CELL_SIZE = 20;

    
// 整个显示区域的大小
    public static final int WIDTH = 20;

    
public static final int HEIGHT = 20;

}

控制、事件监听类

Controller.java

package  com.nilaiya.snake.controller;

import  java.awt.event.KeyAdapter;
import  java.awt.event.KeyEvent;
import  com.nilaiya.snake.entities.Food;
import  com.nilaiya.snake.entities.Ground;
import  com.nilaiya.snake.entities.Snake;
import  com.nilaiya.snake.listener.SnakeListener;
import  com.nilaiya.snake.view.GamePanel;

/**
 * 
@author yellow
 *
 
*/

public   class  Controller  extends  KeyAdapter  implements  SnakeListener  {
    
    
// 定义对象
    private Snake snake;

    
private Food food;

    
private Ground ground;

    
private GamePanel gamePanel;

    
/**
     * 构造器
     * 
     * 
@param snake
     * 
@param food
     * 
@param ground
     * 
@param gamePanel
     
*/

    
public Controller(Snake snake, Food food, Ground ground, GamePanel gamePanel) {
        
super();
        
this.snake = snake;
        
this.food = food;
        
this.ground = ground;
        
this.gamePanel = gamePanel;
    }


    
/**
     * 开始新游戏的方法
     * 
     
*/

    
public void newGame() {
        snake.start();
        food.newFood(ground.getPoint());
    }


    
/**
     * 显示蛇、石头、食物
     
*/

    
public void snakeMoved(Snake snake) {
        
// 如果吃到了食物
        if (food.isSnakeEatFood(snake)) {
            snake.eatFood();
            food.newFood(ground.getPoint());
        }

        
// 如果吃到了石头
        if (ground.isSnakeEatRock(snake)) {
            snake.die();
// 游戏就结束
        }

        
// 如果吃到自己的身体
        if (snake.isEatBody()) {
            snake.die();
// 游戏就结束
        }


        gamePanel.display(snake, food, ground);
    }


    
/**
     * 覆盖KeyAdapter的keyPressed()方法
     
*/

    @Override
    
public void keyPressed(KeyEvent e) {
        
// 改变蛇的方向
        switch (e.getKeyCode()) {
        
case KeyEvent.VK_UP:
            snake.changeDirection(Snake.UP);
            
break;
        
case KeyEvent.VK_DOWN:
            snake.changeDirection(Snake.DOWN);
            
break;
        
case KeyEvent.VK_LEFT:
            snake.changeDirection(Snake.LEFT);
            
break;
        
case KeyEvent.VK_RIGHT:
            snake.changeDirection(Snake.RIGHT);
            
break;
        }

    }

}

SnakeListener .java

package  com.nilaiya.snake.listener;

import  com.nilaiya.snake.entities.Snake;

/**
 * 
@author yellow
 * 
 
*/

public   interface  SnakeListener  {

    
/**
     * 蛇移动的方法,蛇每移动一次就触发这个事件
     * 
     * 
@param snake
     
*/

    
void snakeMoved(Snake snake);
}

游戏测试类,包含了main()函数

GameTest.java

package  com.nilaiya.snake.gametest;

import  java.awt.BorderLayout;

import  javax.swing.JFrame;

import  com.nilaiya.snake.controller.Controller;
import  com.nilaiya.snake.entities.Food;
import  com.nilaiya.snake.entities.Ground;
import  com.nilaiya.snake.entities.Snake;
import  com.nilaiya.snake.util.Global;
import  com.nilaiya.snake.view.GamePanel;

/**
 * 
@author yellow
 * 
 
*/

public   class  GameTest  {

    
/**
     * main()方法,程序入口
     * 
     * 
@param args
     
*/

    
public static void main(String[] args) {

        
// 实例化类
        Snake snake = new Snake();
        Food food 
= new Food();
        Ground ground 
= new Ground();
        GamePanel gamePanel 
= new GamePanel();

        Controller controller 
= new Controller(snake, food, ground, gamePanel);

        
// 游戏窗口
        JFrame frame = new JFrame("贪吃蛇-37#404工作小组出品-yellow");
        
//禁止窗口最大化
        frame.setResizable(false);
        
// 关闭窗口就退出程序
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
// 设置大小
        gamePanel.setSize(Global.WIDTH * Global.CELL_SIZE, Global.HEIGHT
                
* Global.CELL_SIZE);

        frame.setSize(Global.WIDTH 
* Global.CELL_SIZE + 6, Global.HEIGHT
                
* Global.CELL_SIZE + 28);
        
// 添加gamePanel
        frame.add(gamePanel, BorderLayout.CENTER);

        
// 注册监听器
        gamePanel.addKeyListener(controller);
        snake.addSnakeListener(controller);
        
// 给frame加上监听
        frame.addKeyListener(controller);

        
// 显示游戏窗口
        frame.setVisible(true);

        
// 开始游戏
        controller.newGame();
    }


}

本游戏的开发环境为MyEclipse 5.1 + jdk1.5。本游戏是按照MVC模块开发的。其中:

Snake.java,Food.java,Ground.java 为MVC的M部分既是模型部分。

GamePanel.java,Grobal.java为MVC的M部分既是视图部分,主要用来显示游戏的窗体。

Controller.java,SnakeListener .java为MVC的C部分,既是控制器,还有处理相关的逻辑代码。

GameTest.java 为游戏的测试类,此类为测试游戏。

该游戏还有许多的bug和不足之处,还望大家指出,谢谢。

你可能感兴趣的:(自己用java弄的一个贪吃蛇游戏)