Java中关于贪吃蛇的实现源代码

 

小游戏(贪食蛇)
    线程
    面向对象
    文件操作
    内部类
    数据库

目标:
    可娱乐
    记录娱乐的结果
        
步骤:
    1--了解swing相关知识和小游戏设计
        通过main方法启动初始化界面
        逐步添加界面元素
        
        蛇的构成(多个关节组成)和运动方式(确认好方向,去尾加头)
        食物的构成怎么出现(随机,位置与界面宽度和高度保持整除关系(余数为龙))
        蛇如何吃豆子(头部元素与豆子元素坐标重合)
        
        确定使用哪一种容器(LinkedList)
        
    2--配置界面
        宽度、高度
    3--画出蛇
        准备数据(一个关节就是一个对象  一条蛇是一个容器)
        初始多个关节数据(关联着)
        
        作业:
            1--能独立开发出当前效果
            2--继续思考并实践后续开发
        
        
        
    4--蛇运动(按照方向运动)  可以自定义线程、Timer
        方向控制(键盘方向键控制方向  、 snake按照要求的方向继续运动)
        360、撞墙、咬自己、调速、暂停
        
    5--蛇吃豆子
    6--记录每次游戏的成绩

Main 类

package 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.util.LinkedList;

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

/**
 * 1--初始化界面 2--初始化面板 3--面板与界面合并
 */
public class Main extends JFrame implements KeyListener {

    private static final long serialVersionUID = -1803858577233572276L;

    private JPanel jp = null;

    private int fw = 600; //画布的宽
    private int fh = 600;//画布的高

    private int count = 10;//多少个蛇的关节
    private int se_size = 20;//蛇身体尺寸
    private int se_x = 100;
    private int se_y = 100;

    private int b_size = 20; //豆子的尺寸

    
    private String tip = "";

    private String status = "";

    private String dirction = Constant.UP;

    private int score = 0;
    private double speed = 200;

    private LinkedList<SE> snake = new LinkedList<SE>();
    
    private LinkedList<Bean> douzi = new LinkedList<Bean>();

    boolean b = true;
    // 总初始化方法
    private void init() {
        initSnake();
        initPanel();
        initFrame();
        initBean();
        inttThread();
    }

    private void initBean() {
        //初始化豆子
        int x = (int)(Math.random()*fw);
        int y = (int)(Math.random()*fh);
        //随机出现豆子的坐标
        int b_x = x- x% se_size;
        int b_y = y- y% se_size;
        
        //初始化元素
        //判断食物是否在身上
        for (int i = 0; i < snake.size(); i++) {
            if(snake.get(i).getSe_x() == b_x && snake.get(i).getSe_y() ==b_y) {
                b =false;
            }
        }
        if(b) {
            douzi.add(new Bean(b_size, b_x, b_y));
        }else {
            initBean();
        }
    }

