贪吃蛇Java版

贪吃蛇小游戏

1. 简介

  这是用Java的Swing工具实现的一个小程序。

  与传统的贪吃蛇游戏一样,通过“上、下、左、右”控制方向觅食,随着吃的食物越多,身体会变得越长,移动速度也会变得越快。

  死亡条件:①头碰到身体。②头碰到墙壁。

关于这个程序的源代码及打包资源,我上传到资源下载和GitHub仓库了,可以直接去下载:

资源下载地址:CSDN资源下载
GitHub地址:Gluttonous-Snake



2. 程序代码部分

我这里的开发环境是:

  • IDEA_2019.2.3
  • Java_8

2.1 目录结构

在这里插入图片描述

2.2 代码实现

  1. StartGames.java
package com.jacks.snake;

import javax.swing.*;

/**
 * 程序启动类,main方法
 */
public class StartGames {
    public static void main(String[] args) {
        /**
         * 绘制一个游戏窗口 JFrame
         */
        JFrame frame = new JFrame("贪吃蛇小游戏   作者:赤魂丶");//窗口标题
        frame.setBounds(10,10,900,720);   //设置窗口的大小
        frame.setResizable(false);  //窗口大小不可以改变
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //设置关闭事件,游戏关闭,程序结束
        /**
         *  添加面板 Panel
         */
        frame.add(new GamePanel());//添加面板
        frame.setVisible(true);//展示窗口
    }
}

  1. Data.java
package com.jacks.snake;

import javax.swing.*;
import java.net.URL;

/**
 * 游戏的数据存放类
 */
class Data {
    //顶部图片背景
    private static URL headerUrl = Data.class.getResource("/statics/header.png");
    static ImageIcon header = new ImageIcon(headerUrl);
    //蛇头
    private static URL upUrl = Data.class.getResource("/statics/up.png");
    private static URL downUrl = Data.class.getResource("/statics/down.png");
    private static URL leftUrl = Data.class.getResource("/statics/left.png");
    private static URL rightUrl = Data.class.getResource("/statics/right.png");
    static ImageIcon up = new ImageIcon(upUrl);
    static ImageIcon down = new ImageIcon(downUrl);
    static ImageIcon left = new ImageIcon(leftUrl);
    static ImageIcon right = new ImageIcon(rightUrl);
    // 身体
    private static URL bodyUrl = Data.class.getResource("/statics/body.png");
    static ImageIcon body = new ImageIcon(bodyUrl);
    //食物
    private static URL foodUrl = Data.class.getResource("/statics/food.png");
    static ImageIcon food = new ImageIcon(foodUrl);
}

  1. GamePanel.java
package com.jacks.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;

/**
 * 游戏的业务逻辑类,制作 JPanel 面板
 */
public class GamePanel extends JPanel implements KeyListener, ActionListener {

    /*
    蛇的相关属性
     */
    private int length;                     //蛇长度
    private int[] snakeX = new int[600];    //蛇的X座标
    private int[] snakeY = new int[500];    //蛇的Y座标
    private String fx;                      //蛇头方向
    /*
    食物的相关属性
     */
    private int foodX;
    private int foodY;
    private Random random = new Random();
    /*
    系统相关属性
     */
    private int speed;
    private Timer timer = new Timer(speed, this);//定时器
    private boolean isStart = false;        //游戏是否开始
    private int isFail = 0;         //游戏是否失败,默人不失败
    private int score;                      //分数系统
    private int scoreM = 0;                 //历史最高分

    /**
     * 初始化函数
     */
    private void init() {
        speed = 100;
        timer.setDelay(speed);
        length = 3;
        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 = 75 + 25 * random.nextInt(24);
        score = 0;
        fx = "R";

    }

    /**
     * 构造函数
     */
    GamePanel() {
        init();
        //获取键盘的监听事件
        this.setFocusable(true);
        this.addKeyListener(this);
        timer.start();//定时器启动
    }

