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<SE> snake = new LinkedList<SE>();
     private String direction = Constant.UP;
     
     private String tip = "";
     private String status = "";
     //速度
     private long speed;
     private Random rand = new Random();
     private LinkedList<Bean> b = new LinkedList<Bean>();
     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贪吃蛇摘要_Java贪吃蛇摘要


写的不是很完善,还有许多的的小问题存在,还请大家帮忙指点一二。后续技术还在学习当中。