Java GUI 實(shí)例:貪吃蛇游戲

Java GUI 基礎(chǔ)

一、實(shí)現(xiàn)效果

  1. 空格暫停;
  2. 上彼硫、下、左凌箕、右控制方向拧篮;
  3. 長度隨著食物的吃下,而增加;
  4. 定時(shí)刷新陌知;
  5. 累計(jì)長度和分?jǐn)?shù)等他托。

二掖肋、實(shí)現(xiàn)思路:

  1. 定義所有功能的數(shù)據(jù)
  2. 繪制功能需要的圖形
  3. 添加監(jiān)聽功能需要的事件(幀率事件)鍵盤仆葡、鼠標(biāo)

三、實(shí)現(xiàn)代碼

  • Data(數(shù)據(jù)類):初始化需要的圖片志笼;
  • StartGame(游戲主啟動(dòng)類):主要實(shí)現(xiàn)窗口的加載沿盅,和添加 GamePanel 面板到窗口;
  • GamePanel(游戲的面板):最重要的實(shí)現(xiàn)部分纫溃,包括:
    • 定義需要的數(shù)據(jù)
    • 繪制圖像
    • 實(shí)現(xiàn)事件監(jiān)聽
  1. 靜態(tài)界面繪制
  • StartGame.java
package com.xxx.gui.snake;

import javax.swing.*;

/**
 * 游戲主啟動(dòng)類
 */
public class StartGame {
    public StartGame() {
        JFrame frame = new JFrame("貪吃蛇");
        // 長寬尺寸腰涧,根據(jù)內(nèi)容計(jì)算得出
        frame.setBounds(10, 10, 915, 730);
        // 窗口大小不可變,避免游戲變形
        frame.setResizable(false);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        // 將游戲面板添加到窗口中
        frame.add(new GamePanel());
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        new StartGame();
    }
}
  • Date.java
package com.xxx.gui.snake;

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

/**
 * 數(shù)據(jù)類
 */
public class Data {
    // 相對(duì)路徑 header.png
    // 絕對(duì)路徑 / 相當(dāng)于當(dāng)前的項(xiàng)目
    // 頂部圖片
    public static URL headerURL = Data.class.getResource("statics/header.png");
    // 圖像轉(zhuǎn)為圖標(biāo)
    public static ImageIcon header = new ImageIcon(headerURL);
    // 上下左右
    public static URL upURL = Data.class.getResource("statics/up.png");
    public static URL downURL = Data.class.getResource("statics/down.png");
    public static URL leftURL = Data.class.getResource("statics/left.png");
    public static URL rightURL = Data.class.getResource("statics/right.png");
    public static ImageIcon up = new ImageIcon(upURL);
    public static ImageIcon down = new ImageIcon(downURL);
    public static ImageIcon left = new ImageIcon(leftURL);
    public static ImageIcon right = new ImageIcon(rightURL);
    // 身體
    public static URL bodyURL = Data.class.getResource("statics/body.png");
    public static ImageIcon body = new ImageIcon(bodyURL);
    // 食物
    public static URL foodURL = Data.class.getResource("statics/food.png");
    public static ImageIcon food = new ImageIcon(foodURL);
}
  • GamePanel.java
package com.xxx.gui.snake;

import javax.swing.*;
import java.awt.*;

/**
 * 游戲的面板
 */
public class GamePanel extends JPanel {
    // 繪制面板紊浩,游戲中所有的東西窖铡,都是用這個(gè)筆來畫
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);    // 清屏
        // 繪制靜態(tài)面板
        this.setBackground(Color.WHITE);
        // 頂部圖片繪制到當(dāng)前組件中
        Data.header.paintIcon(this, g, 25, 11);
        // 默認(rèn)的游戲界面,坐標(biāo)及尺寸坊谁,經(jīng)過計(jì)算得出
        g.fillRect(25, 75, 850, 600);
    }
}
  1. 繪制靜態(tài)小蛇
  • GamePanel.java
package com.xxx.gui.snake;

import javax.swing.*;
import java.awt.*;

/**
 * 游戲的面板
 */
public class GamePanel extends JPanel {
    // 定義蛇的數(shù)據(jù)結(jié)構(gòu)
    int length; // 蛇的長度
    int[] snakeX = new int[600];  // 蛇的 X 坐標(biāo)费彼,25*25
    int[] snakeY = new int[500];  // 蛇的 Y 坐標(biāo),25*25
    String fx;  // 初始方向:向右
    // 游戲當(dāng)前狀態(tài):開始口芍,停止
    boolean isStart = false;    // 默認(rèn)停止

