Java写贪吃蛇小游戏

根据遇见狂神说的视频编写的贪吃蛇小程序,在代码部分做了一些改变,添加了详细的注释,感兴趣的朋友们可以看看。
视频教程地址:一小时搞定Java贪吃蛇
下面是个人代码,源码包见地址:贪吃蛇源码

启动类

public class StartGame {
    
    
    public static void main(String[] args) {
    
    
        //1.绘制一个静态窗口 JFrame
        // 设置标题
        JFrame jf = new JFrame("xxx的贪吃蛇");
        //设置界面大小
        jf.setBounds(500,200,900,720);
        //设置是否可以改变窗口大小
        jf.setResizable(false);
        //设置关闭事件
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //2.面板Jpanel 加入到Jframe
        jf.add(new GamePanel());
        //是否可见
        jf.setVisible(true);

    }
}

画板

package com.ye.snake;


import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;

public class GamePanel  extends JPanel implements ActionListener, KeyListener {
    
    

    /*
    * 定义游戏变量
    */
    // 定义蛇身长度
    int length;
    // 定义小蛇位置坐标
    int[] snakeX = new int[500];
    int[] snakeY = new int[500];
    //定义食物坐标
    int foodX;
    int foodY;
    Random random = new Random();
    // 定义方向
    String direction;
    // 定义分数
    int score;
    // 游戏是否开始
    boolean isStart;
    // 游戏是否失败
    boolean isFail;
    // 定时器
    Timer timer = new Timer(200,this);

    // 定义初始化方法
    public GamePanel() {
    
    
        init();
       /* 获取键盘监听事件,不能放在init()方法里面
       不然每次重新开始游戏调用init()都会添加一个事件监听器,导致死亡之后按空格重新开始游戏后有两个事件监听
       再按空格启动游戏时候isStart会被改变两次仍为false,无法启动游戏*/
        this.setFocusable(true);
        this.addKeyListener(this);
    }

    public void init() {
    
    
        // 初始化长度
        length = 3;
        // 初始化分数
        score = 0;
        // 初始化蛇头
        snakeX[0] = 100;snakeY[0] = 100;
        // 初始化蛇身
        snakeX[1] = 75;snakeY[1] = 100;
        snakeX[2] = 50;snakeY[2] = 100;
        // 初始化食物位置,注意不要超过画板边界
        foodX = 25 + 25 * random.nextInt(34);
        foodY = 25 + 25 * random.nextInt(26);
        // 初始化方向
        direction = "R";
        // 游戏是否开始
        isStart = false;
        // 是否失败
        isFail = false;
        //启动定时任务
        timer.start();
    }

    //游戏画板
    @Override
    protected void paintComponent(Graphics g) {
    
    
        //清屏
        super.paintComponent(g);
        //设置背景色为白色
        this.setBackground(Color.WHITE);
        //设置游戏区域
        g.fillRect(25,25,850,650);
        // 分数和长度显示
        g.setColor(Color.blue);
        g.setFont(new Font("微软雅黑",1,30));
        g.drawString("score:" + score,50,50);
        g.drawString("length:" + length,50,80);
        // 画蛇头
        switch (direction) {
    
    
            case "R":
                Data.right.paintIcon(this,g,snakeX[0],snakeY[0]);
                break;
            case "L":
                Data.left.paintIcon(this,g,snakeX[0],snakeY[0]);
                break;
            case "U":
                Data.up.paintIcon(this,g,snakeX[0],snakeY[0]);
                break;
            case "D":
                Data.down.paintIcon(this,g,snakeX[0],snakeY[0]);
                break;
            default:
                break;
        }

        // 画蛇身
        for (int i = 1;i < length;i++) {
    
    
            Data.body.paintIcon(this,g,snakeX[i],snakeY[i]);
        }

        // 画食物
        Data.food.paintIcon(this,g,foodX,foodY);

        // 界面提示
        if (!isStart && !isFail) {
    
    
            g.setColor(Color.gray);
            g.setFont(new Font("宋体",1,40));
            g.drawString("按空格开始游戏/暂停",200,300);
        }

        // 失败提醒
        if (isFail) {
    
    
            g.setColor(Color.RED);
            g.setFont(new Font("行书",1,30));
            g.drawString("胜败乃兵家常事,大侠请重新来过!",200,300);
        }
    }

