From 84f19cd43479517a8ec75017fcc346b4fab3afac Mon Sep 17 00:00:00 2001 From: pckgyexw2 <255701148@qq.com> Date: Sat, 15 Mar 2025 23:29:10 +0800 Subject: [PATCH] ADD file via upload --- src/SnakeGame.java | 258 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 258 insertions(+) create mode 100644 src/SnakeGame.java diff --git a/src/SnakeGame.java b/src/SnakeGame.java new file mode 100644 index 0000000..ac6124f --- /dev/null +++ b/src/SnakeGame.java @@ -0,0 +1,258 @@ +package tanchishe; +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.List; +import java.util.Random; + +public class SnakeGame extends JFrame { + + // 主界面 + private JPanel mainPanel; + private JButton startButton; + private JComboBox difficultyComboBox; + private JComboBox modeComboBox; + + // 游戏界面 + private GamePanel gamePanel; + + public SnakeGame() { + setTitle("贪吃蛇游戏"); + setSize(600, 600); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setLocationRelativeTo(null); + + // 初始化主界面 + initMainPanel(); + add(mainPanel); + setVisible(true); + } + + private void initMainPanel() { + mainPanel = new JPanel(); + mainPanel.setLayout(new GridLayout(3, 1)); + + // 难度选择 + JPanel difficultyPanel = new JPanel(); + difficultyPanel.add(new JLabel("选择难度:")); + String[] difficulties = {"简单", "困难", "地狱"}; + difficultyComboBox = new JComboBox<>(difficulties); + difficultyPanel.add(difficultyComboBox); + mainPanel.add(difficultyPanel); + + // 模式选择 + JPanel modePanel = new JPanel(); + modePanel.add(new JLabel("选择模式:")); + String[] modes = {"穿墙模式", "撞墙模式"}; + modeComboBox = new JComboBox<>(modes); + modePanel.add(modeComboBox); + mainPanel.add(modePanel); + + // 开始按钮 + startButton = new JButton("开始游戏"); + startButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + // 获取用户选择的难度和模式 + String difficulty = (String) difficultyComboBox.getSelectedItem(); + String mode = (String) modeComboBox.getSelectedItem(); + + // 切换到游戏界面 + mainPanel.setVisible(false); + gamePanel = new GamePanel(difficulty, mode); + add(gamePanel); + gamePanel.setVisible(true); + gamePanel.requestFocus(); // 让游戏面板获取焦点,以便接收键盘事件 + } + }); + mainPanel.add(startButton); + } + + public static void main(String[] args) { + new SnakeGame(); + } +} + +class GamePanel extends JPanel implements KeyListener, Runnable { + private static final int WIDTH = 600; + private static final int HEIGHT = 600; + private static final int UNIT_SIZE = 20; + private static final int GAME_UNITS = (WIDTH * HEIGHT) / (UNIT_SIZE * UNIT_SIZE); + + private final List snake = new ArrayList<>(); + private Point food; + private int direction = KeyEvent.VK_RIGHT; // 初始方向向右 + private boolean running = false; + private int score = 0; + private int delay; // 控制蛇的移动速度 + private boolean wallCollision; // 是否开启撞墙模式 + + public GamePanel(String difficulty, String mode) { + setPreferredSize(new Dimension(WIDTH, HEIGHT)); + setBackground(Color.BLACK); + setFocusable(true); + addKeyListener(this); + + // 根据难度设置蛇的移动速度 + switch (difficulty) { + case "简单": + delay = 150; + break; + case "困难": + delay = 100; + break; + case "地狱": + delay = 50; + break; + } + + // 根据模式设置是否开启撞墙模式 + wallCollision = mode.equals("撞墙模式"); + + startGame(); + } + + public void startGame() { + snake.clear(); + snake.add(new Point(WIDTH / 2, HEIGHT / 2)); // 初始化蛇的起始位置 + generateFood(); + running = true; + new Thread(this).start(); + } + + public void generateFood() { + Random random = new Random(); + int x = random.nextInt(WIDTH / UNIT_SIZE) * UNIT_SIZE; + int y = random.nextInt(HEIGHT / UNIT_SIZE) * UNIT_SIZE; + food = new Point(x, y); + + // 确保食物不会生成在蛇的身体上 + while (snake.contains(food)) { + x = random.nextInt(WIDTH / UNIT_SIZE) * UNIT_SIZE; + y = random.nextInt(HEIGHT / UNIT_SIZE) * UNIT_SIZE; + food = new Point(x, y); + } + } + + public void move() { + Point head = snake.get(0); + Point newHead = new Point(head); + + switch (direction) { + case KeyEvent.VK_UP: + newHead.y -= UNIT_SIZE; + break; + case KeyEvent.VK_DOWN: + newHead.y += UNIT_SIZE; + break; + case KeyEvent.VK_LEFT: + newHead.x -= UNIT_SIZE; + break; + case KeyEvent.VK_RIGHT: + newHead.x += UNIT_SIZE; + break; + } + + // 穿墙模式:蛇穿过边界从另一侧出现 + if (!wallCollision) { + if (newHead.x < 0) newHead.x = WIDTH - UNIT_SIZE; + if (newHead.x >= WIDTH) newHead.x = 0; + if (newHead.y < 0) newHead.y = HEIGHT - UNIT_SIZE; + if (newHead.y >= HEIGHT) newHead.y = 0; + } + + // 检查是否撞墙(撞墙模式下) + if (wallCollision && (newHead.x < 0 || newHead.x >= WIDTH || newHead.y < 0 || newHead.y >= HEIGHT)) { + running = false; + return; + } + + // 检查是否撞到自己 + if (snake.contains(newHead)) { + running = false; + return; + } + + snake.add(0, newHead); + + // 检查是否吃到食物 + if (newHead.equals(food)) { + score++; + generateFood(); + } else { + snake.remove(snake.size() - 1); // 如果没有吃到食物,移除蛇尾 + } + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + draw(g); + } + + public void draw(Graphics g) { + if (running) { + // 绘制食物 + g.setColor(Color.RED); + g.fillRect(food.x, food.y, UNIT_SIZE, UNIT_SIZE); + + // 绘制蛇 + for (Point p : snake) { + g.setColor(Color.GREEN); + g.fillRect(p.x, p.y, UNIT_SIZE, UNIT_SIZE); + } + + // 绘制分数 + g.setColor(Color.WHITE); + g.setFont(new Font("Arial", Font.BOLD, 20)); + g.drawString("Score: " + score, 10, 20); + } else { + gameOver(g); + } + } + + public void gameOver(Graphics g) { + // 游戏结束界面 + g.setColor(Color.RED); + g.setFont(new Font("Arial", Font.BOLD, 40)); + g.drawString("Game Over", WIDTH / 2 - 100, HEIGHT / 2); + g.setFont(new Font("Arial", Font.BOLD, 20)); + g.drawString("Final Score: " + score, WIDTH / 2 - 80, HEIGHT / 2 + 40); + } + + @Override + public void run() { + while (running) { + move(); + repaint(); + try { + Thread.sleep(delay); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + @Override + public void keyPressed(KeyEvent e) { + int key = e.getKeyCode(); + + // 防止蛇反向移动 + if ((key == KeyEvent.VK_LEFT && direction != KeyEvent.VK_RIGHT) || + (key == KeyEvent.VK_RIGHT && direction != KeyEvent.VK_LEFT) || + (key == KeyEvent.VK_UP && direction != KeyEvent.VK_DOWN) || + (key == KeyEvent.VK_DOWN && direction != KeyEvent.VK_UP)) { + direction = key; + } + } + + @Override + public void keyReleased(KeyEvent e) {} + + @Override + public void keyTyped(KeyEvent e) {} +} \ No newline at end of file