JAVA程序设计:一篇文章教你完整写出贪吃蛇小游戏 您所在的位置:网站首页 小黄色的蛇长什么样子 JAVA程序设计:一篇文章教你完整写出贪吃蛇小游戏

JAVA程序设计:一篇文章教你完整写出贪吃蛇小游戏

2024-06-24 03:23| 来源: 网络整理| 查看: 265

1 运行展示

2 设计思路

        设计一个贪吃蛇游戏,我们应当遵循了一系列步骤来确保游戏的基本功能:蛇的移动、吃苹果、游戏结束判断、以及重新开始游戏。以下是设计思路的分步总结.

        1. 初始化游戏界面 使用Swing组件:利用JFrame和JPanel创建游戏窗口和绘图面板。设置游戏参数:定义蛇的大小、游戏区域的大小、苹果的位置等参数。初始化游戏状态:设置蛇的初始长度、位置、移动方向等。         2. 游戏逻辑实现 蛇的移动:通过数组记录蛇身体每一部分的位置,并在每次移动时更新这些位置。吃苹果:检测蛇头和苹果的位置,若重合则增加蛇的长度,并重新放置苹果。碰撞检测:检查蛇头是否触碰到边界或自身,若是,则游戏结束。         3. 绘制游戏界面 重写paintComponent方法:使用Graphics对象绘制蛇、苹果和游戏结束时的提示信息。使用计时器:javax.swing.Timer用于控制游戏的更新频率,每个时间间隔都会重绘界面并更新游戏状态。         4. 控制游戏 键盘监听:实现KeyListener接口,根据用户的按键输入改变蛇的移动方向。暂停功能:通过监听特定的按键(如P键)来实现游戏的暂停和继续。         5. 重新开始游戏 添加按钮:在游戏面板中添加一个重新开始的按钮。事件监听:为按钮添加ActionListener,在游戏结束时显示按钮,并在点击时重置游戏状态。 3 技术列举 使用到的Java概念 面向对象编程:通过类和对象来模拟游戏中的实体(如蛇、苹果)和行为(如移动、吃苹果)。事件驱动编程:使用事件监听器来响应用户的输入(键盘事件)和交互(按钮点击事件)。图形用户界面(GUI):使用Java Swing库来创建和管理窗口、按钮、绘图等GUI组件。多线程和并发:使用计时器(Timer)来控制游戏逻辑的周期性执行,这涉及到Java的并发编程。 4 核心功能实现思路

          在贪吃蛇游戏中,最主要的两个功能是蛇的移动和游戏状态的管理(包括吃苹果和碰撞检测)。这两个功能是游戏运行的核心,决定了游戏的基本玩法和用户体验。

        1. 蛇的移动

       蛇的移动是贪吃蛇游戏的基础。玩家通过控制蛇的移动来吃苹果,游戏的乐趣和挑战性主要来自于如何控制蛇的移动路径和速度。

实现思路:

数据结构:使用两个数组分别存储蛇身体每一部分的x和y坐标。蛇头是数组的第一个元素,蛇尾是最后一个元素。移动逻辑:在每个时间间隔,根据蛇的当前移动方向更新蛇头的位置,然后让蛇身体的每一部分移动到前一部分的位置,实现蛇的整体移动。方向控制:通过监听键盘事件,允许玩家改变蛇的移动方向,但不能让蛇直接反向移动。         2. 游戏状态的管理

        游戏状态的管理决定了游戏的进程和结束条件。它包括检测蛇是否吃到苹果以增长身体,以及蛇是否撞到自己或游戏边界导致游戏结束。

实现思路:

吃苹果: 检测碰撞:在蛇移动后,检查蛇头的位置是否与苹果的位置重合。如果是,表示蛇吃到了苹果。增长蛇身:增加蛇的长度,并在游戏区域内随机生成一个新的苹果位置。碰撞检测: 边界检测:检查蛇头是否移动出游戏区域的边界。如果是,游戏结束。自身碰撞检测:检查蛇头是否与蛇身的其他部分位置重合。如果是,同样游戏结束。游戏结束处理:当游戏结束时,停止游戏循环,可能显示游戏结束的信息,并提供重新开始游戏的选项。

        这两个功能的实现是构建一个可玩的贪吃蛇游戏的关键。它们不仅涉及到游戏的基本逻辑和用户交互,还需要考虑如何在界面上有效地反映游戏状态的变化,提供流畅和有趣的游戏体验。

5 核心功能代码实现         1. 蛇的移动 private void move() { for (int z = dots; z > 0; z--) { x[z] = x[(z - 1)]; y[z] = y[(z - 1)]; } if (leftDirection) { x[0] -= DOT_SIZE; } if (rightDirection) { x[0] += DOT_SIZE; } if (upDirection) { y[0] -= DOT_SIZE; } if (downDirection) { y[0] += DOT_SIZE; } }         2. 游戏状态的管理                  1 吃苹果方法 private void checkApple() { if ((x[0] == apple_x) && (y[0] == apple_y)) { dots++; locateApple(); } }                 2 碰撞检测方法 private void checkCollision() { for (int z = dots; z > 0; z--) { if ((z > 4) && (x[0] == x[z]) && (y[0] == y[z])) { inGame = false; } } if (y[0] >= HEIGHT) { inGame = false; } if (y[0] < 0) { inGame = false; } if (x[0] >= WIDTH) { inGame = false; } if (x[0] < 0) { inGame = false; } if (!inGame) { timer.stop(); } } 6 全部代码实现 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.ArrayList; import java.util.Collections; import java.util.Random; public class SnakeGame extends JPanel implements KeyListener, ActionListener { private final int WIDTH = 300; private final int HEIGHT = 300; private final int DOT_SIZE = 10; private final int ALL_DOTS = 900; private final int RANDOM_POSITION = 29; private final int DELAY = 140; private final int x[] = new int[ALL_DOTS]; private final int y[] = new int[ALL_DOTS]; // 在SnakeGame类中添加 private JButton restartButton; private int dots; private int apple_x; private int apple_y; private boolean leftDirection = false; private boolean rightDirection = true; private boolean upDirection = false; private boolean downDirection = false; private boolean inGame = true; private boolean paused = false; private Timer timer; private Random random; private ArrayList highScores = new ArrayList(); public SnakeGame() { initBoard(); } private void initBoard() { restartButton = new JButton("Restart"); restartButton.setBounds(WIDTH / 2 - 50, HEIGHT / 2, 100, 30); restartButton.addActionListener(this); restartButton.setFocusable(false); restartButton.setVisible(false); // 初始时不显示按钮 this.add(restartButton); addKeyListener(this); setBackground(Color.black); setFocusable(true); setPreferredSize(new Dimension(WIDTH, HEIGHT)); initGame(); } private void initGame() { dots = 3; for (int z = 0; z < dots; z++) { x[z] = 50 - z * 10; y[z] = 50; } locateApple(); timer = new Timer(DELAY, this); timer.start(); } private void restartGame() { dots = 3; for (int z = 0; z < dots; z++) { x[z] = 50 - z * 10; y[z] = 50; } rightDirection = true; leftDirection = false; upDirection = false; downDirection = false; inGame = true; restartButton.setVisible(false); // 重置游戏时隐藏按钮 timer.start(); // 重新开始计时 locateApple(); // 重新放置苹果 } public void paintComponent(Graphics g) { super.paintComponent(g); doDrawing(g); } private void doDrawing(Graphics g) { if (inGame) { g.setColor(Color.red); g.fillOval(apple_x, apple_y, DOT_SIZE, DOT_SIZE); for (int z = 0; z < dots; z++) { if (z == 0) { g.setColor(Color.green); g.fillRect(x[z], y[z], DOT_SIZE, DOT_SIZE); } else { g.setColor(new Color(45, 180, 0)); g.fillRect(x[z], y[z], DOT_SIZE, DOT_SIZE); } } Toolkit.getDefaultToolkit().sync(); } else { gameOver(g); } } private void gameOver(Graphics g) { String msg = "Game Over"; Font small = new Font("Helvetica", Font.BOLD, 14); FontMetrics metr = getFontMetrics(small); g.setColor(Color.white); g.setFont(small); g.drawString(msg, (WIDTH - metr.stringWidth(msg)) / 2, HEIGHT / 2); checkHighScore(); displayHighScores(g); restartButton.setVisible(true); // 显示重新开始按钮 } private void checkHighScore() { highScores.add(dots); Collections.sort(highScores, Collections.reverseOrder()); while (highScores.size() > 3) { highScores.remove(highScores.size() - 1); } } private void displayHighScores(Graphics g) { g.drawString("High Scores:", 100, HEIGHT / 2 + 50); for (int i = 0; i < highScores.size(); i++) { g.drawString((i + 1) + ". " + highScores.get(i), 100, HEIGHT / 2 + 65 + i * 15); } } private void checkApple() { if ((x[0] == apple_x) && (y[0] == apple_y)) { dots++; locateApple(); } } private void move() { for (int z = dots; z > 0; z--) { x[z] = x[(z - 1)]; y[z] = y[(z - 1)]; } if (leftDirection) { x[0] -= DOT_SIZE; } if (rightDirection) { x[0] += DOT_SIZE; } if (upDirection) { y[0] -= DOT_SIZE; } if (downDirection) { y[0] += DOT_SIZE; } } private void checkCollision() { for (int z = dots; z > 0; z--) { if ((z > 4) && (x[0] == x[z]) && (y[0] == y[z])) { inGame = false; } } if (y[0] >= HEIGHT) { inGame = false; } if (y[0] < 0) { inGame = false; } if (x[0] >= WIDTH) { inGame = false; } if (x[0] < 0) { inGame = false; } if (!inGame) { timer.stop(); } } private void locateApple() { int r = (int) (Math.random() * RANDOM_POSITION); apple_x = ((r * DOT_SIZE)); r = (int) (Math.random() * RANDOM_POSITION); apple_y = ((r * DOT_SIZE)); } @Override public void actionPerformed(ActionEvent e) { if (inGame) { checkApple(); checkCollision(); move(); } else if (e.getSource() == restartButton) { restartGame(); } repaint(); } @Override public void keyPressed(KeyEvent e) { int key = e.getKeyCode(); if ((key == KeyEvent.VK_LEFT) && (!rightDirection)) { leftDirection = true; upDirection = false; downDirection = false; } if ((key == KeyEvent.VK_RIGHT) && (!leftDirection)) { rightDirection = true; upDirection = false; downDirection = false; } if ((key == KeyEvent.VK_UP) && (!downDirection)) { upDirection = true; rightDirection = false; leftDirection = false; } if ((key == KeyEvent.VK_DOWN) && (!upDirection)) { downDirection = true; rightDirection = false; leftDirection = false; } if (key == KeyEvent.VK_P) { paused = !paused; if (paused) { timer.stop(); } else { timer.start(); } } } @Override public void keyReleased(KeyEvent e) { } @Override public void keyTyped(KeyEvent e) { } public static void main(String[] args) { SwingUtilities.invokeLater(() -> { JFrame frame = new JFrame("Snake Game"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new SnakeGame()); frame.pack(); frame.setResizable(false); frame.setVisible(true); frame.setLocationRelativeTo(null); }); } } 7 总结

        本文提供了一个贪吃蛇游戏的完整Java实现,包括游戏设计思路、关键功能的实现方法、以及完整的代码。游戏使用Java Swing库构建图形用户界面,通过面向对象编程、事件驱动编程、图形用户界面(GUI)设计、以及多线程和并发控制,实现了一个基本但功能完整的贪吃蛇游戏。游戏的核心功能包括蛇的移动、吃苹果、碰撞检测、游戏状态管理、以及游戏的重新开始功能。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有