    // 構(gòu)造器
    public GamePanel() {
        // 調(diào)用初始化
        init();
    }

    // 初始化方法
    public void init() {
        // 初始蛇有三節(jié),包括頭
        length = 3;
        // 初始化開始的蛇箍铲,給蛇定位
        // 頭部位置
        snakeX[0] = 100;
        snakeY[0] = 100;
        // 第一節(jié)身體
        snakeX[1] = 75;
        snakeY[1] = 100;
        // 第二節(jié)身體
        snakeX[2] = 50;
        snakeY[2] = 100;
        fx = "R";
    }

    // 繪制面板,游戲中所有的東西鬓椭,都是用這個(gè)筆來畫
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);    // 清屏
        // 繪制靜態(tài)面板
        this.setBackground(Color.WHITE);
        // 頂部圖片繪制到當(dāng)前組件中
        Data.header.paintIcon(this, g, 25, 11);
        // 默認(rèn)的游戲界面颠猴,坐標(biāo)及尺寸关划,經(jīng)過計(jì)算得出
        g.fillRect(25, 75, 850, 600);

        // 把小蛇畫上去
        // 蛇頭初始化,向右,需要通過方向來判斷
        if (fx.equals("R")) {
            Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx.equals("L")) {
            Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx.equals("U")) {
            Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx.equals("D")) {
            Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
        }

        // 根據(jù)身體的長度翘瓮,繪制蛇身
        for (int i = 1; i < length; i++) {
            Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
        }

        //游戲狀態(tài)
        if (isStart == false) {
            g.setColor(Color.white);
            g.setFont(new Font("黑體", Font.BOLD, 40));   // 設(shè)置字體
            g.drawString("按下空格開始游戲", 300, 300);    // 初始文字
        }
    }
}
  1. 小蛇開始移動(dòng)
  • GamePanel.java
package com.xxx.gui.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;

/**
 * 游戲的面板
 * ActionListener(接口):實(shí)現(xiàn)定時(shí)器
 */
public class GamePanel extends JPanel implements KeyListener, ActionListener {
    // 定義蛇的數(shù)據(jù)結(jié)構(gòu)
    int length; // 蛇的長度
    int[] snakeX = new int[600];  // 蛇的 X 坐標(biāo)贮折,25*25
    int[] snakeY = new int[500];  // 蛇的 Y 坐標(biāo),25*25
    String fx;  // 初始方向:向右
    // 游戲當(dāng)前狀態(tài):開始春畔,停止
    boolean isStart = false;    // 默認(rèn)停止

    // 定時(shí)器:100(ms) 毫秒刷新一次(1000ms=1秒)
    Timer timer = new Timer(100, this);

    // 構(gòu)造器
    public GamePanel() {
        // 調(diào)用初始化
        init();
        // 獲取事件
        this.setFocusable(true);    // 焦點(diǎn)事件
        this.addKeyListener(this); // 鍵盤監(jiān)聽事件
        timer.start();  // 游戲一開始脱货,定時(shí)器啟動(dòng)
    }

    // 初始化方法
    public void init() {
        // 初始蛇有三節(jié),包括頭
        length = 3;
        // 初始化開始的蛇,給蛇定位
        // 頭部位置
        snakeX[0] = 100;
        snakeY[0] = 100;
        // 第一節(jié)身體
        snakeX[1] = 75;
        snakeY[1] = 100;
        // 第二節(jié)身體
        snakeX[2] = 50;
        snakeY[2] = 100;
        fx = "R";
    }

