貪吃蛇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) {
        //釋放某個鍵
    }
}

  註釋已經寫的很詳細了,就不再過多贅述了。

發佈了79 篇原創文章 · 獲贊 43 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章