Java实现贪吃蛇游戏

简介: 本文介绍了如何使用Java实现一个简单的贪吃蛇游戏。

 目录

一、项目结构

二、实现步骤

1. 创建 Snake 类

2. 创建 Food 类

3. 创建 GameBoard 类

4. 创建 SnakeGame 类

三、总结

贪吃蛇是一个经典的电子游戏,它的玩法非常简单,但又充满了挑战。玩家通过控制蛇的移动,吃到食物并不断成长,目标是尽可能长时间生存。本文将介绍如何使用 Java 实现一个简单的贪吃蛇游戏。我们将重点展示游戏的核心实现,包括蛇的移动、碰撞检测、食物生成等功能。

一、项目结构

本项目将使用 Java 的图形用户界面库 javax.swing 来创建界面,利用 KeyListener 监听键盘输入。整体的项目结构如下:

- SnakeGame.java        // 游戏主程序,启动游戏窗口
- GameBoard.java        // 游戏面板,包含游戏逻辑和绘制
- Snake.java            // 贪吃蛇类,控制蛇的移动和行为
- Food.java             // 食物类,用于生成和管理食物

image.gif

二、实现步骤

1. 创建 Snake 类

首先,我们创建 Snake 类来控制贪吃蛇的行为。蛇是由一系列的方块构成,每个方块可以看作是一个 Point 对象,代表蛇的身体部位。

import java.awt.Point;
import java.util.LinkedList;
public class Snake {
    private LinkedList<Point> body;
    private int direction; // 方向 0 - 上, 1 - 右, 2 - 下, 3 - 左
    private boolean growing; // 是否在增长
    public Snake(int startX, int startY) {
        body = new LinkedList<>();
        body.add(new Point(startX, startY));
        direction = 1; // 初始方向向右
        growing = false;
    }
    // 获取蛇的身体
    public LinkedList<Point> getBody() {
        return body;
    }
    // 获取蛇的头部
    public Point getHead() {
        return body.getFirst();
    }
    // 控制蛇的移动
    public void move() {
        Point head = getHead();
        Point newHead = null;
        // 根据方向移动蛇头
        switch (direction) {
            case 0: newHead = new Point(head.x, head.y - 1); break; // 向上
            case 1: newHead = new Point(head.x + 1, head.y); break; // 向右
            case 2: newHead = new Point(head.x, head.y + 1); break; // 向下
            case 3: newHead = new Point(head.x - 1, head.y); break; // 向左
        }
        // 向蛇的身体前端添加新头部
        body.addFirst(newHead);
        if (!growing) {
            // 如果没有增长,移除尾部
            body.removeLast();
        } else {
            // 如果正在增长,保持尾部不变
            growing = false;
        }
    }
    // 蛇吃到食物后增长
    public void grow() {
        growing = true;
    }
    // 检查蛇是否与自己相撞
    public boolean hasCollided() {
        Point head = getHead();
        for (int i = 1; i < body.size(); i++) {
            if (head.equals(body.get(i))) {
                return true;
            }
        }
        return false;
    }
    // 检查蛇是否撞墙
    public boolean hasHitWall(int width, int height) {
        Point head = getHead();
        return head.x < 0 || head.x >= width || head.y < 0 || head.y >= height;
    }
    // 改变蛇的方向
    public void setDirection(int newDirection) {
        // 防止蛇直接掉头
        if (Math.abs(direction - newDirection) != 2) {
            direction = newDirection;
        }
    }
}

image.gif

2. 创建 Food 类

Food 类用于表示游戏中的食物。每次蛇吃到食物后,食物都会重新出现在一个随机的位置。

import java.awt.Point;
import java.util.Random;
public class Food {
    private Point position;
    public Food(int width, int height) {
        // 随机生成食物的位置
        Random rand = new Random();
        position = new Point(rand.nextInt(width), rand.nextInt(height));
    }
    // 获取食物的位置
    public Point getPosition() {
        return position;
    }
    // 重置食物的位置
    public void relocate(int width, int height) {
        Random rand = new Random();
        position.setLocation(rand.nextInt(width), rand.nextInt(height));
    }
}

image.gif

3. 创建 GameBoard 类