    // 繪制面板律姨,游戲中所有的東西振峻,都是用這個(gè)筆來畫
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);    // 清屏
        // 繪制靜態(tài)面板
        this.setBackground(Color.WHITE);
        // 頂部圖片繪制到當(dāng)前組件中
        Data.header.paintIcon(this, g, 25, 11);
        // 默認(rèn)的游戲界面,坐標(biāo)及尺寸择份,經(jīng)過計(jì)算得出
        g.fillRect(25, 75, 850, 600);

        // 把小蛇畫上去
        // 蛇頭初始化扣孟,向右,需要通過方向來判斷
        if (fx.equals("R")) {
            Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx.equals("L")) {
            Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx.equals("U")) {
            Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx.equals("D")) {
            Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
        }

        // 根據(jù)身體的長度,繪制蛇身
        for (int i = 1; i < length; i++) {
            Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
        }

        //游戲狀態(tài)
        if (isStart == false) {
            g.setColor(Color.white);
            g.setFont(new Font("黑體", Font.BOLD, 40));   // 設(shè)置字體
            g.drawString("按下空格開始游戲", 300, 300);    // 初始文字
        }
    }

    // 鍵盤監(jiān)聽事件
    @Override
    public void keyPressed(KeyEvent e) {
        // 獲得鍵盤按鍵
        int keyCode = e.getKeyCode();
        // 如果按下空格鍵
        if (keyCode == KeyEvent.VK_SPACE) {
            isStart = !isStart;   // 取反
            repaint();  // 重新繪制
        }
        // 小蛇移動(dòng)(通過方向鍵判斷)
        if (keyCode == KeyEvent.VK_UP) {
            fx = "U";
        } else if (keyCode == KeyEvent.VK_DOWN) {
            fx = "D";
        } else if (keyCode == KeyEvent.VK_LEFT) {
            fx = "L";
        } else if (keyCode == KeyEvent.VK_RIGHT) {
            fx = "R";
        }
    }

    // 事件監(jiān)聽:定時(shí)執(zhí)行時(shí)的操作(刷新)
    @Override
    public void actionPerformed(ActionEvent e) {
        // 如果是開始狀態(tài)荣赶,讓小蛇移動(dòng)
        if (isStart) {
            // 移動(dòng):
            for (int i = length - 1; i > 0; i--) {
                // 身體后一節(jié)移到前一節(jié)的位置(snakeX[1]=snakeX[0])
                snakeX[i] = snakeX[i - 1];
                snakeY[i] = snakeY[i - 1];
            }
            // 通過方向鍵控制凤价,頭部移動(dòng)
            if (fx.equals("R")) {
                // 頭部 X 坐標(biāo),右移一格(25)
                snakeX[0] = snakeX[0] + 25;
                // 判斷邊界:超出后拔创,回到最左邊
                if (snakeX[0] > 850) snakeX[0] = 25;
            } else if (fx.equals("L")) {
                snakeX[0] = snakeX[0] - 25;
                // 判斷邊界:超出后利诺,回到最右邊
                if (snakeX[0] < 25) snakeX[0] = 850;
            } else if (fx.equals("U")) {
                snakeY[0] = snakeY[0] - 25;
                // 判斷邊界:超出后,回到最左邊
                if (snakeY[0] < 75) snakeY[0] = 650;
            } else if (fx.equals("D")) {
                snakeY[0] = snakeY[0] + 25;
                if (snakeY[0] > 650) snakeY[0] = 75;
            }
            repaint();  // 重畫頁面
        }
        timer.start();  // 定時(shí)器開啟
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }
}
  1. 小蛇開始吃食物
  • GamePanel.java
package com.xxx.gui.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;

/**
 * 游戲的面板
 * ActionListener(接口):實(shí)現(xiàn)定時(shí)器
 */
public class GamePanel extends JPanel implements KeyListener, ActionListener {
    // 定義蛇的數(shù)據(jù)結(jié)構(gòu)
    int length; // 蛇的長度
    int[] snakeX = new int[600];  // 蛇的 X 坐標(biāo)剩燥,25*25
    int[] snakeY = new int[500];  // 蛇的 Y 坐標(biāo)慢逾,25*25
    String fx;  // 初始方向:向右

    // 食物坐標(biāo)
    int foodX;
    int foodY;
    Random random = new Random();   // 獲取隨機(jī)數(shù)

    // 游戲當(dāng)前狀態(tài):開始,停止
    boolean isStart = false;    // 默認(rèn)停止

    // 定時(shí)器:100(ms) 毫秒刷新一次(1000ms=1秒)
    Timer timer = new Timer(100, this);

    // 構(gòu)造器
    public GamePanel() {
        // 調(diào)用初始化
        init();
        // 獲取事件
        this.setFocusable(true);    // 焦點(diǎn)事件
        this.addKeyListener(this); // 鍵盤監(jiān)聽事件
        timer.start();  // 游戲一開始灭红,定時(shí)器啟動(dòng)
    }

