01.入门篇-体验AI编程
1 体验AI编程
1.1 案例需求
需求:利用AI开发一款贪吃蛇小游戏
1.2 描述信息
你是一个经验丰富的Java工程师。 请利用Java的GUI开发一个像素风格的贪吃蛇游戏,要求: - 用方向键控制蛇的移动方向 - 蛇头和蛇身体采用不同颜色 - 每当蛇吃到苹果则蛇身长度加1,积分加1 - 顶部显示用户当前得分 - 蛇头碰到墙壁或自己身体则游戏结束 - 游戏结束后可以退出游戏或重新开始游戏 项目基础包为com.itheima,请设计合理的项目结构,不要把所有代码写在一个包。要给出每一个类及类中详细完整的代码。
1.3 项目结构
com.itheima ├── SnakeGame.java // 主类:启动程序 ├── controller │ └── GameController.java // 控制游戏逻辑(方向、更新、碰撞等) ├── model │ ├── Direction.java // 枚举:方向 │ ├── GameStatus.java // 枚举:游戏状态 │ ├── Point.java // 自定义坐标点(避免与 java.awt.Point 冲突) │ └── Snake.java // 蛇的数据模型 ├── view │ └── GamePanel.java // 游戏主面板(绘制 + 键盘监听) └── util └── Constants.java // 常量配置(格子大小、速度、颜色等)
com.itheima/SnakeGame.java
package com.itheima; import javax.swing.*; public class SnakeGame { public static void main(String[] args) { SwingUtilities.invokeLater(() -> { JFrame frame = new JFrame("像素贪吃蛇 - by Itheima"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setResizable(false); frame.add(new com.itheima.view.GamePanel()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); }); } }
com.itheima/model/Direction.java
package com.itheima.model; public enum Direction { UP, DOWN, LEFT, RIGHT }
com.itheima/model/GameStatus.java
package com.itheima.model; public enum GameStatus { RUNNING, GAME_OVER }
com.itheima/model/Point.java
package com.itheima.model; public class Point { public final int x; public final int y; public Point(int x, int y) { this.x = x; this.y = y; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; Point point = (Point) obj; return x == point.x && y == point.y; } @Override public int hashCode() { return Integer.hashCode(x) * 31 + Integer.hashCode(y); } }
com.itheima/model/Snake.java
package com.itheima.model; import java.util.*; public class Snake { private final LinkedList<Point> body; private Direction direction; public Snake() { body = new LinkedList<>(); // 初始长度为3 body.add(new Point(10, 10)); body.add(new Point(9, 10)); body.add(new Point(8, 10)); direction = Direction.RIGHT; } public void move(Point newHead, boolean grow) { body.addFirst(newHead); if (!grow) { body.removeLast(); } } public Point getHead() { return body.getFirst(); } public List<Point> getBody() { return new ArrayList<>(body); } public Direction getDirection() { return direction; } public void setDirection(Direction direction) { this.direction = direction; } public boolean contains(Point p) { return body.contains(p); } public int getLength() { return body.size(); } }
com.itheima/util/Constants.java
package com.itheima.util; import java.awt.Color; public class Constants { public static final int GRID_SIZE = 20; // 每个格子像素大小 public static final int ROWS = 20; // 行数 public static final int COLS = 20; // 列数 public static final int DELAY = 150; // 游戏刷新间隔(毫秒) public static final Color SNAKE_HEAD_COLOR = Color.GREEN; public static final Color SNAKE_BODY_COLOR = Color.CYAN; public static final Color APPLE_COLOR = Color.RED; public static final Color BACKGROUND_COLOR = Color.BLACK; public static final Color TEXT_COLOR = Color.WHITE; }
com.itheima/controller/GameController.java
package com.itheima.controller; import com.itheima.model.*; import com.itheima.util.Constants; import java.util.Random; public class GameController { private Snake snake; private Point apple; private int score; private GameStatus status; private final Random random = new Random(); public GameController() { reset(); } public void reset() { snake = new Snake(); score = 0; status = GameStatus.RUNNING; generateApple(); } public void update() { if (status != GameStatus.RUNNING) return; Point head = snake.getHead(); Point newHead = getNextHead(head); // 检查是否撞墙 if (newHead.x < 0 || newHead.x >= Constants.COLS || newHead.y < 0 || newHead.y >= Constants.ROWS) { status = GameStatus.GAME_OVER; return; } // 检查是否撞自己 if (snake.contains(newHead)) { status = GameStatus.GAME_OVER; return; } boolean ateApple = newHead.equals(apple); snake.move(newHead, ateApple); if (ateApple) { score++; generateApple(); } } private Point getNextHead(Point head) { int x = head.x; int y = head.y; switch (snake.getDirection()) { case UP: y--; break; case DOWN: y++; break; case LEFT: x--; break; case RIGHT: x++; break; } return new Point(x, y); } private void generateApple() { while (true) { int x = random.nextInt(Constants.COLS); int y = random.nextInt(Constants.ROWS); Point candidate = new Point(x, y); if (!snake.contains(candidate)) { apple = candidate; break; } } } public Snake getSnake() { return snake; } public Point getApple() { return apple; } public int getScore() { return score; } public GameStatus getStatus() { return status; } public void setDirection(Direction dir) { if (status != GameStatus.RUNNING) return; Direction current = snake.getDirection(); // 防止反向移动(如正在右,不能直接左) if ((current == Direction.LEFT && dir == Direction.RIGHT) || (current == Direction.RIGHT && dir == Direction.LEFT) || (current == Direction.UP && dir == Direction.DOWN) || (current == Direction.DOWN && dir == Direction.UP)) { return; } snake.setDirection(dir); } }
com.itheima/view/GamePanel.java
package com.itheima.view; import com.itheima.controller.GameController; import com.itheima.model.Direction; import com.itheima.model.GameStatus; import com.itheima.model.Point; import com.itheima.model.Snake; import com.itheima.util.Constants; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; public class GamePanel extends JPanel implements ActionListener { private final GameController controller; private final Timer timer; public GamePanel() { this.controller = new GameController(); setPreferredSize(new Dimension( Constants.COLS * Constants.GRID_SIZE, Constants.ROWS * Constants.GRID_SIZE + 30)); // +30 给分数留空间 setBackground(Constants.BACKGROUND_COLOR); setFocusable(true); addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { switch (e.getKeyCode()) { case KeyEvent.VK_UP: controller.setDirection(Direction.UP); break; case KeyEvent.VK_DOWN: controller.setDirection(Direction.DOWN); break; case KeyEvent.VK_LEFT: controller.setDirection(Direction.LEFT); break; case KeyEvent.VK_RIGHT: controller.setDirection(Direction.RIGHT); break; case KeyEvent.VK_R: if (controller.getStatus() == GameStatus.GAME_OVER) { controller.reset(); } break; case KeyEvent.VK_ESCAPE: System.exit(0); break; } } }); timer = new Timer(Constants.DELAY, this); timer.start(); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); drawScore(g); if (controller.getStatus() == GameStatus.GAME_OVER) { drawGameOver(g); return; } drawSnake(g); drawApple(g); } private void drawScore(Graphics g) { // 设置中文字体 Font font = new Font("SimHei", Font.BOLD, 16); // 确保使用支持中文的字体 g.setFont(font); // 获取分数字符串 String scoreText = "得分: " + controller.getScore(); // 假设 this 是你的 JComponent 或 JPanel 子类实例 int frameWidth = this.getWidth(); // 获取组件宽度 // 设置分数行背景颜色为黄色 g.setColor(Color.YELLOW); // 计算需要填充的矩形区域的高度 FontMetrics fm = g.getFontMetrics(); int textHeight = fm.getHeight(); // 填充背景色,宽度设置为整个组件的宽度 g.fillRect(0, 0, frameWidth, textHeight); // 使用组件宽度作为背景宽度 // 重置颜色为文本颜色 g.setColor(Color.BLACK); // 绘制文本 int textX = 10; // 文本起始点x坐标,可以根据需求调整 int textY = textHeight - fm.getDescent(); // 文本基线y坐标 g.drawString(scoreText, textX, textY); } private void drawSnake(Graphics g) { Snake snake = controller.getSnake(); boolean isFirst = true; for (Point p : snake.getBody()) { if (isFirst) { g.setColor(Constants.SNAKE_HEAD_COLOR); isFirst = false; } else { g.setColor(Constants.SNAKE_BODY_COLOR); } g.fillRect(p.x * Constants.GRID_SIZE, p.y * Constants.GRID_SIZE + 30, Constants.GRID_SIZE, Constants.GRID_SIZE); } } private void drawApple(Graphics g) { g.setColor(Constants.APPLE_COLOR); Point apple = controller.getApple(); g.fillRect(apple.x * Constants.GRID_SIZE, apple.y * Constants.GRID_SIZE + 30, Constants.GRID_SIZE, Constants.GRID_SIZE); } private void drawGameOver(Graphics g) { // 使用中文字体 Font titleFont = new Font("SimHei", Font.BOLD, 24); Font hintFont = new Font("SimHei", Font.PLAIN, 16); g.setColor(Color.RED); g.setFont(titleFont); String msg = "游戏结束!得分: " + controller.getScore(); FontMetrics fm = g.getFontMetrics(); int x = (getWidth() - fm.stringWidth(msg)) / 2; int y = (getHeight() - 30) / 2; g.drawString(msg, x, y); g.setFont(hintFont); String hint = "按 R 重新开始,ESC 退出"; fm = g.getFontMetrics(); x = (getWidth() - fm.stringWidth(hint)) / 2; y += 30; g.drawString(hint, x, y); } @Override public void actionPerformed(ActionEvent e) { controller.update(); repaint(); } }
1.4 AI时代程序开发的变化
人工时代:
1.有思路 知道下一步做什么,有编程思维
2.会输入 会自己写代码实现思路,需要熟练使用API
3.能看懂 能看懂代码,甄别错误,看懂异常信息
AI 时代: 驾驭智能工具的能力 (1).培养编程思维、(2).甄别代码的能力
1.会思考 有一定的编程思维,询问AI获取解决思路
2.会提问 知道如何询问AI(写好提示词)
3.能看懂 能看懂AI生成的代码,甄别错误
———————————————————————————————————————————————————————————————————————————
无敌小马爱学习
浙公网安备 33010602011771号