    private void inttThread() {

        new Thread(new Runnable() {

            @Override
            public void run() {
                while (true) {
                    if ("".equalsIgnoreCase(status)) {
                        
                        //吃豆子
                        if(snake.getFirst().getSe_x() == douzi.getFirst().getB_x() &&
                            snake.getFirst().getSe_y() == douzi.getFirst().getB_y()) {
                            douzi.clear();
                        
                            snake.add(new SE(se_size, 
                                    snake.getLast().getSe_x(), 
                                    snake.getLast().getSe_y()));
                            score ++;
                            initBean();
                        }
                    

                        
                        // 判断是否咬到自己,(既是坐标与身体上的任意一个元素的坐标重合)
                        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()) {
                                gameOver();

                            }
                        }
                        // 操作snake容器中的元素
                        // 移除最后一个(蛇尾)
                        snake.removeLast();
                        // 添加一个到头部
                        if (dirction.equalsIgnoreCase(Constant.UP)) {
                            // 如果新的头部y坐标越界了 提示GAMEOVER
                            if (snake.getFirst().getSe_y() - se_size < 0) {
                                gameOver();
                            }else {
                            //在头部添加
                            snake.addFirst(
                                    new SE(se_size, snake.getFirst().getSe_x(), snake.getFirst().getSe_y() - se_size));
                        }
                            }

                        if (dirction.equalsIgnoreCase(Constant.RIGHT)) {
                            if (snake.getFirst().getSe_x() + se_size > fw) {
                                gameOver();
                            }else {
                            snake.addFirst(
                                    new SE(se_size, 
                                            snake.getFirst().getSe_x() + se_size, 
                                            snake.getFirst().getSe_y()));
                            }
                        }
                        if (dirction.equalsIgnoreCase(Constant.LEFT)) {
                            if (snake.getFirst().getSe_x() - se_size < 0) {
                                gameOver();
                            }else {
                            snake.addFirst(
                                    new SE(se_size, 
                                            snake.getFirst().getSe_x() - se_size, 
                                            snake.getFirst().getSe_y()));
                            }
                        }
                        if (dirction.equalsIgnoreCase(Constant.DOWN)) {
                            if (snake.getFirst().getSe_y() + se_size > fh) {
                                gameOver();
                            }else {
                            snake.addFirst(
                                    new SE(se_size,
                                        snake.getFirst().getSe_x(), 
                                        snake.getFirst().getSe_y() + se_size));
                            }
                        }
                        jp.repaint();
                        try {
                            Thread.sleep((long) speed);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        
                    }
                }
            }

        }).start();
    }
        //游戏结束条件
    public void gameOver() {
        tip = Constant.TIP;
        status = Constant.Stop;
        int op_result = JOptionPane.showConfirmDialog(jp, "GAME OVER!", "你挂了", JOptionPane.OK_CANCEL_OPTION,
                JOptionPane.ERROR_MESSAGE);
        if (op_result == 0) {
//            tip ="";
            status = "";
            snake.clear();
            initSnake();
            score =0;
        }
        if (op_result == 2) {
            System.exit(0);
        }
    }
    /**
     * 
            * 此方法描述的是:蛇吃豆子 (不能出现在蛇身上.不能出界)
            *                 Bean 
            *                  初始化豆子
            *               画出豆子
            *             吃豆子
            *             身体长一个
            * @author:fanleiemail@163.com
            * @version: 2018年9月18日
            下午3:38:21
     */
    

    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));
        }
    }

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

            @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.RED);
                    } else {
                        g.setColor(Color.GREEN);
                    }
                    g.fill3DRect(snake.get(i).getSe_x(),
                                 snake.get(i).getSe_y(), 
                                 snake.get(i).getSe_size(),
                                 snake.get(i).getSe_size(), true);
                }
                //画豆子
                    g.setColor(Color.PINK);
                    g.fill3DRect(douzi.getFirst().getB_x(),
                                 douzi.getFirst().getB_y(),
                                 douzi.getFirst().getB_size(),
                                 douzi.getFirst().getB_size(),
                                 true);
                

                    Integer i =  new Integer(score);
                    String s =    i.toString();
                    g.setColor(Color.YELLOW);
                    g.setFont(new Font("宋体",Font.BOLD,40));
                    g.drawString("总分:", 30, 40);
                    g.drawString(s, 150, 40);
            }
        };
        jp.setOpaque(false);
    }

    private void initFrame() {
        this.setTitle("测试!");
        this.setSize(fw, fh);
        this.getContentPane().setBackground(Color.DARK_GRAY);
        this.setUndecorated(true);

        this.setLocationRelativeTo(null); //设置窗体居中
        this.add(jp);//添加到画布里去

        this.setAlwaysOnTop(true);  //窗体一直处于屏幕的最前端

        this.setVisible(true);
        // 当前对象具有多重身份(这是由继承结构决定的)
        // 第一个this -- 窗口对象
        // 第二个this -- 键盘监听器
        this.addKeyListener(this);
    }

    public Main() {
        init();
    }

    public static void main(String[] args) {
        // new Main().init();
        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.dirction.equalsIgnoreCase(Constant.LEFT) && e.getKeyCode() == KeyEvent.VK_RIGHT) {
            this.dirction = Constant.RIGHT;
        }
        if (!this.dirction.equalsIgnoreCase(Constant.RIGHT) && e.getKeyCode() == KeyEvent.VK_LEFT) {
            this.dirction = Constant.LEFT;
        }
        if (!this.dirction.equalsIgnoreCase(Constant.UP) && e.getKeyCode() == KeyEvent.VK_DOWN) {
            this.dirction = Constant.DOWN;
        }
        if (!this.dirction.equalsIgnoreCase(Constant.DOWN) && e.getKeyCode() == KeyEvent.VK_UP) {
            this.dirction = Constant.UP;
        }
        if (e.getKeyCode() == KeyEvent.VK_SPACE) {
            // 先检查Status的值是什么,如果是 "" ,就修改成psuse 如果是pause 就改成 ""
            switch (status) {
            case Constant.PAUSE:
                this.status = "";
                break;
            case "":
                this.status = Constant.PAUSE;
                break;

            default:
                break;
            }
        }
    }

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

    }
}
 

SE 蛇类源代码

package java20180917.snake;

import java.io.Serializable;
/*
 * 蛇身体关节元素 实体类
 * */
public class SE  implements Serializable{

    
            /**
            * serialVersionUID:TODO(用一句话描述这个变量表示什么)
            *
            * @since Ver 1.1
            */
        
    private static final long serialVersionUID = 4042880054351783092L;
    private int se_size;
    private int se_x;
    private int se_y;
    
    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;
    }
    @Override
    public String toString() {
        return "SE [se_size=" + se_size + ", se_x=" + se_x + ", se_y=" + 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
    }

}
Bean 豆子类的源代码

package java20180917.snake;

import java.io.Serializable;
/*
 * 蛇身体关节元素 实体类
 * */
public class SE  implements Serializable{

    
            /**
            * serialVersionUID:TODO(用一句话描述这个变量表示什么)
            *
            * @since Ver 1.1
            */
        
    private static final long serialVersionUID = 4042880054351783092L;
    private int se_size;
    private int se_x;
    private int se_y;
    
    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;
    }
    @Override
    public String toString() {
        return "SE [se_size=" + se_size + ", se_x=" + se_x + ", se_y=" + 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
    }  
}

 

一些固定不变的常量源代码

package java20180917.snake;
/**
 * 
        * 此类描述的是:
        * @author:fanleiemail@163.com
        * @version: 2018年9月18日
        下午1:03:12
 */
public interface Constant {
 
    /**
     * 方向常量
     */
    public  static final String UP = "up";
    public  static final String DOWN = "down";
    public  static final String RIGHT = "right";
    public  static final String LEFT ="left";
    
    public  static final String TIP = "GAME OVER !";
    public  static final String Stop="stop";
    public  static final String PAUSE ="pause";//暂停
    
}
 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值