    // 初始化方法
    public void init() {
        // 初始蛇有三節(jié),包括頭
        length = 3;
        // 初始化開始的蛇侣滩,給蛇定位
        // 頭部位置
        snakeX[0] = 100;
        snakeY[0] = 100;
        // 第一節(jié)身體
        snakeX[1] = 75;
        snakeY[1] = 100;
        // 第二節(jié)身體
        snakeX[2] = 50;
        snakeY[2] = 100;
        fx = "R";
        // 把食物隨機(jī)分布在界面上
        foodX = 25 + 25 * random.nextInt(34); // 34:850/25
        foodY = 75 + 25 * random.nextInt(34); // 24:600/25

    }

    // 繪制面板,游戲中所有的東西变擒,都是用這個(gè)筆來畫
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);    // 清屏
        // 繪制靜態(tài)面板
        this.setBackground(Color.WHITE);
        // 頂部圖片繪制到當(dāng)前組件中
        Data.header.paintIcon(this, g, 25, 11);
        // 默認(rèn)的游戲界面君珠,坐標(biāo)及尺寸,經(jīng)過計(jì)算得出
        g.fillRect(25, 75, 850, 600);

        // 把小蛇畫上去
        // 蛇頭初始化娇斑,向右,需要通過方向來判斷
        if (fx.equals("R")) {
            Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx.equals("L")) {
            Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx.equals("U")) {
            Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx.equals("D")) {
            Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
        }

        // 根據(jù)身體的長度策添,繪制蛇身
        for (int i = 1; i < length; i++) {
            Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
        }

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

        //游戲狀態(tài)
        if (isStart == false) {
            g.setColor(Color.white);
            g.setFont(new Font("黑體", Font.BOLD, 40));   // 設(shè)置字體
            g.drawString("按下空格開始游戲", 300, 300);    // 初始文字
        }
    }

    // 鍵盤監(jiān)聽事件
    @Override
    public void keyPressed(KeyEvent e) {
        // 獲得鍵盤按鍵
        int keyCode = e.getKeyCode();
        // 如果按下空格鍵
        if (keyCode == KeyEvent.VK_SPACE) {
            isStart = !isStart;   // 取反
            repaint();  // 重新繪制
        }
        // 小蛇移動(dòng)(通過方向鍵判斷)
        if (keyCode == KeyEvent.VK_UP) {
            fx = "U";
        } else if (keyCode == KeyEvent.VK_DOWN) {
            fx = "D";
        } else if (keyCode == KeyEvent.VK_LEFT) {
            fx = "L";
        } else if (keyCode == KeyEvent.VK_RIGHT) {
            fx = "R";
        }
    }

    // 事件監(jiān)聽:定時(shí)執(zhí)行時(shí)的操作(刷新)
    @Override
    public void actionPerformed(ActionEvent e) {
        // 如果是開始狀態(tài),讓小蛇移動(dòng)
        if (isStart) {
            // 吃食物
            if (snakeX[0] == foodX && snakeY[0] == foodY) {
                // 身體長度+1
                length++;
                // 再次隨機(jī)食物
                // 把食物隨機(jī)分布在界面上
                foodX = 25 + 25 * random.nextInt(34);
                foodY = 75 + 25 * random.nextInt(34);
            }
            // 移動(dòng):
            for (int i = length - 1; i > 0; i--) {
                // 身體后一節(jié)移到前一節(jié)的位置(snakeX[1]=snakeX[0])
                snakeX[i] = snakeX[i - 1];
                snakeY[i] = snakeY[i - 1];
            }
            // 通過方向鍵控制毫缆,頭部移動(dòng)
            if (fx.equals("R")) {
                // 頭部 X 坐標(biāo)唯竹,右移一格(25)
                snakeX[0] = snakeX[0] + 25;
                // 判斷邊界:超出后,回到最左邊
                if (snakeX[0] > 850) snakeX[0] = 25;
            } else if (fx.equals("L")) {
                snakeX[0] = snakeX[0] - 25;
                // 判斷邊界:超出后悔醋,回到最右邊
                if (snakeX[0] < 25) snakeX[0] = 850;
            } else if (fx.equals("U")) {
                snakeY[0] = snakeY[0] - 25;
                // 判斷邊界:超出后摩窃,回到最左邊
                if (snakeY[0] < 75) snakeY[0] = 650;
            } else if (fx.equals("D")) {
                snakeY[0] = snakeY[0] + 25;
                if (snakeY[0] > 650) snakeY[0] = 75;
            }
            repaint();  // 重畫頁面
        }
        timer.start();  // 定時(shí)器開啟
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }
}
  1. 失敗判定,積分系統(tǒng)
  • GamePanel.java
package com.xxx.gui.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;

/**
 * 游戲的面板
 * ActionListener(接口):實(shí)現(xiàn)定時(shí)器
 */