    @Override
    protected void paintComponent(Graphics g) {//TODO:画静态界面
        super.paintComponent(g);            //清屏
        this.setBackground(Color.BLACK);    //背景颜色
        Data.header.paintIcon(this, g, 25, 11);//绘制头部的广告栏
        g.fillRect(25, 75, 850, 600);//绘制游戏区域

        switch (fx) {//TODO:根据控制画蛇头方向
            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;
        }
        for (int i = 1; i < length; i++) {//TODO:根据长度画蛇的身体
            Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
        }
        Data.food.paintIcon(this, g, foodX, foodY);//TODO:画食物
        // 画积分
        g.setColor(Color.WHITE);//TODO:画计分系统
        g.setFont(new Font("华文楷体", Font.BOLD, 18));
        g.drawString("当前长度:" + length, 520, 35);
        g.drawString("当前分数:" + score, 370, 35);
        if (score >= scoreM) scoreM = score;
        g.drawString("历史最高分:" + scoreM, 370, 50);
        if (!isStart) {//TODO:用字符串提示游戏开始
            g.setColor(Color.RED);
            g.setFont(new Font("华文楷体", Font.BOLD, 45));//字体、加粗、大小
            g.drawString("按下空格开始游戏", 300, 300);
        }
        if (isFail == 1) {//TODO:用字符串提示游戏失败
            g.setColor(Color.RED);
            g.setFont(new Font("华文楷体", Font.BOLD, 40));//字体、加粗、大小
            g.drawString("游戏失败,你啃到自己了,按空格重新开始!", 35, 300);
        } else if (isFail == 2) {//TODO:提示游戏失败
            g.setColor(Color.RED);
            g.setFont(new Font("华文楷体", Font.BOLD, 40));//字体、加粗、大小
            g.drawString("游戏失败,您撞到墙了,按空格重新开始!", 35, 300);
        }
    }
    // TODO:监听键盘输入
    // 按下不释放
    @Override
    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();//记录按键
        if (keyCode == KeyEvent.VK_SPACE) {//TODO:按下空格暂停或重启游戏
            if (isFail != 0) {//失败后按空格重启
                isFail = 0;
                init();
            } else {//为失败按空格为暂停
                isStart = !isStart;
            }
            repaint();//刷新界面
        }
        if (keyCode == KeyEvent.VK_LEFT && !fx.equals("R")) {//TODO:用键盘控制移动方向
            fx = "L";
        } else if (keyCode == KeyEvent.VK_RIGHT && !fx.equals("L")) {
            fx = "R";
        } else if (keyCode == KeyEvent.VK_UP && !fx.equals("D")) {
            fx = "U";
        } else if (keyCode == KeyEvent.VK_DOWN && !fx.equals("U")) {
            fx = "D";
        }
    }
    @Override
    public void actionPerformed(ActionEvent e) {//TODO:控制游戏状态
        if (isStart && isFail == 0) {//TODO:游戏开启并且没有失败
            for (int i = length - 1; i > 0; i--) {//TODO:移动身体
                snakeX[i] = snakeX[i - 1];
                snakeY[i] = snakeY[i - 1];
            }
            switch (fx) {//TODO:判断是否碰到边界
                case "R":
                    snakeX[0] = snakeX[0] + 25;
                    if (snakeX[0] > 850) {
                        isFail = 2;
                        init();
                        // snakeX[0] = 25;
                    }
                    break;
                case "L":
                    snakeX[0] = snakeX[0] - 25;
                    if (snakeX[0] < 25) {
                        isFail = 2;
                        init();
                        //snakeX[0] = 850;
                    }
                    break;
                case "U":
                    snakeY[0] = snakeY[0] - 25;
                    if (snakeY[0] < 75) {
                        isFail = 2;
                        init();
                        //snakeY[0] = 650;
                    }
                    break;
                case "D":
                    snakeY[0] = snakeY[0] + 25;
                    if (snakeY[0] > 650) {
                        isFail = 2;
                        init();
                        //snakeY[0] = 75;
                    }
                    break;
            }
            //判断吃食物
            if (snakeX[0] == foodX && snakeY[0] == foodY) {
                length++;               //蛇长度加1
                score += 10;            //分数+10
                if (length <= 7) {
                    speed -= 5;
                } else if (length <= 10) {
                    speed -= 2;
                } else if (length <= 20) {
                    speed -= 1;
                } else if (length % 3 == 0) {
                    speed -= 1;
                }
                timer.setDelay(speed);
                //生成新食物
                foodX = 25 + 25 * random.nextInt(34);
                foodY = 75 + 25 * random.nextInt(24);

            }
            // 吃到自己失败
            for (int i = 1; i < length; i++) {
                if (snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]) {
                    isFail = 1;
                    break;
                }
            }
            //刷新界面
            repaint();
        }
        timer.start();//定时器启动
    }
	/*
	以下是未用到的按键监听函数复写
	*/
    @Override
    public void keyTyped(KeyEvent e) {
        //键盘按下并释放
    }
    @Override
    public void keyReleased(KeyEvent e) {
        //释放某个键
    }
}

  注释已经写的很详细了,就不再过多赘述了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章