Java贪吃蛇小游戏
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.LinkedList;
import java.util.Random;public class SnakeGame extends JFrame implements ActionListener, KeyListener {private static final long serialVersionUID = 1L;// 游戏区域的格子数和每个格子的大小private static final int GRID_SIZE = 20;private static final int CELL_SIZE = 20;// 蛇的坐标集合,食物的坐标,蛇的移动方向,计时器private LinkedList<Point> snake;private Point food;private char direction;private Timer timer;// 游戏窗口的构造函数public SnakeGame() {setTitle("Snake Game"); // 设置窗口标题setSize(GRID_SIZE * CELL_SIZE, GRID_SIZE * CELL_SIZE); // 设置窗口大小setResizable(false); // 设置窗口不可调整大小setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置默认关闭操作setLocationRelativeTo(null); // 设置窗口居中显示// 初始化蛇的起始位置,方向为向右snake = new LinkedList<>();snake.add(new Point(GRID_SIZE / 2, GRID_SIZE / 2));direction = 'R';// 生成初始食物spawnFood();// 设置计时器,用于触发蛇的移动timer = new Timer(100, this);timer.start();// 添加键盘事件监听器addKeyListener(this);setFocusable(true);}// 生成食物的方法public void spawnFood() {Random rand = new Random();int x = rand.nextInt(GRID_SIZE);int y = rand.nextInt(GRID_SIZE);food = new Point(x, y);// 确保食物不会生成在蛇的身体上while (snake.contains(food)) {x = rand.nextInt(GRID_SIZE);y = rand.nextInt(GRID_SIZE);food.setLocation(x, y);}}// 移动蛇的方法public void move() {Point head = snake.getFirst();Point newHead = new Point(head);switch (direction) {case 'U':newHead.translate(0, -1);break;case 'D':newHead.translate(0, 1);break;case 'L':newHead.translate(-1, 0);break;case 'R':newHead.translate(1, 0);break;}// 检查碰撞if (newHead.equals(food)) {snake.addFirst(food);spawnFood();} else {snake.addFirst(newHead);// 如果蛇没吃到食物,则移除尾部,否则保持尾部snake.removeLast();}// 检查蛇是否撞到自己if (snake.size() > 1 && snake.subList(1, snake.size()).contains(newHead)) {gameOver();}// 检查蛇是否撞到墙壁if (newHead.x < 0 || newHead.x >= GRID_SIZE || newHead.y < 0 || newHead.y >= GRID_SIZE) {gameOver();}}// 游戏结束的方法public void gameOver() {timer.stop();JOptionPane.showMessageDialog(this, "Game Over", "Game Over", JOptionPane.INFORMATION_MESSAGE);System.exit(0);}// 画图的方法,用于绘制蛇、食物和网格public void paint(Graphics g) {super.paint(g);// 绘制蛇g.setColor(Color.GREEN);for (Point point : snake) {g.fillRect(point.x * CELL_SIZE, point.y * CELL_SIZE, CELL_SIZE, CELL_SIZE);}// 绘制食物g.setColor(Color.RED);g.fillRect(food.x * CELL_SIZE, food.y * CELL_SIZE, CELL_SIZE, CELL_SIZE);// 绘制网格线g.setColor(Color.BLACK);for (int i = 0; i < GRID_SIZE; i++) {g.drawLine(i * CELL_SIZE, 0, i * CELL_SIZE, GRID_SIZE * CELL_SIZE);g.drawLine(0, i * CELL_SIZE, GRID_SIZE * CELL_SIZE, i * CELL_SIZE);}}// 主函数,创建SnakeGame对象并显示窗口public static void main(String[] args) {SwingUtilities.invokeLater(() -> {SnakeGame game = new SnakeGame();game.setVisible(true);});}// 计时器触发的事件处理@Overridepublic void actionPerformed(ActionEvent e) {move();repaint();}// 键盘按下事件处理@Overridepublic void keyPressed(KeyEvent e) {switch (e.getKeyCode()) {case KeyEvent.VK_UP:if (direction != 'D') direction = 'U';break;case KeyEvent.VK_DOWN:if (direction != 'U') direction = 'D';break;case KeyEvent.VK_LEFT:if (direction != 'R') direction = 'L';break;case KeyEvent.VK_RIGHT:if (direction != 'L') direction = 'R';break;}}// 未使用的键盘事件处理方法@Overridepublic void keyTyped(KeyEvent e) {}// 未使用的键盘事件处理方法@Overridepublic void keyReleased(KeyEvent e) {}
}