public class GamePanel extends JPanel implements KeyListener, ActionListener {
    // 定義蛇的數(shù)據(jù)結(jié)構(gòu)
    int length; // 蛇的長度
    int[] snakeX = new int[600];  // 蛇的 X 坐標(biāo),25*25
    int[] snakeY = new int[500];  // 蛇的 Y 坐標(biāo)猾愿,25*25
    String fx;  // 初始方向:向右
    // 食物坐標(biāo)
    int foodX;
    int foodY;
    Random random = new Random();   // 獲取隨機(jī)數(shù)
    // 成績
    int score;
    // 游戲當(dāng)前狀態(tài):開始鹦聪,停止
    boolean isStart = false;    // 默認(rèn)停止
    // 游戲失敗狀態(tài)
    boolean isFail = false;
    // 定時(shí)器:100(ms) 毫秒刷新一次(1000ms=1秒)
    Timer timer = new Timer(100, this);

    // 構(gòu)造器
    public GamePanel() {
        // 調(diào)用初始化
        init();
        // 獲取事件
        this.setFocusable(true);    // 焦點(diǎn)事件
        this.addKeyListener(this); // 鍵盤監(jiān)聽事件
        timer.start();  // 游戲一開始,定時(shí)器啟動(dòng)
    }

    // 初始化方法
    public void init() {
        // 初始蛇有三節(jié),包括頭
        length = 3;
        // 初始化開始的蛇蒂秘,給蛇定位
        // 頭部位置
        snakeX[0] = 100;
        snakeY[0] = 100;
        // 第一節(jié)身體
        snakeX[1] = 75;
        snakeY[1] = 100;
        // 第二節(jié)身體
        snakeX[2] = 50;
        snakeY[2] = 100;
        fx = "R";
        // 把食物隨機(jī)分布在界面上
        foodX = 25 + 25 * random.nextInt(34); // 34:850/25
        foodY = 75 + 25 * random.nextInt(24); // 24:600/25

        score = 0;
    }

