JAVA贪吃蛇

在这篇博客中,我们将深入探讨如何使用Java编程语言实现经典的贪吃蛇游戏。通过这次实践,您将体验到从零开始构建一个完整游戏的过程,提升您的编程能力和对面向对象设计的理解。

一、项目概述

贪吃蛇是一款经典的街机游戏,玩家控制一条蛇在屏幕上移动,吃掉食物以增长身体长度,同时避免撞墙或撞到自己。在本项目中,我们将使用Java的Swing库来构建图形用户界面,并实现游戏的核心逻辑。

二、开发环境

  • 编程语言:Java
  • 开发工具:IntelliJ IDEA
  • JDK版本:1.8

三、项目结构

本项目主要包含以下几个类:

  1. SnakeGame:游戏主类,负责初始化游戏窗口和启动游戏。
  2. GamePanel:游戏面板类,负责绘制游戏界面和处理用户输入。
  3. Snake:蛇类,包含蛇的属性和行为。
  4. Food:食物类,负责生成食物的位置。

四、实现步骤

  1. 创建游戏窗口

    首先,我们需要创建一个继承自JPanelGamePanel类,用于绘制游戏界面。在paintComponent方法中,我们将绘制蛇和食物。

    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.KeyAdapter;
    import java.awt.event.KeyEvent;
    import java.util.LinkedList;
    import java.util.Random;
    
    public class GamePanel extends JPanel {
        private static final int CELL_SIZE = 20;
        private static final int GRID_WIDTH = 20;
        private static final int GRID_HEIGHT = 20;
        private static final int GAME_SPEED = 150;
    
        private LinkedList<Point> snake;
        private Point food;
        private int direction;
        private boolean isMoving;
        private boolean isGameOver;
    
        public GamePanel() {
            setPreferredSize(new Dimension(CELL_SIZE * GRID_WIDTH, CELL_SIZE * GRID_HEIGHT));
            setBackground(Color.BLACK);
            setFocusable(true);
    
            addKeyListener(new KeyAdapter() {
                @Override
                public void keyPressed(KeyEvent e) {
                    int key = e.getKeyCode();
                    if ((key == KeyEvent.VK_LEFT) && (direction != 1)) direction = 0;
                    if ((key == KeyEvent.VK_RIGHT) && (direction != 0)) direction = 1;
                    if ((key == KeyEvent.VK_UP) && (direction != 3)) direction = 2;
                    if ((key == KeyEvent.VK_DOWN) && (direction != 2)) direction = 3;
                }
            });
    
            snake = new LinkedList<>();
            generateFood();
            isMoving = true;
            isGameOver = false;
    
            Timer timer = new Timer(GAME_SPEED, e -> {
                if (isMoving && !isGameOver) {
                    move();
                    checkCollision();
                    repaint();
                }
            });
            timer.start();
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (isGameOver) {
                g.setColor(Color.WHITE);
                g.setFont(new Font("SansSerif", Font.BOLD, 30));
                g.drawString("Game Over!", CELL_SIZE * 5, CELL_SIZE * 10);
            } else {
                // 绘制食物
                g.setColor(Color.RED);
                g.fillRect(food.x * CELL_SIZE, food.y * CELL_SIZE, CELL_SIZE, CELL_SIZE);
    
                // 绘制蛇
                g.setColor(Color.GREEN);
                for (Point p : snake) {
                    g.fillRect(p.x * CELL_SIZE, p.y * CELL_SIZE, CELL_SIZE, CELL_SIZE);
                }
            }
        }
    
        private void generateFood() {
            Random rand = new Random();
            int x, y;
            do {
                x = rand.nextInt(GRID_WIDTH);
                y = rand.nextInt(GRID_HEIGHT);
            } while (snake.contains(new Point(x, y)));
            food = new Point(x, y);
        }
    
        private void move() {
            Point head = snake.peekFirst();
            Point newHead;
            switch (direction) {
                case 0:
                    newHead = new Point(head.x - 1, head.y);
                    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, head.y + 1);
                    break;
                default:
                    newHead = head;
            }
    
            snake.addFirst(newHead);
    
            if (newHead.equals(food)) {
                generateFood();
            } else {
                snake.removeLast();
            }
        }
    
        private void checkCollision() {
            if (snake.size() == GRID_WIDTH * GRID_HEIGHT) {
                isMoving = false;
                isGameOver = true;
            }
    
            Point head = snake.peekFirst();
            if (head.x < 0 || head.x >= GRID_WIDTH || head.y < 0 || head.y >= GRID_HEIGHT) {
                isMoving = false;
                isGameOver = true;
            }
    
            if (snake.size() > 1 && snake.contains(head)) {
                isMoving = false;
                isGameOver = true;
            }
        }
    }
    

    创建游戏主类

    接下来,我们创建一个SnakeGame类,负责初始化游戏窗口和启动游戏。在main方法中,我们创建一个JFrame,并将GamePanel添加到其中。

    import javax.swing.*;
    
    public class SnakeGame {
        public static void main(String[] args) {
            JFrame frame = new JFrame("贪吃蛇游戏");
            GamePanel gamePanel = new GamePanel();
            frame.add(gamePanel);
            frame.pack();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    }
    

    五、运行结果

    运行上述代码后,您将看到一个窗口,显示一个黑色的游戏区域。您可以使用键盘的方向键控制蛇的移动,目标是吃掉红色的食物,避免撞墙或撞到自己。当游戏结束时,屏幕上会显示“Game Over!”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值