GameBoard 类是游戏的核心,负责管理游戏状态、更新界面和处理游戏逻辑。

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.LinkedList;
public class GameBoard extends JPanel {
    private Snake snake;
    private Food food;
    private boolean gameOver;
    private int score;
    private int boardWidth = 30;
    private int boardHeight = 20;
    private final int tileSize = 20;
    public GameBoard() {
        snake = new Snake(5, 5);
        food = new Food(boardWidth, boardHeight);
        score = 0;
        gameOver = false;
        // 设置键盘监听
        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (gameOver) return;
                int keyCode = e.getKeyCode();
                if (keyCode == KeyEvent.VK_UP) {
                    snake.setDirection(0);
                } else if (keyCode == KeyEvent.VK_RIGHT) {
                    snake.setDirection(1);
                } else if (keyCode == KeyEvent.VK_DOWN) {
                    snake.setDirection(2);
                } else if (keyCode == KeyEvent.VK_LEFT) {
                    snake.setDirection(3);
                }
            }
        });
        setFocusable(true);
    }
    // 更新游戏状态
    public void update() {
        if (gameOver) return;
        // 移动蛇
        snake.move();
        // 检查蛇是否撞墙或自咬
        if (snake.hasHitWall(boardWidth, boardHeight) || snake.hasCollided()) {
            gameOver = true;
            return;
        }
        // 检查蛇是否吃到食物
        if (snake.getHead().equals(food.getPosition())) {
            snake.grow();
            score++;
            food.relocate(boardWidth, boardHeight);
        }
        repaint();
    }
    // 绘制游戏界面
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        // 绘制游戏边界
        g.setColor(Color.BLACK);
        g.fillRect(0, 0, boardWidth * tileSize, boardHeight * tileSize);
        // 绘制蛇
        g.setColor(Color.GREEN);
        for (Point p : snake.getBody()) {
            g.fillRect(p.x * tileSize, p.y * tileSize, tileSize, tileSize);
        }
        // 绘制食物
        g.setColor(Color.RED);
        g.fillRect(food.getPosition().x * tileSize, food.getPosition().y * tileSize, tileSize, tileSize);
        // 绘制游戏状态
        if (gameOver) {
            g.setColor(Color.WHITE);
            g.setFont(new Font("Arial", Font.BOLD, 30));
            g.drawString("Game Over! Score: " + score, 50, boardHeight * tileSize / 2);
        }
    }
}

image.gif

4. 创建 SnakeGame 类

SnakeGame 类负责启动游戏窗口,并启动游戏的主循环。

import javax.swing.*;
public class SnakeGame {
    public static void main(String[] args) {
        JFrame frame = new JFrame("贪吃蛇");
        GameBoard gameBoard = new GameBoard();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(gameBoard.getPreferredSize());
        frame.add(gameBoard);
        frame.setVisible(true);
        // 游戏主循环
        while (true) {
            gameBoard.update();
            try {
                Thread.sleep(100); // 控制游戏速度
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

image.gif

三、总结

通过上述代码,我们成功实现了一个简单的贪吃蛇游戏。这个实现涵盖了游戏的基本逻辑,包括蛇的控制、食物的生成、碰撞检测和游戏结束条件。你可以在此基础上进一步扩展功能,比如增加难度设置、得分排行榜、音效和动画等。

贪吃蛇不仅是一个有趣的游戏,也是学习编程的一项经典练习。通过实现这个项目,你可以深入理解 Java 图形界面编程、事件处理以及基本的面向对象设计思想。

希望这篇文章能够帮助你实现自己的贪吃蛇游戏,也欢迎在评论区分享你的修改和优化建议!

相关文章
|
29天前
|
IDE Java API
Java游戏开发基础:从零开始制作一个简单的2D游戏
本文介绍了使用Java开发一个简单的2D避障游戏的基础流程。
73 10
|
8月前
|
前端开发 JavaScript Java
计算机Java项目|java游戏账号交易系统
计算机Java项目|java游戏账号交易系统
计算机Java项目|java游戏账号交易系统
|
7月前
|
Java 索引
Java实现扑克牌游戏 | 随机发牌 ( 过程拆分详解+完整代码 )
Java实现扑克牌游戏 | 随机发牌 ( 过程拆分详解+完整代码 )
158 3
|
4月前
|
开发框架 IDE Java
java制作游戏,如何使用libgdx,入门级别教学
本文是一篇入门级教程,介绍了如何使用libgdx游戏开发框架创建一个简单的游戏项目,包括访问libgdx官网、设置项目、下载项目生成工具,并在IDE中运行生成的项目。
119 1
java制作游戏,如何使用libgdx,入门级别教学
|
6月前
|
人工智能 算法 Java
LeetCode经典算法题:井字游戏+优势洗牌+Dota2参议院java解法
LeetCode经典算法题:井字游戏+优势洗牌+Dota2参议院java解法
68 1
|
8月前
|
前端开发 JavaScript Java
计算机Java项目|游戏美术外包管理信息系统
计算机Java项目|游戏美术外包管理信息系统
|
8月前
|
算法 JavaScript 前端开发
【经典算法】LCR187:破冰游戏(约瑟夫问题,Java/C/Python3/JavaScript实现含注释说明,Easy)
【经典算法】LCR187:破冰游戏(约瑟夫问题,Java/C/Python3/JavaScript实现含注释说明,Easy)
111 1
|
8月前
|
Java
使用java编写猜数字游戏
使用java编写猜数字游戏
|
8月前
|
Java
Java 实现 贪吃蛇 小游戏【附源码】
Java 实现 贪吃蛇 小游戏【附源码】
62 0
|
3天前
|
Java 程序员 开发者
Java社招面试题:一个线程运行时发生异常会怎样?
大家好,我是小米。今天分享一个经典的 Java 面试题:线程运行时发生异常,程序会怎样处理?此问题考察 Java 线程和异常处理机制的理解。线程发生异常,默认会导致线程终止,但可以通过 try-catch 捕获并处理,避免影响其他线程。未捕获的异常可通过 Thread.UncaughtExceptionHandler 处理。线程池中的异常会被自动处理,不影响任务执行。希望这篇文章能帮助你深入理解 Java 线程异常处理机制,为面试做好准备。如果你觉得有帮助,欢迎收藏、转发!
39 14