    // 繪制面板泽本,游戲中所有的東西,都是用這個(gè)筆來畫
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);    // 清屏
        // 繪制靜態(tài)面板
        this.setBackground(Color.WHITE);
        // 頂部圖片繪制到當(dāng)前組件中
        Data.header.paintIcon(this, g, 25, 11);
        // 默認(rèn)的游戲界面姻僧,坐標(biāo)及尺寸规丽,經(jīng)過計(jì)算得出
        g.fillRect(25, 75, 850, 600);
        // 畫積分
        g.setColor(Color.WHITE);
        g.setFont(new Font("黑體", Font.BOLD, 16));
        g.drawString("長度 " + length, 750, 32);
        g.drawString("分?jǐn)?shù) " + score, 750, 53);
        // 畫食物
        Data.food.paintIcon(this, g, foodX, foodY);
        // 把小蛇畫上去
        // 蛇頭初始化,向右,需要通過方向來判斷
        if (fx.equals("R")) {
            Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx.equals("L")) {
            Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx.equals("U")) {
            Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx.equals("D")) {
            Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
        }
        // 根據(jù)身體的長度撇贺,繪制蛇身
        for (int i = 1; i < length; i++) {
            Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
        }
        // 游戲狀態(tài)
        if (isStart == false) {
            g.setColor(Color.white);
            g.setFont(new Font("黑體", Font.BOLD, 40));   // 設(shè)置字體
            g.drawString("按下空格開始游戲", 300, 300);    // 初始文字
        }
        //  失敗狀態(tài)
        if (isFail) {
            g.setColor(Color.RED);
            g.setFont(new Font("黑體", Font.BOLD, 40));   // 設(shè)置字體
            g.drawString("失敗赌莺,按下空格重新開始", 300, 300);    // 初始文字
        }
    }

    // 鍵盤監(jiān)聽事件
    @Override
    public void keyPressed(KeyEvent e) {
        // 獲得鍵盤按鍵
        int keyCode = e.getKeyCode();
        // 如果按下空格鍵
        if (keyCode == KeyEvent.VK_SPACE) {
            if (isFail) {
                // 重新開始
                isFail = false;
                init();
            } else {
                isStart = !isStart;   // 取反
            }
            repaint();  // 重新繪制
        }
        // 小蛇移動(dòng)(通過方向鍵判斷)
        if (keyCode == KeyEvent.VK_UP) {
            fx = "U";
        } else if (keyCode == KeyEvent.VK_DOWN) {
            fx = "D";
        } else if (keyCode == KeyEvent.VK_LEFT) {
            fx = "L";
        } else if (keyCode == KeyEvent.VK_RIGHT) {
            fx = "R";
        }
    }

    // 事件監(jiān)聽:定時(shí)執(zhí)行時(shí)的操作(刷新)
    @Override
    public void actionPerformed(ActionEvent e) {
        // 如果是開始狀態(tài),且沒有結(jié)束松嘶,讓小蛇移動(dòng)
        if (isStart && isFail == false) {
            // 吃食物
            if (snakeX[0] == foodX && snakeY[0] == foodY) {
                // 身體長度+1
                length++;
                // 分?jǐn)?shù)+10
                score += 10;
                // 再次隨機(jī)食物
                // 把食物隨機(jī)分布在界面上
                foodX = 25 + 25 * random.nextInt(34);
                foodY = 75 + 25 * random.nextInt(24);
            }
            // 移動(dòng):
            for (int i = length - 1; i > 0; i--) {
                // 身體后一節(jié)移到前一節(jié)的位置(snakeX[1]=snakeX[0])
                snakeX[i] = snakeX[i - 1];
                snakeY[i] = snakeY[i - 1];
            }
            // 通過方向鍵控制艘狭,頭部移動(dòng)
            if (fx.equals("R")) {
                // 頭部 X 坐標(biāo),右移一格(25)
                snakeX[0] = snakeX[0] + 25;
                // 判斷邊界:超出后翠订,回到最左邊
                if (snakeX[0] > 850) snakeX[0] = 25;
            } else if (fx.equals("L")) {
                snakeX[0] = snakeX[0] - 25;
                // 判斷邊界:超出后巢音,回到最右邊
                if (snakeX[0] < 25) snakeX[0] = 850;
            } else if (fx.equals("U")) {
                snakeY[0] = snakeY[0] - 25;
                // 判斷邊界:超出后,回到最左邊
                if (snakeY[0] < 75) snakeY[0] = 650;
            } else if (fx.equals("D")) {
                snakeY[0] = snakeY[0] + 25;
                if (snakeY[0] > 650) snakeY[0] = 75;
            }
            // 失敗判斷:撞到自己
            // 遍歷身體的每一個(gè)坐標(biāo)
            for (int i = 1; i < length; i++) {
                // 頭部坐標(biāo)與身體坐標(biāo)重合
                if (snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]) {
                    // 游戲失敗
                    isFail = true;
                }
            }
            repaint();  // 重畫頁面
        }
        timer.start();  // 定時(shí)器開啟
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }
}

Java 版貪吃蛇尽超,圖片素材:

  • 食物 – food.png
  • 上 – up.png
  • 下 – down.png
  • 左 – left.png
  • 右 – right.png
  • 身體 – body.png
  • 頂部圖片 – header.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末官撼,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子似谁,更是在濱河造成了極大的恐慌傲绣,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件棘脐,死亡現(xiàn)場離奇詭異斜筐,居然都是意外死亡龙致,警方通過查閱死者的電腦和手機(jī)蛀缝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來目代,“玉大人屈梁,你說我怎么就攤上這事¢涣耍” “怎么了在讶?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長霜大。 經(jīng)常有香客問我构哺,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任曙强,我火速辦了婚禮残拐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘碟嘴。我一直安慰自己溪食,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布娜扇。 她就那樣靜靜地躺著错沃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪雀瓢。 梳的紋絲不亂的頭發(fā)上枢析,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音刃麸,去河邊找鬼登疗。 笑死,一個(gè)胖子當(dāng)著我的面吹牛嫌蚤,可吹牛的內(nèi)容都是我干的辐益。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼脱吱,長吁一口氣:“原來是場噩夢啊……” “哼智政!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起箱蝠,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤续捂,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后宦搬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體牙瓢,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年间校,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了矾克。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡憔足,死狀恐怖胁附,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情滓彰,我是刑警寧澤控妻,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站揭绑,受9級(jí)特大地震影響弓候,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一菇存、第九天 我趴在偏房一處隱蔽的房頂上張望彰居。 院中可真熱鬧,春花似錦撰筷、人聲如沸陈惰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽抬闯。三九已至,卻和暖如春关筒,著一層夾襖步出監(jiān)牢的瞬間溶握,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來泰國打工蒸播, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留睡榆,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓袍榆,卻偏偏與公主長得像胀屿,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子包雀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容