当前位置: 首页 > article >正文

Java实现贪吃蛇游戏

目录

一、项目结构

二、实现步骤

1. 创建 Snake 类

2. 创建 Food 类

3. 创建 GameBoard 类

4. 创建 SnakeGame 类

三、总结

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

一、项目结构

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

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

二、实现步骤

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;
        }
    }
}

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));
    }
}

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);
        }
    }
}

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();
            }
        }
    }
}

三、总结

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

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

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


http://www.kler.cn/a/448036.html

相关文章:

  • Qt之QML应用程序开发:给应用程序添加图标文件
  • 【机器学习与数据挖掘实战】案例04:基于K-Means算法的信用卡高风险客户识别
  • 移动0 - 简单
  • 日本充电桩标准--CHAdeMO介绍
  • linux普通用户使用sudo不需要输密码
  • @PostConstruct注解解释!!!!
  • tslib(触摸屏输入设备的轻量级库)的学习、编译及测试记录
  • 【go每日一题】:并发任务调度器
  • 科技查新对专利申请有什么帮助?
  • 考前倒计时98天
  • 【华为OD-E卷-通信误码 100分(python、java、c++、js、c)】
  • Vue3之性能优化
  • 一起学Git【第二节:创建版本库】
  • Solaris-IPMP配置
  • 概率论得学习和整理30: 用EXCEL 描述泊松分布 poisson distribution
  • 高效准确的PDF解析工具,赋能企业非结构化数据治理
  • 【计算机网络篇】计算机网络期末复习题库详解
  • C语言习题2.0
  • PyCharm 中打印完整的 DataFrame
  • ubuntu 上怎么设置应用开机自动启动
  • 复习打卡大数据篇——Hadoop HDFS 01
  • 全志H618 Android12修改doucmentsui进入后左边动态加载的item
  • BUUCTF Pwn picoctf_2018_rop chain WP
  • Firecrawl教程①:自动化抓取与数据转化,赋能AI应用
  • idea中打补丁包
  • 音视频入门基础:AAC专题(13)——FFmpeg源码中,获取ADTS格式的AAC裸流音频信息的实现