
贪吃蛇游戏看似简单,却包含了 Java 编程的核心知识点:GUI 编程、事件处理、数据结构、线程控制等。通过开发这个小游戏,你不仅能掌握 Swing 框架的使用,更能理解面向对象编程的精髓。本文将带你一步步实现一个可运行的贪吃蛇游戏,从需求分析到代码实现,再到功能扩展,全程干货满满。
贪吃蛇游戏主要包含以下核心要素:
我们采用 MVC 模式设计这款游戏,将游戏分为三个核心模块:


创建pom.xml文件,添加必要的依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.game</groupId>
<artifactId>snake-game</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<lombok.version>1.18.30</lombok.version>
<spring.version>6.1.8</spring.version>
<fastjson2.version>2.0.47</fastjson2.version>
<guava.version>33.2.1-jre</guava.version>
</properties>
<dependencies>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<!-- Spring Core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- FastJson2 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>${fastjson2.version}</version>
</dependency>
<!-- Guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.game.snake.SnakeGame</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
首先创建一个表示位置坐标的类,用于记录蛇身和食物的位置:
package com.game.snake.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 位置坐标类,用于表示游戏元素在面板上的位置
*
* @author ken
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Position {
/**
* x坐标
*/
private int x;
/**
* y坐标
*/
private int y;
/**
* 判断两个位置是否相同
*
* @param other 另一个位置对象
* @return 如果坐标相同则返回true,否则返回false
*/
@Override
public boolean equals(Object other) {
if (this == other) return true;
if (other == null || getClass() != other.getClass()) return false;
Position position = (Position) other;
return x == position.x && y == position.y;
}
/**
* 计算哈希值
*
* @return 哈希值
*/
@Override
public int hashCode() {
return 31 * x + y;
}
}
蛇是游戏的核心元素,我们需要设计一个类来表示蛇的属性和行为:
package com.game.snake.model;
import com.google.common.collect.Lists;
import lombok.Getter;
import lombok.Setter;
import org.springframework.util.CollectionUtils;
import java.util.List;
/**
* 蛇对象类,包含蛇的属性和行为
*
* @author ken
*/
@Getter
@Setter
public class Snake {
/**
* 蛇身由一系列坐标点组成,头部在列表的第一个位置
*/
private List<Position> body;
/**
* 蛇的移动方向:上、下、左、右
*/
private Direction direction;
/**
* 蛇的移动方向枚举
*/
public enum Direction {
UP, DOWN, LEFT, RIGHT
}
/**
* 初始化蛇对象
*
* @param initialX 初始X坐标
* @param initialY 初始Y坐标
* @param length 初始长度
* @param initialDirection 初始方向
*/
public Snake(int initialX, int initialY, int length, Direction initialDirection) {
body = Lists.newArrayList();
// 初始化蛇身
for (int i = 0; i < length; i++) {
switch (initialDirection) {
case RIGHT:
body.add(new Position(initialX - i, initialY));
break;
case LEFT:
body.add(new Position(initialX + i, initialY));
break;
case DOWN:
body.add(new Position(initialX, initialY - i));
break;
case UP:
body.add(new Position(initialX, initialY + i));
break;
}
}
this.direction = initialDirection;
}
/**
* 移动蛇,根据当前方向计算新的头部位置,并添加到蛇身
*
* @return 新的头部位置
*/
public Position move() {
if (CollectionUtils.isEmpty(body)) {
return null;
}
// 获取当前头部位置
Position head = body.get(0);
Position newHead = new Position(head.getX(), head.getY());
// 根据方向计算新的头部位置
switch (direction) {
case UP:
newHead.setY(head.getY() - 1);
break;
case DOWN:
newHead.setY(head.getY() + 1);
break;
case LEFT:
newHead.setX(head.getX() - 1);
break;
case RIGHT:
newHead.setX(head.getX() + 1);
break;
}
// 将新头部添加到蛇身的最前面
body.add(0, newHead);
return newHead;
}
/**
* 移除蛇的尾部,当蛇没有吃到食物时调用
*/
public void removeTail() {
if (!CollectionUtils.isEmpty(body)) {
body.remove(body.size() - 1);
}
}
/**
* 检查蛇是否撞到了自己
*
* @return 如果撞到自己返回true,否则返回false
*/
public boolean isCollidedWithSelf() {
if (CollectionUtils.isEmpty(body) || body.size() <= 1) {
return false;
}
Position head = body.get(0);
// 检查头部是否与身体其他部分碰撞
for (int i = 1; i < body.size(); i++) {
if (head.equals(body.get(i))) {
return true;
}
}
return false;
}
/**
* 改变蛇的移动方向,但不能直接反向移动
*
* @param newDirection 新的方向
*/
public void changeDirection(Direction newDirection) {
// 防止蛇直接反向移动(例如从向上直接变为向下)
if ((direction == Direction.UP && newDirection != Direction.DOWN) ||
(direction == Direction.DOWN && newDirection != Direction.UP) ||
(direction == Direction.LEFT && newDirection != Direction.RIGHT) ||
(direction == Direction.RIGHT && newDirection != Direction.LEFT)) {
this.direction = newDirection;
}
}
}
食物是蛇的目标,被蛇吃掉后会增加分数并让蛇变长:
package com.game.snake.model;
import lombok.Data;
import java.util.Random;
/**
* 食物对象类,包含食物的属性和行为
*
* @author ken
*/
@Data
public class Food {
/**
* 食物的位置
*/
private Position position;
/**
* 食物的分数值
*/
private int scoreValue;
/**
* 随机数生成器
*/
private static final Random random = new Random();
/**
* 初始化食物对象
*
* @param maxX X坐标最大值(不包含)
* @param maxY Y坐标最大值(不包含)
*/
public Food(int maxX, int maxY) {
this.scoreValue = 10; // 默认每个食物10分
generateNewPosition(maxX, maxY);
}
/**
* 生成新的食物位置,确保不在蛇身上
*
* @param maxX X坐标最大值(不包含)
* @param maxY Y坐标最大值(不包含)
* @param snakeBody 蛇的身体
*/
public void generateNewPosition(int maxX, int maxY, Snake snake) {
Position newPosition;
do {
newPosition = generateNewPosition(maxX, maxY);
} while (snake.getBody().contains(newPosition)); // 确保食物不会出现在蛇身上
this.position = newPosition;
}
/**
* 生成新的食物位置
*
* @param maxX X坐标最大值(不包含)
* @param maxY Y坐标最大值(不包含)
* @return 新的食物位置
*/
private Position generateNewPosition(int maxX, int maxY) {
int x = random.nextInt(maxX);
int y = random.nextInt(maxY);
return new Position(x, y);
}
}
游戏状态类用于管理整个游戏的状态,包括分数、游戏是否结束等:
package com.game.snake.model;
import lombok.Getter;
import lombok.Setter;
/**
* 游戏状态类,管理游戏的整体状态
*
* @author ken
*/
@Getter
@Setter
public class GameState {
/**
* 当前分数
*/
private int score;
/**
* 游戏是否正在运行
*/
private boolean isRunning;
/**
* 游戏是否结束
*/
private boolean isGameOver;
/**
* 游戏区域的宽度(以格子为单位)
*/
private final int gridWidth;
/**
* 游戏区域的高度(以格子为单位)
*/
private final int gridHeight;
/**
* 格子的大小(像素)
*/
private final int gridSize;
/**
* 初始化游戏状态
*
* @param gridWidth 游戏区域宽度(格子)
* @param gridHeight 游戏区域高度(格子)
* @param gridSize 格子大小(像素)
*/
public GameState(int gridWidth, int gridHeight, int gridSize) {
this.gridWidth = gridWidth;
this.gridHeight = gridHeight;
this.gridSize = gridSize;
this.score = 0;
this.isRunning = false;
this.isGameOver = false;
}
/**
* 增加分数
*
* @param points 要增加的分数
*/
public void addScore(int points) {
this.score += points;
}
/**
* 重置游戏状态
*/
public void reset() {
this.score = 0;
this.isRunning = false;
this.isGameOver = false;
}
/**
* 检查位置是否超出游戏边界
*
* @param position 要检查的位置
* @return 如果超出边界返回true,否则返回false
*/
public boolean isOutOfBounds(Position position) {
return position.getX() < 0 || position.getX() >= gridWidth ||
position.getY() < 0 || position.getY() >= gridHeight;
}
}
游戏面板是显示游戏元素的主要区域,负责绘制蛇、食物等元素:
package com.game.snake.view;
import com.game.snake.model.Food;
import com.game.snake.model.GameState;
import com.game.snake.model.Position;
import com.game.snake.model.Snake;
import lombok.Setter;
import org.springframework.util.ObjectUtils;
import javax.swing.*;
import java.awt.*;
/**
* 游戏面板类,负责绘制游戏元素
*
* @author ken
*/
@Setter
public class GamePanel extends JPanel {
/**
* 游戏状态
*/
private GameState gameState;
/**
* 蛇对象
*/
private Snake snake;
/**
* 食物对象
*/
private Food food;
/**
* 初始化游戏面板
*
* @param gameState 游戏状态
*/
public GamePanel(GameState gameState) {
this.gameState = gameState;
// 设置面板大小
int panelWidth = gameState.getGridWidth() * gameState.getGridSize();
int panelHeight = gameState.getGridHeight() * gameState.getGridSize();
setPreferredSize(new Dimension(panelWidth, panelHeight));
// 设置背景色
setBackground(Color.BLACK);
}
/**
* 重写绘制方法,绘制游戏元素
*
* @param g 绘图对象
*/
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// 绘制网格线(可选)
drawGrid(g);
// 如果游戏对象已初始化,则绘制它们
if (!ObjectUtils.isEmpty(snake) && !ObjectUtils.isEmpty(food) && !ObjectUtils.isEmpty(gameState)) {
drawSnake(g);
drawFood(g);
}
// 如果游戏结束,显示游戏结束信息
if (gameState.isGameOver()) {
drawGameOver(g);
} else if (!gameState.isRunning()) {
// 如果游戏未开始,显示开始信息
drawStartMessage(g);
}
}
/**
* 绘制蛇
*
* @param g 绘图对象
*/
private void drawSnake(Graphics g) {
// 绘制蛇身
for (int i = 1; i < snake.getBody().size(); i++) {
Position segment = snake.getBody().get(i);
drawGridCell(g, segment, Color.GREEN);
}
// 绘制蛇头(与身体颜色不同)
if (!snake.getBody().isEmpty()) {
Position head = snake.getBody().get(0);
drawGridCell(g, head, Color.RED);
}
}
/**
* 绘制食物
*
* @param g 绘图对象
*/
private void drawFood(Graphics g) {
drawGridCell(g, food.getPosition(), Color.YELLOW);
}
/**
* 绘制单个网格单元
*
* @param g 绘图对象
* @param position 位置
* @param color 颜色
*/
private void drawGridCell(Graphics g, Position position, Color color) {
int x = position.getX() * gameState.getGridSize();
int y = position.getY() * gameState.getGridSize();
int size = gameState.getGridSize();
g.setColor(color);
g.fillRect(x, y, size, size);
// 绘制边框,使格子更清晰
g.setColor(Color.BLACK);
g.drawRect(x, y, size, size);
}
/**
* 绘制网格线
*
* @param g 绘图对象
*/
private void drawGrid(Graphics g) {
g.setColor(new Color(40, 40, 40)); // 深色网格线,不影响游戏视觉
int gridSize = gameState.getGridSize();
int width = getWidth();
int height = getHeight();
// 绘制水平线
for (int y = 0; y <= height; y += gridSize) {
g.drawLine(0, y, width, y);
}
// 绘制垂直线
for (int x = 0; x <= width; x += gridSize) {
g.drawLine(x, 0, x, height);
}
}
/**
* 绘制游戏结束信息
*
* @param g 绘图对象
*/
private void drawGameOver(Graphics g) {
String message = "游戏结束!得分: " + gameState.getScore() + " 按空格键重新开始";
drawCenteredMessage(g, message, Color.RED, getHeight() / 2);
}
/**
* 绘制开始游戏信息
*
* @param g 绘图对象
*/
private void drawStartMessage(Graphics g) {
String message = "按空格键开始游戏";
drawCenteredMessage(g, message, Color.WHITE, getHeight() / 2);
}
/**
* 在面板中央绘制文本信息
*
* @param g 绘图对象
* @param message 要显示的消息
* @param color 文本颜色
* @param y Y坐标
*/
private void drawCenteredMessage(Graphics g, String message, Color color, int y) {
g.setColor(color);
g.setFont(new Font("Arial", Font.BOLD, 20));
FontMetrics metrics = g.getFontMetrics();
int x = (getWidth() - metrics.stringWidth(message)) / 2;
g.drawString(message, x, y);
}
}
分数面板用于显示当前游戏的分数:
package com.game.snake.view;
import com.game.snake.model.GameState;
import lombok.Setter;
import javax.swing.*;
import java.awt.*;
/**
* 分数面板类,显示游戏分数
*
* @author ken
*/
@Setter
public class ScorePanel extends JPanel {
/**
* 游戏状态
*/
private GameState gameState;
/**
* 初始化分数面板
*/
public ScorePanel() {
setBackground(Color.DARK_GRAY);
setPreferredSize(new Dimension(0, 30)); // 高度固定为30像素,宽度自适应
}
/**
* 重写绘制方法,显示分数
*
* @param g 绘图对象
*/
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (gameState != null) {
g.setColor(Color.WHITE);
g.setFont(new Font("Arial", Font.PLAIN, 16));
String scoreText = "分数: " + gameState.getScore();
g.drawString(scoreText, 10, 20);
}
}
}
主窗口类用于组合各个面板,形成完整的游戏界面:
package com.game.snake.view;
import com.game.snake.controller.GameController;
import com.game.snake.model.GameState;
import lombok.Getter;
import javax.swing.*;
import java.awt.*;
/**
* 游戏主窗口类
*
* @author ken
*/
@Getter
public class GameFrame extends JFrame {
/**
* 游戏面板
*/
private final GamePanel gamePanel;
/**
* 分数面板
*/
private final ScorePanel scorePanel;
/**
* 初始化游戏窗口
*
* @param title 窗口标题
* @param gameState 游戏状态
* @param controller 游戏控制器
*/
public GameFrame(String title, GameState gameState, GameController controller) {
super(title);
// 初始化面板
this.gamePanel = new GamePanel(gameState);
this.scorePanel = new ScorePanel();
// 设置面板的游戏状态引用
this.gamePanel.setGameState(gameState);
this.scorePanel.setGameState(gameState);
// 配置窗口
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
// 添加键盘监听器
addKeyListener(controller);
// 布局管理
setLayout(new BorderLayout());
add(scorePanel, BorderLayout.NORTH);
add(gamePanel, BorderLayout.CENTER);
// 调整窗口大小以适应内容
pack();
// 窗口居中显示
setLocationRelativeTo(null);
}
}
游戏控制器是连接模型和视图的桥梁,负责处理用户输入和游戏逻辑:
package com.game.snake.controller;
import com.game.snake.model.Food;
import com.game.snake.model.GameState;
import com.game.snake.model.Position;
import com.game.snake.model.Snake;
import com.game.snake.view.GameFrame;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
/**
* 游戏控制器类,处理用户输入和游戏逻辑
*
* @author ken
*/
@Slf4j
public class GameController extends KeyAdapter {
/**
* 游戏状态
*/
private final GameState gameState;
/**
* 蛇对象
*/
private Snake snake;
/**
* 食物对象
*/
private Food food;
/**
* 游戏窗口
*/
private final GameFrame gameFrame;
/**
* 游戏线程
*/
private Thread gameThread;
/**
* 游戏速度(毫秒),值越小速度越快
*/
private int gameSpeed = 150;
/**
* 初始化游戏控制器
*
* @param gameState 游戏状态
* @param gameFrame 游戏窗口
*/
public GameController(GameState gameState, GameFrame gameFrame) {
this.gameState = gameState;
this.gameFrame = gameFrame;
// 初始化游戏对象
initGameObjects();
// 将游戏对象设置到视图
gameFrame.getGamePanel().setSnake(snake);
gameFrame.getGamePanel().setFood(food);
}
/**
* 初始化游戏对象
*/
private void initGameObjects() {
// 初始化蛇,从中间位置开始,初始长度为3,初始方向向右
int startX = gameState.getGridWidth() / 2;
int startY = gameState.getGridHeight() / 2;
this.snake = new Snake(startX, startY, 3, Snake.Direction.RIGHT);
// 初始化食物
this.food = new Food(gameState.getGridWidth(), gameState.getGridHeight());
// 确保食物不会出现在蛇身上
this.food.generateNewPosition(gameState.getGridWidth(), gameState.getGridHeight(), snake);
}
/**
* 处理键盘事件
*
* @param e 键盘事件
*/
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
// 空格键控制游戏开始/重新开始
if (keyCode == KeyEvent.VK_SPACE) {
if (gameState.isGameOver()) {
// 游戏结束时,重新开始
restartGame();
} else if (!gameState.isRunning()) {
// 游戏未运行时,开始游戏
startGame();
}
return;
}
// 仅在游戏运行时处理方向键
if (!gameState.isRunning() || gameState.isGameOver()) {
return;
}
// 处理方向键
switch (keyCode) {
case KeyEvent.VK_UP:
snake.changeDirection(Snake.Direction.UP);
break;
case KeyEvent.VK_DOWN:
snake.changeDirection(Snake.Direction.DOWN);
break;
case KeyEvent.VK_LEFT:
snake.changeDirection(Snake.Direction.LEFT);
break;
case KeyEvent.VK_RIGHT:
snake.changeDirection(Snake.Direction.RIGHT);
break;
case KeyEvent.VK_P:
// 暂停/继续游戏
togglePause();
break;
}
}
/**
* 开始游戏
*/
public void startGame() {
if (gameState.isRunning()) {
return;
}
log.info("游戏开始");
gameState.setRunning(true);
gameState.setGameOver(false);
// 创建并启动游戏线程
gameThread = new Thread(this::gameLoop);
gameThread.start();
}
/**
* 重新开始游戏
*/
public void restartGame() {
log.info("游戏重新开始");
// 停止当前游戏线程
if (gameThread != null && gameThread.isAlive()) {
gameState.setRunning(false);
try {
gameThread.join();
} catch (InterruptedException e) {
log.error("游戏线程中断异常", e);
Thread.currentThread().interrupt();
}
}
// 重置游戏状态和对象
gameState.reset();
initGameObjects();
// 更新视图
gameFrame.getGamePanel().setSnake(snake);
gameFrame.getGamePanel().setFood(food);
// 开始新游戏
startGame();
}
/**
* 暂停/继续游戏
*/
public void togglePause() {
if (gameState.isGameOver()) {
return;
}
gameState.setRunning(!gameState.isRunning());
if (gameState.isRunning()) {
log.info("游戏继续");
gameThread = new Thread(this::gameLoop);
gameThread.start();
} else {
log.info("游戏暂停");
if (gameThread != null && gameThread.isAlive()) {
gameThread.interrupt();
}
}
gameFrame.getGamePanel().repaint();
}
/**
* 游戏主循环
*/
private void gameLoop() {
while (gameState.isRunning() && !gameState.isGameOver()) {
try {
// 控制游戏速度
Thread.sleep(gameSpeed);
// 移动蛇
Position newHead = snake.move();
// 检查是否撞到边界
if (ObjectUtils.isEmpty(newHead) || gameState.isOutOfBounds(newHead)) {
gameOver();
break;
}
// 检查是否撞到自己
if (snake.isCollidedWithSelf()) {
gameOver();
break;
}
// 检查是否吃到食物
if (newHead.equals(food.getPosition())) {
// 增加分数
gameState.addScore(food.getScoreValue());
log.info("吃到食物,当前分数: {}", gameState.getScore());
// 生成新食物
food.generateNewPosition(gameState.getGridWidth(), gameState.getGridHeight(), snake);
// 随着分数增加,提高游戏难度(加快速度)
increaseDifficulty();
} else {
// 没有吃到食物,移除尾部
snake.removeTail();
}
// 重绘游戏界面
gameFrame.getGamePanel().repaint();
gameFrame.getScorePanel().repaint();
} catch (InterruptedException e) {
// 捕获中断异常,通常是暂停游戏时
Thread.currentThread().interrupt();
break;
}
}
}
/**
* 增加游戏难度(加快速度)
*/
private void increaseDifficulty() {
// 每得100分,加快一点速度,但有最低限制
if (gameSpeed > 50) {
int newSpeed = gameSpeed - (gameState.getScore() / 100) * 5;
gameSpeed = Math.max(newSpeed, 50);
}
}
/**
* 游戏结束处理
*/
private void gameOver() {
log.info("游戏结束,最终分数: {}", gameState.getScore());
gameState.setRunning(false);
gameState.setGameOver(true);
gameFrame.getGamePanel().repaint();
}
}
主程序入口类用于初始化并启动游戏:
package com.game.snake;
import com.game.snake.controller.GameController;
import com.game.snake.model.GameState;
import com.game.snake.view.GameFrame;
import lombok.extern.slf4j.Slf4j;
import javax.swing.*;
/**
* 贪吃蛇游戏主类
*
* @author ken
*/
@Slf4j
public class SnakeGame {
/**
* 游戏网格宽度(格子数量)
*/
private static final int GRID_WIDTH = 30;
/**
* 游戏网格高度(格子数量)
*/
private static final int GRID_HEIGHT = 20;
/**
* 每个格子的大小(像素)
*/
private static final int GRID_SIZE = 25;
/**
* 主方法,程序入口
*
* @param args 命令行参数
*/
public static void main(String[] args) {
log.info("贪吃蛇游戏启动");
// 在EDT(事件调度线程)中创建和显示GUI组件
SwingUtilities.invokeLater(() -> {
try {
// 初始化游戏状态
GameState gameState = new GameState(GRID_WIDTH, GRID_HEIGHT, GRID_SIZE);
// 创建游戏控制器(临时为null,后面会设置)
GameController controller = new GameController(gameState, null);
// 创建游戏窗口
GameFrame gameFrame = new GameFrame("Java贪吃蛇游戏", gameState, controller);
// 完成控制器的初始化
controller.setGameFrame(gameFrame);
// 显示窗口
gameFrame.setVisible(true);
log.info("游戏窗口创建成功");
} catch (Exception e) {
log.error("游戏初始化失败", e);
JOptionPane.showMessageDialog(null, "游戏初始化失败: " + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
}
});
}
}
注意:需要在GameController类中添加gameFrame的 setter 方法:
/**
* 设置游戏窗口
*
* @param gameFrame 游戏窗口
*/
public void setGameFrame(GameFrame gameFrame) {
this.gameFrame = gameFrame;
}
使用 Maven 命令编译打包,启动main方法启动游戏:
mvn clean package
通过本文的学习,你已经掌握了使用 Java 开发贪吃蛇游戏的全过程。这个项目虽然简单,但涵盖了 Java 编程的多个重要知识点:
希望这个项目能帮助你巩固 Java 基础知识,并激发你对游戏开发的兴趣。你可以基于这个基础版本,继续扩展功能,打造属于自己的贪吃蛇游戏。
示例中藏了一个小bug, 需要可运行完整代码的联系我哈。
以下是游戏截图:

