华为od统一考试B卷【贪吃蛇】C++ 实现

这篇博客详细介绍了如何使用C++实现华为OD统一考试中贪吃蛇游戏的模拟,包括游戏规则、移动逻辑以及碰撞检测。文章讨论了题目的复杂性和需要考虑的多种边界情况,提供了一种解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

          所有题目均有五种语言实现。C实现目录C++ 实现目录Python实现目录Java实现目录JavaScript实现目录

题目

贪吃蛇是一个经典游戏,蛇的身体由若干方格连接而成,身体随蛇头移动。蛇头触碰到食物时,蛇的长度会增加一格。

蛇头和身体的任一方格或者游戏版图边界碰撞时,游戏结束。

下面让我们来完成贪吃蛇游戏的模拟。

给定一个N*M的数组arr,代表N*M个方格组成的版图,贪吃蛇每次移动一个方格。

若arr[i][j] == ‘H’,表示该方格为贪吃蛇的起始位置;

若arr[i][j] == ‘F’,表示该方格为食物,

若arr[i][j] == ‘E’,表示该方格为空格。

贪吃蛇初始长度为1,初始移动方向为向左。

为给定一系列贪吃蛇的移动操作,返回操作后蛇的长度,如果在操作执行完之前已经游戏结束,返回游戏结束时蛇的长度。

贪吃蛇移动、吃食物和碰撞处理的细节见下面图示:

图1:截取了贪吃蛇移动的一个中间状态,H表示蛇头,F表示食物,数字为蛇身体各节的编号,蛇为向左移动,此时蛇头和食物已经相邻

图2:蛇头向左移动一格,蛇头和食物重叠,注意此时食物的格子成为了新的蛇头,第1节身体移动到蛇头位置,第2节身体移动到第1节身体位置,以此类推,

最后添加第4节身体到原来第3节身体的位置。

图3:蛇头继续向左移动一格,身体的各节按上述规则移动,此时蛇头已经和边界相邻,但还未碰撞。

图4:蛇头继续向左移动一格,此时蛇头已经超过边界,发生碰撞,游戏结束。

图5和图6给出一个蛇头和身体碰撞的例子,蛇为向上移动。

图5时

### 华为OD贪吃蛇游戏Java实现方案 #### 游戏概述 华为OD中的“贪吃蛇”是一个典型的编程挑战,旨在评估候选人的算法设计能力和编码技巧。该游戏的核心目标是通过键盘控制蛇的方向,在不撞墙或自身体的情况下尽可能多地获取食物以提高分数[^1]。 #### 设计思路 在Java中实现贪吃蛇游戏的关键在于合理的设计架构和清晰的逻辑划分。以下是几个核心模块及其功能说明: 1. **地图管理**:利用二维数组表示游戏区域。 2. **蛇体操作**:使用`ArrayList`存储蛇的身体坐标,并动态更新其位置。 3. **食物生成**:随生成食物的位置,确保不在蛇身上。 4. **用户输入处理**:监听用户的按键事件来改变蛇的移动方向。 5. **碰撞检测**:检查蛇是否撞到墙壁或其他部分。 #### 实现细节 下面展示了一个简化版的Java实现代码片段: ```java import java.awt.*; import javax.swing.*; import java.util.Random; import java.util.ArrayList; public class SnakeGame extends JFrame { private final int WIDTH = 300; // 地图宽度 private final int HEIGHT = 300; // 地图高度 private final int DOT_SIZE = 10; // 每格大小 private final int ALL_DOTS = WIDTH * HEIGHT / (DOT_SIZE * DOT_SIZE); private final int RAND_POS = 29; private final int DELAY = 140; private ArrayList<Point> snakeDots = new ArrayList<>(); private Point applePosition = null; private boolean leftDirection = false; private boolean rightDirection = true; private boolean upDirection = false; private boolean downDirection = false; private boolean inGame = true; private Timer timer; public SnakeGame() { initUI(); initializeSnakeAndApple(); addKeyListener(new TAdapter()); setFocusable(true); startGameLoop(); } private void initUI() { setTitle("Greedy Snake"); setSize(WIDTH, HEIGHT); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBackground(Color.BLACK); setLocationRelativeTo(null); setVisible(true); } private void initializeSnakeAndApple() { Random rand = new Random(); for(int i=0;i<3;i++) { snakeDots.add(new Point(i*DOT_SIZE,DOT_SIZE)); } applePosition = new Point(rand.nextInt(RAND_POS)*DOT_SIZE, rand.nextInt(RAND_POS)*DOT_SIZE); while(snakeDots.contains(applePosition)) { applePosition.setLocation( rand.nextInt(RAND_POS)*DOT_SIZE, rand.nextInt(RAND_POS)*DOT_SIZE ); } } private void move() { Point head = snakeDots.get(0); if(leftDirection){ head.x -= DOT_SIZE; }else if(rightDirection){ head.x += DOT_SIZE; }else if(upDirection){ head.y -= DOT_SIZE; }else if(downDirection){ head.y += DOT_SIZE; } checkCollision(head); if(inGame){ snakeDots.remove(snakeDots.size()-1); snakeDots.add(0,new Point(head)); repaint(); } } private void checkCollision(Point head) { if((head.x < 0)||(head.x >=WIDTH)|| (head.y < 0)||(head.y >=HEIGHT)){ gameOver(); } if(snakeDots.subList(1,snakeDots.size()).contains(head)){ gameOver(); } if(head.equals(applePosition)){ snakeDots.add(new Point(-1,-1)); // 延长蛇身 generateNewAppleLocation(); } } private void generateNewAppleLocation(){ Random rand = new Random(); do{ applePosition.setLocation( rand.nextInt(RAND_POS)*DOT_SIZE, rand.nextInt(RAND_POS)*DOT_SIZE ); }while(snakeDots.contains(applePosition)); } private void gameOver(){ inGame=false; JOptionPane.showMessageDialog(this,"Game Over!"); System.exit(0); } @Override public void paint(Graphics g){ super.paint(g); Graphics2D g2d=(Graphics2D)g; if(!inGame){ return ; } g.setColor(Color.RED); g.fillOval(applePosition.x,applePosition.y,DOT_SIZE,DOT_SIZE); g.setColor(Color.GREEN); for(Point p : snakeDots){ g.fillRect(p.x,p.y,DOT_SIZE,DOT_SIZE); } Toolkit.getDefaultToolkit().sync(); } private void startGameLoop(){ timer=new Timer(DELAY,this::actionPerformed); timer.start(); } protected void actionPerformed(java.awt.event.ActionEvent evt){ if(inGame){ move(); } } public static void main(String[] args) { SwingUtilities.invokeLater(SnakeGame::new); } } ``` 上述代码展示了如何构建一个基本版本的贪吃蛇游戏,涵盖了从界面绘制到逻辑控制的主要方面[^2]。 --- #### 关键技术点解析 - **数据结构的选择**: `ArrayList<Point>`用于保存蛇的所有节点位置,便于后续的操作如删除尾巴、添加头部等动作。 - **定时器制**: 使用`javax.swing.Timer`按照固定间隔触发游戏帧刷新,从而驱动整个游戏流程。 - **边界与自身碰撞检测**: 在每次移动后立即执行碰撞检测,一旦发现问题即刻结束游戏并提示玩家失败原因[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MISAYAONE

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值