zoukankan      html  css  js  c++  java
  • Java_GUI小游戏--贪吃蛇

    贪吃蛇游戏:是一条蛇在封闭围墙里,围墙里随机出现一个食物,通过按键盘四个光标键控制蛇向上下左右四个方向移动,蛇头撞倒食物,则食物被吃掉,蛇身体长一节,接着又出现食物,等待蛇来吃,如果蛇在移动中撞到墙或身体交叉蛇头撞倒自己身体游戏结束。

    package game;
    
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Image;
    import java.awt.Point;
    import java.awt.event.KeyAdapter;
    import java.awt.event.KeyEvent;
    import java.util.LinkedList;
    
    import javax.swing.*;
    
    public class Snake extends    JFrame
    {
        
        //食物
        private Point point=new Point();
        //
        private LinkedList<Point>    list=new LinkedList<Point>();
        
        private int key =37;
        //为食物和蛇的坐标进行初始化
        public void init() {
            //默认食物输出化的位置
            point.setLocation(100, 100);
            list.add(new Point(300,300));
            list.add(new Point(310,300));
            list.add(new Point(320,300));
            list.add(new Point(330,300));
            list.add(new Point(340,300));
            list.add(new Point(350,300));
            list.add(new Point(360,300));
            //开始启用这个线程
            new Thread(new MoveThread()).start();
        }
        
        public void paint(Graphics g) {
            
            Image img=createImage(500,500);
            //用Graphics画笔类创建一个画笔来画出这个白布
            Graphics g2=img.getGraphics();
            //把游戏背景填充成白色
            g2.setColor(Color.WHITE);
            //设置填充范围
            g2.fillRect(0, 0, 500, 500);
            //把画笔移动到的位置
            g2.translate(50, 50);
            //设置边框为红色(边框内为蛇能活动的范围)
            g2.setColor(Color.RED);
            g2.drawRect(0,0,400,400);
            
            
            //下面实现小蛇
            g2.setColor(Color.GREEN);
            //蛇 获取List中的每一个点
            for(int i=0;i<list.size();i++) {
                //下面来得到蛇的那些小点,后面两个参数是表示小方框的大小
                //能在指定的位置画出蛇的位置
                g2.fillRect(list.get(i).x,list.get(i).y, 10, 10);
            }
            
    
            
            //画食物
            g2.setColor(Color.RED);
            g2.fillRect(point.x, point.y, 10, 10);
            
            g.drawImage(img, 0, 0, 500, 500, this);
        }
        
        public Snake() {
            //给游戏外边框添加标题(this就表示当前对象)
            this.setTitle("贪吃蛇");
            //不能改变边框的大小
            this.setResizable(false);
            //设施边框的大小
            this.setSize(500, 500);
            //居中显示
            this.setLocationRelativeTo(null);
            //当点击关闭时候程序停止
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            //设置可见
            this.setVisible(true);
            this.addKeyListener(new KeyAdapter() {
                public void keyPressed(KeyEvent e) {
                    //键盘的上下左右
                        if(e.getKeyCode()>=37&&e.getKeyCode()<=40) {
                            if(Math.abs(key-e.getKeyCode())!=2) {
                                key=e.getKeyCode();
                            }
                        }
                }
            });
            this.init();
        }
        
        //内部类 实现线程
        //写内部类是因为用线程的时候都都需要获取点的值来改变点的属性
        class MoveThread implements Runnable{
            @Override
            public void run()
            {
                // TODO Auto-generated method stub
                while(true) {
                    try {
                        Thread.sleep(150);
                    }catch(InterruptedException e) {
                        e.printStackTrace();
                    }
                    //获取蛇的第一个点
                    Point p=list.getFirst().getLocation();
                    switch(key) {//37表示前行
                    case 37:
                        p.x=p.x-10;    
                        break;
                    case 38:
                        p.y=p.y-10;    
                        break;
                    case 39:
                        p.x=p.x+10;
                        break;
                    case 40:
                        p.y=p.y+10;
                        break;
                        
                    }
                    //判断游戏结束的两种方法
                    //1.蛇超出了边界    2.蛇头碰到蛇的身体
                    if(p.x<0||p.x>390||p.y<0||p.y>390||list.contains(p)) {//在上面的时候点就已经定位到50,50
                        JOptionPane.showMessageDialog(null, "游戏结束");
                        break;
                    }
                    list.addFirst(p);
                    //当蛇吃掉食物后 马上生成新的食物 自身变长
                    if(p.equals(point)) {
                        int x=(int)(Math.random()*40)*10;
                        int y=(int)(Math.random()*40)*10;
                        point.setLocation(x, y);
                    }else {
                        //删除最后一个点
                        list.removeLast();
                    }
                    //调用画的方法
                    Snake.this.repaint();
                }
            }
            
        }
        public static void main(String[] args)
        {
            // TODO Auto-generated method stub
                new Snake();
        }
    
    }
    Snake.class

    一、首先给蛇添加一个界面

    二、对蛇和食物的初始化

    三、实现判断游戏结束的方法以及键盘对蛇的运动

     实现过程:

    一、首先给蛇添加一个界面

        public Snake() {
            //给游戏外边框添加标题(this就表示当前对象)
            this.setTitle("贪吃蛇");
            //不能改变边框的大小
            this.setResizable(false);
            //设施边框的大小
            this.setSize(500, 500);
            //居中显示
            this.setLocationRelativeTo(null);
            //当点击关闭时候程序停止
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            //设置可见
            this.setVisible(true);
        }
     

    把这些放到Snake构造函数里面的好处:可以在创建这个对象的自动调用这个里面的代码

    下面来设置游戏背景和贪吃蛇在红线里面能活动的范围

    (Graphics是Java Gui里面的一个画笔类)

    public void paint(Graphics g) {
            
            Image img=createImage(500,500);
            //用Graphics画笔类创建一个画笔来画出这个白布
            Graphics g2=img.getGraphics();
            //把游戏背景填充成白色
            g2.setColor(Color.WHITE);
            //设置填充范围
            g2.fillRect(0, 0, 500, 500);
            //把画笔移动到的位置
            g2.translate(50, 50);
            //设置边框为红色(边框内为蛇能活动的范围)
            g2.setColor(Color.RED);
            g2.drawRect(0,0,400,400);
            
    
            }


    贪吃蛇的食物可以一个红色的小方块来实现,这个食物目前是固定的,下面会实现食物的随机生成

            g2.setColor(Color.RED);
            g2.fillRect(100, 100, 10, 10);

    运行Eclipse可以看到

    二、对蛇和食物的初始化

    为了可以让蛇不断的向四周移动,我们用多个小正方形来组成,而用LinkList正好可以来组成贪吃蛇,而食物就比较简单,用一个随机生成红点就可以用来表示食物的生成

    游戏开始的时候蛇本身就已经存在,所以在游戏开始的时候蛇和食物就已经产生了


    蛇:

    public class Snake extends    JFrame
    {
        
        //食物
        private Point point=new Point();
        //
        private LinkedList<Point>    list=new LinkedList<Point>();
        
        //为食物和蛇的坐标进行初始化
        public void init() {
            //默认食物输出化的位置
            point.setLocation(100, 100);
            list.add(new Point(300,300));
            list.add(new Point(310,300));
            list.add(new Point(320,300));
            list.add(new Point(330,300));
            list.add(new Point(340,300));
            list.add(new Point(350,300));
            list.add(new Point(360,300));
            new Thread(new MoveThread()).start();
        }
    
    
            for(int i=0;i<list.size();i++) {
                //下面来得到蛇的那些小点,后面两个参数是表示小方框的大小
                //能在指定的位置画出蛇的位置
                g2.fillRect(list.get(i).x,list.get(i).y, 10, 10);
            }
    
    
    
     

    食物:

    先前上面食物点是写死了的,游戏中的食物是需要随机生成的,而我们知道了实际上这个食物的点是point,所以上面画食物的代码就可以改为

            g2.setColor(Color.RED);
            g2.fillRect(point.x, point.y, 10, 10);        

    红点的随机生成可以用到Math中的random方法

        int x=(int)(Math.random()*40)*10;
        int y=(int)(Math.random()*40)*10;
        point.setLocation(x, y);

    接下来就是在构造函数中调用这个Init()初始化方法

    public Snake() {
            //给游戏外边框添加标题(this就表示当前对象)
            this.setTitle("贪吃蛇");
            //不能改变边框的大小
            this.setResizable(false);
            //设施边框的大小
            this.setSize(500, 500);
            //居中显示
            this.setLocationRelativeTo(null);
            //当点击关闭时候程序停止
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            //设置可见
            this.setVisible(true);
            //调用init
            this.init();
        }


    运行Eclipse可以看到

     

    上面游戏的初始化就完成了,目前游戏是静止不动的,接下来我们要用上下左右四个按键来让蛇移动起来,一开始我们让蛇不断的想左移动,直到我们按下键盘上下左右才让蛇改变移动的方向,蛇移动的时候原理也很简单,可以不断的让右边的点去掉,然后让左边生成一个新的点,这时候我们就可以用到线程,用线程的好处:贪吃蛇游戏一直在往前动,我们可以通过死循环,用线程一直让贪吃蛇进行移动,我们在这里是实现一个接口,在里面重写它的Run方法,start方法已经封装好了,这个线程是一个死循环,只要游戏没有Over,线程是不断运行的

    //内部类 实现线程
        //写内部类是因为用线程的时候都都需要获取点的值来改变点的属性
        class MoveThread implements Runnable{
            @Override
            public void run()
            {
                // TODO Auto-generated method stub
                while(true) {
                    try {
                        Thread.sleep(150);    //每隔150毫秒对线程实行一次监控
                    }catch(InterruptedException e) {
                        e.printStackTrace();
                    }
                    //获取蛇的第一个点
                    Point p=list.getFirst().getLocation();
                    switch(37) {//37在ASCII中表示左的意思
                    case 37:
                        p.x=p.x-10;    
                        break;
                        
                    }
                    list.addFirst(p);
                
                    //删除最后一个点
                    list.removeLast();
                    
                    //调用画的方法
                    Snake.this.repaint();
                }
            }

    内部类实现的好处:因为在线程里面还得不断用到上面的属性,我们得改变这些点的值,如果在外面写的话还要不断去写方法得到这些点的值

    在初始化小蛇的时候开启这个线程,执行线程里面的内容

    public void init() {
            //默认食物输出化的位置
            point.setLocation(100, 100);
            list.add(new Point(300,300));
            list.add(new Point(310,300));
            list.add(new Point(320,300));
            list.add(new Point(330,300));
            list.add(new Point(340,300));
            list.add(new Point(350,300));
            list.add(new Point(360,300));
            //开始启用这个线程
            new Thread(new MoveThread()).start();
        }

    这时候蛇就一直向左动起来了,注意这里没有实现当蛇吃掉食物变长的方法,也没有判断蛇能移动范围,这时候运行Eclipse可以看到程序运行如下



    三、实现判断游戏结束的方法以及键盘对蛇的运动

    (list.contains(o),系统会对list中的每个元素e调用o.equals(e),方法,加入list中有n个元素,那么会调用n次o.equals(e),只要有一次o.equals(e)返回了true,那么list.contains(o)返回true,否则返回false。)

    //判断游戏结束的两种方法
                    //1.蛇超出了边界    2.蛇头碰到蛇的身体
                    if(p.x<0||p.x>390||p.y<0||p.y>390||list.contains(p)) {//在上面的时候点就已经定位到50,50
                        JOptionPane.showMessageDialog(null, "游戏结束");
                        break;
                    }


    在判断游戏结束下面实现游戏的一些基本逻辑

        list.addFirst(p);
                    //当蛇吃掉食物后 马上生成新的食物 自身变长
                    if(p.equals(point)) {
                        int x=(int)(Math.random()*40)*10;
                        int y=(int)(Math.random()*40)*10;
                        point.setLocation(x, y);
                    }else {
                        //删除最后一个点
                        list.removeLast();
                    }
                    //调用画的方法
                    Snake.this.repaint();

    接下来是要实现用上下左右来控制蛇的移动,这里就需要用线程不断的去监听

    定义一个变量key

    private int key =37;


    下面就是实现蛇的监听

    public Snake() {
            //给游戏外边框添加标题(this就表示当前对象)
            this.setTitle("贪吃蛇");
            //不能改变边框的大小
            this.setResizable(false);
            //设施边框的大小
            this.setSize(500, 500);
            //居中显示
            this.setLocationRelativeTo(null);
            //当点击关闭时候程序停止
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            //设置可见
            this.setVisible(true);
            this.addKeyListener(new KeyAdapter() {
                public void keyPressed(KeyEvent e) {
                    //键盘的上下左右
                        if(e.getKeyCode()>=37&&e.getKeyCode()<=40) {
                            if(Math.abs(key-e.getKeyCode())!=2) {
                                key=e.getKeyCode();
                            }
                        }
                }
            });
            this.init();
        }


    重写在线程中run方法实现的逻辑:

    public void run()
            {
                // TODO Auto-generated method stub
                while(true) {
                    try {
                        Thread.sleep(150);
                    }catch(InterruptedException e) {
                        e.printStackTrace();
                    }
                    //获取蛇的第一个点
                    Point p=list.getFirst().getLocation();
                    switch(key) {//37表示前行
                    case 37:
                        p.x=p.x-10;    
                        break;
                    case 38:
                        p.y=p.y-10;    
                        break;
                    case 39:
                        p.x=p.x+10;
                        break;
                    case 40:
                        p.y=p.y+10;
                        break;
                        
                    }
    
    
    
     

    这时候在主函数中创建这个蛇就可以运行游戏:

    public static void main(String[] args)
        {
            // TODO Auto-generated method stub
                new Snake();
        }

    运行结果如下:

    这个游戏还有很多没有完善的,比如计分板,排行榜,暂停按键,背景音乐,随机生成的食物会不会出现在蛇的身体上等等,嗯这里就当分享学习啦O(∩_∩)O哈哈~

    (如需转载学习,请标明出处)
  • 相关阅读:
    css -- 元素消失的方法
    设备-地理定位
    css -- 高度相等的列 -- 3列高度相等
    css -- 映像 ,分页(上一页下一页)
    css -- 导航条
    现代JavaScript
    移动网页 -- 结构与属性
    移动网页 -- CSS布局
    JS常规的验证代码
    分享
  • 原文地址:https://www.cnblogs.com/1138720556Gary/p/8975138.html
Copyright © 2011-2022 走看看