java贪吃蛇小游戏完整版。

package com.java20180917.snake;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.Properties;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

/**
 * 1.初始化界面 2.初始化面板 3.面板与界面合并
 * 
 * @author Xiaolei
 *
 */
public class Main extends JFrame implements KeyListener {
    private static final long serialVersionUID = -1803858577233572276L;
    //定义容器
    private JPanel jp = null;
    //定义窗口
    private int fw;
    private int fh;
    //定义蛇的大小和位置和长度
    private int count;
    private int b_size;
    private int se_size;
    private int se_x;
    private int se_y;
    private LinkedList snake = new LinkedList();
    private String direction = Constant.UP;
    
    private String tip = "";
    private String status = "";
    //速度
    private long speed;
    private Random rand = new Random();
    private LinkedList b = new LinkedList();
    private Color[] colors = { Color.white, Color.orange, Color.BLUE, Color.CYAN, Color.gray, Color.yellow };
    //成绩和关卡定义
    private int Score;
    private int cheak = 1;
    //定义记录暂停和重启的时间
    private long startTime;
    private long endTime;
    
    //暂停游戏间隔时间定义
    private long pausetime;
    private long resettime;
    private long sumtime;

    // 总初始化方法
    private void init() {
        initCoket();
        initSnake();
        initBean();
        initPanel();
        initFrame();
        initThread();
    }