    // 定时器
    @Override
    public void actionPerformed(ActionEvent e) {
    
    
        if (isStart && isFail == false) {
    
    
            //由于坐标由i从大往小变,该处不可从小往大遍历
            for (int i = length -1;i > 0;i--) {
    
    
                snakeX[i] = snakeX[i - 1];
                snakeY[i] = snakeY[i - 1];
            }
            switch (direction) {
    
    
                case "R" :
                    snakeX[0] += 25;
                    break;
                case "L" :
                    snakeX[0] -= 25;
                    break;
                case "U" :
                    snakeY[0] -= 25;
                    break;
                case "D" :
                    snakeY[0] += 25;
                    break;
                default:
                    break;
            }
            //边界判断
            if (snakeX[0] > 850) {
    
    
                snakeX[0] = 25;
            }
            if (snakeX[0] < 25){
    
    
                snakeX[0] = 850;
            }
            if (snakeY[0] > 650) {
    
    
                snakeY[0] = 25;
            }
            if (snakeY[0] < 25) {
    
    
                snakeY[0] = 650;
            }

            // 吃到食物
            if (snakeX[0] == foodX && snakeY[0] == foodY){
    
    
                length++;
                score += 100;
                foodX = 25 + 25 * random.nextInt(34);
                foodY = 25 + 25 * random.nextInt(26);
            }

            //失败判定
            for (int i = 1;i < length;i++) {
    
    
                if (snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]) {
    
    
                    isFail = true;
                    isStart = false;
                }
            }
            //刷新界面
            repaint();
        }
        timer.start();
    }

    @Override
    public void keyTyped(KeyEvent e) {
    
    

    }

    // 监听键盘按下事件
    @Override
    public void keyPressed(KeyEvent e) {
    
    
        int keyCode = e.getKeyCode();

        // 改变方向
        switch (keyCode) {
    
    
            // 启动暂停游戏
            case KeyEvent.VK_SPACE:
                if (isFail) {
    
    
                    init();
                }else {
    
    
                    isStart = !isStart;
                }
                repaint();
                break;
            //改变方向
            case KeyEvent.VK_UP:
                direction = !"D".equals(direction) ? "U" : "D";
                break;
            case KeyEvent.VK_DOWN:
                direction = !"U".equals(direction) ? "D" : "U";
                break;
            case KeyEvent.VK_LEFT:
                direction = !"R".equals(direction) ? "L" : "R";
                break;
            case KeyEvent.VK_RIGHT:
                direction = !"L".equals(direction) ? "R" : "L";
                break;
            default:
                break;
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
    
    

    }
}

游戏资源(图片)

public class Data {
    
    
    //获取图片位置
    public static URL upUrl = Data.class.getResource("/picture/up.png");
    public static URL downUrl = Data.class.getResource("/picture/down.png");
    public static URL rightUrl = Data.class.getResource("/picture/right.png");
    public static URL leftUrl = Data.class.getResource("/picture/left.png");
    public static URL bodyUrl = Data.class.getResource("/picture/body.png");
    public static URL foodUrl = Data.class.getResource("/picture/food.png");

    //获取图片
    public static ImageIcon up = new ImageIcon(upUrl);
    public static ImageIcon down = new ImageIcon(downUrl);
    public static ImageIcon right = new ImageIcon(rightUrl);
    public static ImageIcon left = new ImageIcon(leftUrl);
    public static ImageIcon body = new ImageIcon(bodyUrl);
    public static ImageIcon food = new ImageIcon(foodUrl);

}

猜你喜欢

转载自blog.csdn.net/lunatic__/article/details/112386212