    private void initCoket() {
        Properties pps = new Properties();
        try {
            pps.load(new FileInputStream("E:\\workspace-sts\\java20180917\\src\\config.properties"));
            Enumeration enum1 = pps.propertyNames();// 得到配置文件的名字
            while (enum1.hasMoreElements()) {
                // 把指定的键的值赋给当前类定义的变量
                fw = Integer.parseInt(pps.getProperty("fw"));
                fh = Integer.parseInt(pps.getProperty("fh"));
                count = Integer.parseInt(pps.getProperty("count"));
                b_size = Integer.parseInt(pps.getProperty("b_size"));
                se_size = Integer.parseInt(pps.getProperty("se_size"));
                se_x = Integer.parseInt(pps.getProperty("se_x"));
                se_y = Integer.parseInt(pps.getProperty("se_y"));
                speed = Long.parseLong(pps.getProperty("speed"));
                // 第二种方式
                String strKey = (String) enum1.nextElement();
                String strValue = pps.getProperty(strKey);
                if (strKey.equals("fw")) {
                    fw = Integer.parseInt(strValue);
                }
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    private void initBean() {
        // 返回一个伪随机数,它是取自此随机数生成器序列的、在 0(包括)和指定值(不包括)之间均匀分布的 int 值。
        int b_x = 20 * Math.round((new Random().nextInt(30)));
        int b_y = 20 * Math.round((new Random().nextInt(30)));
        // 如果蛇的列表中不包含豆子的位置 如果此列表包含指定元素,则返回 true。
        if (!(snake.contains(new SE(b_size, b_x, b_y)))) {
            b.add(new Bean(b_x, b_y, b_size));
        }

    }

    // 如果方面符合条件,就触发该方法,弹出窗口
    private void popup() {
        tip = Constant.TIP;
        status = Constant.STOP;
        // 让方块重新向上跑
        direction = Constant.UP;
        //重画
        jp.repaint();
        int op_result = JOptionPane.showConfirmDialog(jp, "GAME OVER!", "", 
                JOptionPane.OK_CANCEL_OPTION,
                JOptionPane.ERROR_MESSAGE);
        if (op_result == 0) {
            // 重新开始游戏
            // 让蛇的运动条件重新开始
            status = "";
            // 把蛇的链表集合清空掉
            snake.clear();
            // 把Game Over字体清空。
            tip = "";
            // 重新调用方块,初始化蛇
            initSnake();
            //成绩和速度重新赋值
            speed = 250;
            Score = 0;
        }
        if (op_result == 2) {
            System.exit(0);
        }
    }

    private void initThread() {
        // 添加线程,让方块跟着键盘的指定方面运动
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    System.out.print("");
                    if ("".equalsIgnoreCase(status)) {
                        //判断吃豆子
                         if (snake.getFirst().getSe_x() == b.getFirst().getB_x()
                             && snake.getFirst().getSe_y() == b.getFirst().getB_y()) {
                             b.clear();
                            //重新初始化豆子的数据
                            initBean();
                        //长长
                        snake.addLast(new SE(se_size, snake.getLast().getSe_x(), snake.getLast().getSe_y()));
                            Score++;
//                            加速
                            if(Score%2==0 && cheak<=5) {
                                speed-=30;
                                jp.repaint();
                                int op_result = JOptionPane.showConfirmDialog(jp, "你已通过第"+cheak+"关,是否继续游戏?", "", 
                                        JOptionPane.OK_CANCEL_OPTION,
                                        JOptionPane.ERROR_MESSAGE);
                                cheak++;                                
                                if (op_result == 2) {
                                    System.exit(0);
                                }
                            }
                            
                        }
                        
                        // 判断是否咬到自己(即头部坐标与身体上的任何一个元素的坐标重合)
                        for (int i = 1; i < snake.size(); i++) {
                            if (snake.getFirst().getSe_x() == snake.get(i).getSe_x()
                                    && snake.getFirst().getSe_y() == snake.get(i).getSe_y()) {
                                popup();
                            }
                        }
                        // 操作snake容器中的元素
                        // 移除最后一个
                        snake.removeLast();
                        // 添加一个到头部
                        // 让方块往上走
                        if (direction.equalsIgnoreCase(Constant.UP)) {
                            // 如果新的头部y的坐标出界,提示game over
                            if (snake.getFirst().getSe_y() - se_size < 0) {
                                popup();
                            }
                            //在蛇方块的头部加一个蛇方块
                            snake.addFirst(
                                    new SE(se_size, snake.getFirst().getSe_x(), snake.getFirst().getSe_y() - se_size));
                        }
                        // 让方块往下走
                        if (direction.equalsIgnoreCase(Constant.Down)) {
                            //蛇方块的坐标从左上角开始计算
                            //如果蛇的头部的位置+自身的大小大于窗口总宽度就结束游戏
                            if (snake.getFirst().getSe_y() + se_size > fh) {
                                popup();
                            }
                            snake.addFirst(
                                    new SE(se_size, snake.getFirst().getSe_x(), snake.getFirst().getSe_y() + se_size));
                        }
                        // 让方块往左走
                        if (direction.equalsIgnoreCase(Constant.LEFT)) {
                            // 如果方面的头碰到墙壁就结束游戏,弹窗
                            if (snake.getFirst().getSe_x() - se_size < 0) {
                                popup();
                            }
                            snake.addFirst(
                                    new SE(se_size, snake.getFirst().getSe_x() - se_size, snake.getFirst().getSe_y()));
                        }
                        // 让方块往右走
                        if (direction.equalsIgnoreCase(Constant.RIGHT)) {
                            if (snake.getFirst().getSe_x() + se_size > fw) {
                                popup();
                            }
                            snake.addFirst(
                                    new SE(se_size, snake.getFirst().getSe_x() + se_size, snake.getFirst().getSe_y()));
                        }
                        // 方块动起来后,重画填充
//                        组件将被重新绘制。
                        jp.repaint();
                        try {
                            Thread.sleep(speed);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }
            }
        }).start();
    }

    private void initSnake() {
        // 创建多个有关联着的SE
        // 添加到snake容器中
        for (int i = 0; i < count; i++) {
            snake.add(new SE(se_size, se_x, se_y + se_size * i));
        }
//        long kaishi = System.na
//        System.nanoTime()
        startTime = System.nanoTime();
    }

    private void initPanel() {
        jp = new JPanel() {
            private static final long serialVersionUID = 1L;

            // 在面板中填充方块的初始位置和颜色
            @Override
            public void paint(Graphics g) {
                super.paint(g);
                if (!"".equals(tip)) {
                    g.setColor(Color.red);
                    g.setFont(new Font("", Font.BOLD, 40));
                    g.drawString(tip, 160, 160);
                }
                for (int i = 0; i < snake.size(); i++) {
                    if (i == 0) {
                        g.setColor(Color.BLUE);
                    } else {
                        g.setColor(Color.WHITE);
                    }
                    g.fill3DRect(snake.get(i).getSe_x(), snake.get(i).getSe_y(), snake.get(i).getSe_size(),
                            snake.get(i).getSe_size(), true);
                }
                // 初始化豆子
                for(int i = 0; i < b.size(); i++) {
                if(b!=null) {
                    g.setColor(colors[rand.nextInt(colors.length)]);
                    g.fill3DRect(b.get(i).getB_x(), b.get(i).getB_y(), b.get(i).getB_size(), b.get(i).getB_size(), true);
                    }
                }
                g.setColor(Color.ORANGE);
                g.setFont(new Font("", Font.BOLD, 15));
                g.drawString("成绩:"+Score, 20, 50);
                g.drawString("当前关卡:"+cheak, 20, 80);
                g.drawString("当前运动速度:"+speed+"/ms", 20, 110);
                //结束时间
                endTime = System.nanoTime();
                //记录游戏时间      游戏中暂停后,时间不会停止记录,所以要减去暂停到重新启动的时间
                g.drawString("通关时间:"+(endTime-startTime-sumtime)/1000000000+"秒", 20, 140);
                if(Score>25) {
                    g.setColor(Color.red);
                    g.setFont(new Font("", Font.BOLD, 25));
                    g.drawString("你已经通关啦", 235, 80);
                }
            }
        };
        // 设置透明度
        jp.setOpaque(false);
    }

    private void initFrame() {
        // 设置窗口标题
        this.setTitle("测试");
        // 设置窗口大小
        this.setSize(fw, fh);
        // 设置窗口背景颜色
        this.getContentPane().setBackground(Color.black);
//        禁用或启用此框架的装饰。
        this.setUndecorated(true);
        // 把面板放到窗口上
        this.add(jp);
        // 设置窗口可见
        this.setVisible(true);
        // 当前对象具有多重身份 (这是由继承结构决定的)
        // 第一个this --- 窗口对象
        // 第二个this --- 键盘监听器
        this.addKeyListener(this);
        // 把窗口设置在指定的位置
        this.setLocationRelativeTo(null);
    }

    public Main() {
        init();
    }

    public static void main(String[] args) throws FileNotFoundException, IOException {
        new Main();
//        
    }

    @Override
    public void keyTyped(KeyEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void keyPressed(KeyEvent e) {
        // 按下按一个按键 停止虚拟机运行
//        System.out.println(e.getKeyCode());
        // 按下esc键 关停虚拟机

        if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
            System.exit(0);
        }
        // 获取键盘值的上下左右,赋于我的当前对象
        if (!this.direction.equalsIgnoreCase(Constant.LEFT) && e.getKeyCode() == KeyEvent.VK_RIGHT) {
            this.direction = Constant.RIGHT;
        }
        if (!this.direction.equalsIgnoreCase(Constant.RIGHT) && e.getKeyCode() == KeyEvent.VK_LEFT) {
            this.direction = Constant.LEFT;
        }
        if (!this.direction.equalsIgnoreCase(Constant.UP) && e.getKeyCode() == KeyEvent.VK_DOWN) {
            this.direction = Constant.Down;
        }
        if (!this.direction.equalsIgnoreCase(Constant.Down) && e.getKeyCode() == KeyEvent.VK_UP) {
            this.direction = Constant.UP;
        }
        if (e.getKeyCode() == KeyEvent.VK_SPACE) {
            // 先检查status的值 如果是 "" 就修改成 pause 如果是 pause 就改成 ""
            switch (status) {
            case Constant.PAUSE://重启
                this.status = "";
                pausetime = System.nanoTime();
                sumtime +=(pausetime-resettime);
                break;
            case ""://暂停
                this.status = Constant.PAUSE;
                resettime = System.nanoTime();
                break;
            }
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        // TODO Auto-generated method stub

    }

}

蛇类:

package com.java20180917.snake;

import java.io.Serializable;
/**
 * 蛇身体关节元素  实体类
 * @author Xiaolei
 *
 */
public class SE implements Serializable{
    /**
     * 
     */
    private static final long serialVersionUID = 4103030147063529932L;
    private int se_size;
    private int se_x;
    private int se_y;
    public SE(int se_size, int se_x, int se_y) {
        super();
        this.se_size = se_size;
        this.se_x = se_x;
        this.se_y = se_y;
    }
    public SE() {
        super();
        // TODO Auto-generated constructor stub
    }
    public int getSe_size() {
        return se_size;
    }
    public void setSe_size(int se_size) {
        this.se_size = se_size;
    }
    public int getSe_x() {
        return se_x;
    }
    public void setSe_x(int se_x) {
        this.se_x = se_x;
    }
    public int getSe_y() {
        return se_y;
    }
    public void setSe_y(int se_y) {
        this.se_y = se_y;
    }
    public static long getSerialversionuid() {
        return serialVersionUID;
    }
    @Override
    public String toString() {
        return "SE [se_size=" + se_size + ", se_x=" + se_x + ", se_y=" + se_y + "]";
    }    
}

接口:package com.java20180917.snake;
/**
 * 常量接口
 * @author Xiaolei
 *
 */
public interface Constant {
    /**
     *方向常量
     */
    public static final String UP = "up";
    public static final String Down = "down";
    public static final String LEFT = "left";
    public static final String RIGHT = "right";
    public static final String TIP = "GAME OVER !";
    public static final String STOP = "stop";//停止
    public static final String PAUSE = "pause";//暂停
}
 

豆子类:

package com.java20180917.snake;


public class Bean {
    private int b_x;
    private int b_y;
    private int b_size;
    public Bean() {
        super();
        // TODO Auto-generated constructor stub
    }
    public Bean(int b_x, int b_y, int b_size) {
        super();
        this.b_x = b_x;
        this.b_y = b_y;
        this.b_size = b_size;
    }
    public int getB_x() {
        return b_x;
    }
    public void setB_x(int b_x) {
        this.b_x = b_x;
    }
    public int getB_y() {
        return b_y;
    }
    public void setB_y(int b_y) {
        this.b_y = b_y;
    }
    public int getB_size() {
        return b_size;
    }
    public void setB_size(int b_size) {
        this.b_size = b_size;
    }
    
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + b_size;
        result = prime * result + b_x;
        result = prime * result + b_y;
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Bean other = (Bean) obj;
        if (b_size != other.b_size)
            return false;
        if (b_x != other.b_x)
            return false;
        if (b_y != other.b_y)
            return false;
        return true;
    }
    @Override
    public String toString() {
        return "Bean [b_x=" + b_x + ", b_y=" + b_y + ", b_size=" + b_size + "]";
    }
    
}
配置文件值:也可以放在Mian类当中

#初始速度
speed=300
#初始长度
count = 4
fw = 600
fh = 600
b_size=20
se_size = 20
se_x = 100
se_y = 200
speed = 250

运行结果图如下:
java贪吃蛇小游戏完整版。_第1张图片
写的不是很完善,还有许多的的小问题存在,还请大家帮忙指点一二。后续技术还在学习当中。

你可能感兴趣的:(java贪吃蛇小游戏完整版。)