华为OD机试 - 贪吃蛇 - 队列(Python/JS/C/C++ 2024 E卷 200分)

在这里插入图片描述

华为OD机试 2024E卷题库疯狂收录中,刷题点这里

专栏导读

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

一、题目描述

贪吃蛇是一个经典游戏,蛇的身体由若干方格连接而成,身体随着蛇头移动。蛇头触碰到食物时,蛇的长度会增加一格。蛇头和身体的任何一方格或者游戏版图边界碰撞时,游戏结束。

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

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

若 arr[i][j] == ‘H’,表示该方格为贪吃蛇的起始位置;
若 arr[i][j] == ‘F’,表示该方格为食物;
若 arr[i][j] == ‘E’,表示该方格为空格。
贪吃蛇初始长度为 1,初始移动方向为向右。

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

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

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

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

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

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

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

图5时蛇头和第7节身体相邻,但还未碰撞;

图6蛇头向上移动一格,此时蛇头和第8节身体移动到了原来第7节身体的位置,发生碰撞,游戏结束。

二、输入描述

输入第一行为空格分隔的字母,代表贪吃蛇的移动操作。

字母取值为 U、D、L、R 和 G。

U、D、L、R 分别表示贪吃蛇向上、下、左、右移动,转向时贪吃蛇不移动,G 表示贪吃蛇按当前方向移动一格。

用例保证输入操作是正确的。

第二行为空格分隔的两个数,指定 N 和 M,为数组的行和列数。

余下 N 行每行是空格分隔的 M 个字符。字母取值为 H、F 和 E,H 表示贪吃蛇的起始位置,F 表示食物,E 表示该方格为空。

用例保证且只有一个 H 和 F,而 F 绝不会为 G。

三、输出描述

输出一个数字,为蛇的长度。

四、测试用例

测试用例1:

1、输入

D G G
3 3
F F F
F F H
E F E

2、输出

1

3、说明

地图表示为:

蛇头 H (Head)
食物 F (Food)
E 表示该方格为空

四个方向分别表示为:

向上 U (up)
向下 D (down)
向左 L (Left)
向右 R (Right)

测试用例2:

1、输入

R G G
3 3
F E E
H E F
E E E

2、输出

2

3、说明

五、解题思路

在这个问题中,队列是最合适的数据结构,用来存储蛇的身体部分。原因如下:

先进先出(FIFO)特性:蛇的身体是一个顺序结构,蛇头每次移动,新的头部位置加入,而尾部在蛇没有增长时会被移除。队列的先进先出性质刚好满足这个要求。

动态长度:蛇的长度可以根据是否吃到食物而变化,使用队列可以方便地进行头尾的动态增减操作。

  1. 初始化地图:我们首先读取地图的大小,并根据输入填充地图,标记蛇头、食物和空格的位置。
  2. 初始化蛇的状态:蛇最初的长度为1,只有蛇头。我们使用一个队列来存储蛇的身体部分。蛇头的位置记录在队列中。
  3. 移动模拟:
    • 根据输入的移动命令调整蛇的移动方向(U, D, L, R分别代表上下左右,G代表按当前方向移动一格)。
    • 每当蛇头移动时,检查是否越界或者撞到自身。如果发生上述情况,游戏立即结束,输出当前蛇的长度。
    • 如果蛇头移动到食物所在位置,蛇的长度增加,不移除尾巴;否则蛇尾部分会被移除(队列的最前端出队)。
  4. 游戏结束条件:
    • 如果蛇头碰到地图边界,或者与身体的其他部分相撞,游戏结束。
    • 如果蛇完成所有移动,且没有碰到边界或撞到自身,则输出最终蛇的长度。

六、Python算法源码

from collections import deque

# 读取贪吃蛇的操作和地图
def snake_game(moves, N, M, grid):
    # 定义四个方向 U, D, L, R 对应的移动
    directions = {'U': (-1, 0), 'D': (1, 0), 'L': (0, -1), 'R': (0, 1)}
    # 初始化蛇头位置和队列
    snake = deque()  # 使用 deque 模拟队列
    headX, headY = 0, 0  # 初始化蛇头位置

    # 找到蛇头位置
    for i in range(N):
        for j in range(M):
            if grid[i][j] == 'H':
                headX, headY = i, j
                snake.append((i, j))  # 将初始蛇头加入队列

    snake_length = 1  # 蛇的初始长度
    direction = 'R'  # 初始方向为右

    # 执行每一个操作
    for move in moves:
        if move in "UDLR":
            direction = move  # 改变方向
        elif move == 'G':  # 执行移动
            # 根据当前方向获取蛇头新的位置
            dx, dy = directions[direction]
            newX, newY = headX + dx, headY + dy

            # 检查是否越界
            if newX < 0 or newX >= N or newY < 0 or newY >= M:
                return snake_length  # 游戏结束,输出蛇长度

            # 检查是否撞到自己
            if (newX, newY) in snake:
                return snake_length  # 撞到自己,游戏结束

            # 移动蛇头
            if grid[newX][newY] == 'F':  # 吃到食物
                snake_length += 1  # 增加长度
            else:
                snake.popleft()  # 没有吃到食物,移除尾巴

            snake.append((newX, newY))  # 加入新的头部位置
            headX, headY = newX, newY  # 更新蛇头位置

    return snake_length  # 返回最终蛇的长度


# 测试用例1
moves = ['D', 'G', 'G']
N, M = 3, 3
grid = [['F', 'F', 'F'],
        ['F', 'F', 'H'],
        ['E', 'F', 'E']]

print(snake_game(moves, N, M, grid))  # 应该输出 1

七、JavaScript算法源码

function snakeGame(moves, N, M, grid) {
    let directions = { 'U': [-1, 0], 'D': [1, 0], 'L': [0, -1], 'R': [0, 1] };
    let snake = [];  // 用数组模拟队列
    let headX = 0, headY = 0;
    let snakeLength = 1;
    let direction = 'R';  // 初始方向向右

    // 找到蛇头位置
    for (let i = 0; i < N; i++) {
        for (let j = 0; j < M; j++) {
            if (grid[i][j] === 'H') {
                headX = i;
                headY = j;
                snake.push([i, j]);
            }
        }
    }

    // 处理每个操作
    for (let move of moves) {
        if (move in directions) {
            direction = move;  // 更改方向
        } else if (move === 'G') {  // 按当前方向移动
            let [dx, dy] = directions[direction];
            let newX = headX + dx, newY = headY + dy;

            // 检查是否越界
            if (newX < 0 || newX >= N || newY < 0 || newY >= M) {
                return snakeLength;
            }

            // 检查是否撞到自己
            if (snake.some(([x, y]) => x === newX && y === newY)) {
                return snakeLength;
            }

            // 移动蛇头
            if (grid[newX][newY] === 'F') {
                snakeLength++;
            } else {
                snake.shift();  // 没有吃到食物,移除尾巴
            }

            snake.push([newX, newY]);
            headX = newX;
            headY = newY;
        }
    }

    return snakeLength;
}

// 测试用例
let moves = ['D', 'G', 'G'];
let N = 3, M = 3;
let grid = [['F', 'F', 'F'],
            ['F', 'F', 'H'],
            ['E', 'F', 'E']];

console.log(snakeGame(moves, N, M, grid));  // 应该输出 1

八、C算法源码

#include <stdio.h>
#include <stdbool.h>

#define MAX 50

// 用于存储方向的数组
int dx[4] = {-1, 1, 0, 0};  // 上下左右方向
int dy[4] = {0, 0, -1, 1};

// 定义结构体用于存储蛇的坐标
typedef struct {
    int x, y;
} Point;

int snake_game(char moves[], int move_count, int N, int M, char grid[MAX][MAX]) {
    Point snake[MAX * MAX];  // 用于存储蛇的身体
    int snake_length = 1;
    int headX = 0, headY = 0;
    char direction = 'R';  // 初始方向为右

    // 找到蛇头位置
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            if (grid[i][j] == 'H') {
                headX = i;
                headY = j;
                snake[0].x = i;
                snake[0].y = j;
            }
        }
    }

    // 遍历操作
    for (int i = 0; i < move_count; i++) {
        char move = moves[i];

        // 更改方向
        if (move == 'U') direction = 'U';
        else if (move == 'D') direction = 'D';
        else if (move == 'L') direction = 'L';
        else if (move == 'R') direction = 'R';
        else if (move == 'G') {  // 移动
            int dir_index;
            if (direction == 'U') dir_index = 0;
            else if (direction == 'D') dir_index = 1;
            else if (direction == 'L') dir_index = 2;
            else if (direction == 'R') dir_index = 3;

            int newX = headX + dx[dir_index];
            int newY = headY + dy[dir_index];

            // 检查是否越界
            if (newX < 0 || newX >= N || newY < 0 || newY >= M) {
                return snake_length;
            }

            // 检查是否撞到自己
            for (int j = 0; j < snake_length; j++) {
                if (snake[j].x == newX && snake[j].y == newY) {
                    return snake_length;
                }
            }

            // 移动蛇头
            if (grid[newX][newY] == 'F') {
                snake_length++;  // 吃到食物,长度增加
            } else {
                // 没吃到食物,移除尾巴
                for (int j = 1; j < snake_length; j++) {
                    snake[j - 1] = snake[j];
                }
                snake_length--;
            }

            // 添加新头部
            snake[snake_length - 1].x = newX;
            snake[snake_length - 1].y = newY;
            headX = newX;
            headY = newY;
        }
    }

    return snake_length;
}

int main() {
    char moves[] = {'D', 'G', 'G'};
    int N = 3, M = 3;
    char grid[MAX][MAX] = {
        {'F', 'F', 'F'},
        {'F', 'F', 'H'},
        {'E', 'F', 'E'}
    };

    int move_count = 3;
    int result = snake_game(moves, move_count, N, M, grid);
    printf("%d\n", result);  // 应该输出 1
    return 0;
}

九、C++算法源码

#include <iostream>
#include <deque>
#include <vector>

using namespace std;

struct Point {
    int x, y;
};

int snake_game(vector<char>& moves, int N, int M, vector<vector<char>>& grid) {
    deque<Point> snake;  // 用 deque 作为队列
    int headX = 0, headY = 0;
    int snake_length = 1;
    char direction = 'R';  // 初始方向为右

    // 定义方向
    vector<int> dx = {-1, 1, 0, 0};
    vector<int> dy = {0, 0, -1, 1};
    vector<char> dir_map = {'U', 'D', 'L', 'R'};

    // 找到蛇头位置
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            if (grid[i][j] == 'H') {
                headX = i;
                headY = j;
                snake.push_back({i, j});
            }
        }
    }

    // 处理每个操作
    for (char move : moves) {
        if (move == 'U' || move == 'D' || move == 'L' || move == 'R') {
            direction = move;  // 改变方向
        } else if (move == 'G') {
            // 按当前方向移动
            int dir_idx = find(dir_map.begin(), dir_map.end(), direction) - dir_map.begin();
            int newX = headX + dx[dir_idx];
            int newY = headY + dy[dir_idx];

            // 检查是否越界
            if (newX < 0 || newX >= N || newY < 0 || newY >= M) {
                return snake_length;
            }

            // 检查是否撞到自己
            for (auto& p : snake) {
                if (p.x == newX && p.y == newY) {
                    return snake_length;
                }
            }

            // 移动蛇头
            if (grid[newX][newY] == 'F') {
                snake_length++;  // 吃到食物
            } else {
                snake.pop_front();  // 没有吃到食物,移除尾巴
            }

            snake.push_back({newX, newY});
            headX = newX;
            headY = newY;
        }
    }

    return snake_length;
}

int main() {
    vector<char> moves = {'D', 'G', 'G'};
    int N = 3, M = 3;
    vector<vector<char>> grid = {
        {'F', 'F', 'F'},
        {'F', 'F', 'H'},
        {'E', 'F', 'E'}
    };

    cout << snake_game(moves, N, M, grid) << endl;  // 应该输出 1
    return 0;
}


🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)

🏆本文收录于,华为OD机试真题(Python/JS/C/C++)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/888983.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络:数据链路层 —— 数据链路层概述

文章目录 数据链路层主要功能 基本概念链路数据链路帧 数据链路层 在计算机网络中&#xff0c;链路层&#xff08;Data Link Layer&#xff09;是网络协议栈中的一层&#xff0c;负责管理和控制链路的建立、维护和释放&#xff0c;以及处理链路层的数据帧传输和错误控制等功能…

Linux入门3——vim的简单使用

1.vim 1.1 vim的模式 vim有三种主要模式&#xff1a; ①命令模式&#xff1a;使用vim刚打开进入的模式就是命令模式&#xff1b; ②插入模式&#xff1a;只有在插入模式下才可以做文字输入&#xff0c;按[Esc]键可退回命令模式&#xff1b; ③末行模式&#xff1a;文件保存或退…

大数据毕业设计选题推荐-王者荣耀战队数据分析-Python数据可视化-Hive-Hadoop-Spark

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

Go基础学习11-测试工具gomock和monkey的使用

文章目录 基础回顾MockMock是什么安装gomockMock使用1. 创建user.go源文件2. 使用mockgen生成对应的Mock文件3. 使用mockgen命令生成后在对应包mock下可以查看生成的mock文件4. 编写测试代码5. 运行代码并查看输出 GomonkeyGomonkey优势安装使用对函数进行monkey对结构体中方法…

Android SELinux——安全策略(三)

SELinux 通过严格的访问控制机制增强了 Linux 系统的安全性。它通过标签和安全策略来控制进程和文件的访问权限&#xff0c;从而保护系统免受未经授权的访问和攻击。 一、策略介绍 1、主要组件 安全标签&#xff08;Security Labels&#xff09;&#xff1a;每个文件、目录、…

vite学习教程02、vite+vue2配置环境变量

文章目录 前言1、安装依赖2、配置环境变量3、应用环境变量4、运行和构建项目资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝3W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注于Java后端技术领域。 涵盖技术内容&#xff1…

Python的pandas库基本操作(数据分析)

一、安装&#xff0c;导入 1、安装 使用包管理器安装&#xff1a; pip3 install pandas 2、导入 import pandas as pd as是为了方便引用起的别名 二、DateFrame 在Pandas库中&#xff0c;DataFrame 是一种非常重要的数据结构&#xff0c;它提供了一种灵活的方式来存储和…

typora笔记导出word格式:

Pandoc&#xff1a;各系统下载github链接 https://github.com/jgm/pandoc/releases/latest windows安装包 链接&#xff1a;https://pan.baidu.com/s/17AZNIMImbzFtWJAcAfAB0g?pwd55l2 提取码&#xff1a;55l2 先解压压缩包 点击 设置Pandoc路径&#xff0c;然后选择pa…

【Sceneform-EQR】(手势优化)通过手势事件实现在AR/VR等三维场景中的控制模型旋转、平移与缩放

在上一篇文档中&#xff0c;我们实现了通过手势控制模型节点的旋转、缩放和平移。现在本文将介绍如何优化上一篇做的手势控制器&#xff0c;从而实现更好的跟手效果。 相关链接&#xff1a;【Sceneform-EQR】&#xff08;手势控制器实现&#xff09;通过手势事件实现在AR/VR等…

FiBiNET模型实现推荐算法

1. 项目简介 A031-FiBiNET模型项目是一个基于深度学习的推荐系统算法实现&#xff0c;旨在提升推荐系统的性能和精度。该项目的背景源于当今互联网平台中&#xff0c;推荐算法在电商、社交、内容分发等领域的广泛应用。推荐系统通过分析用户的历史行为和兴趣偏好&#xff0c;预…

Linux平台Kafka高可用集群部署全攻略

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《大数据前沿&#xff1a;技术与应用并进》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、Kafka简介 2、Kafka核心优势 二、环境准备 1…

【学习笔记】SquareLine Studio安装教程(LVGL官方工具)

一.简介与导航&#xff1a; SquareLine Studio是由LVGL官方开发的一款UI设计工具&#xff0c;采用图形化进行界面UI设计&#xff0c;轻易上手。 SquareLine Studio官方网址&#xff1a;https://squareline.io/SquareLine Studio官方文档&#xff1a;https://docs.squareline.io…

上传本地项目到GitHub远程仓库(极简洁操作版)

第一步&#xff1a;在GitHub创建一个空的仓库 第二步&#xff1a;将仓库克隆&#xff08;下载&#xff09;到本地 第三步&#xff1a;将你要上传的所有文件放到这个克隆的仓库文件夹中 第四步&#xff1a;通过git add .将待上传文件添加到暂存区 此时&#xff0c;可以通过git …

css3-----2D转换、动画

2D 转换&#xff08;transform&#xff09; 转换&#xff08;transform&#xff09;是CSS3中具有颠覆性的特征之一&#xff0c;可以实现元素的位移、旋转、缩放等效果 移动&#xff1a;translate旋转&#xff1a;rotate缩放&#xff1a;scale 二维坐标系 2D 转换之移动 trans…

SpringBoot项目打成jar包,在其他项目中引用

1、首先新建一个SpringBoot工程 记得要将Gradle换成Maven 2、新建一个要引用的方法 3、打包的时候要注意&#xff1a; ① 不能使用springboot项目自带的打包插件进行打包&#xff0c;下面是自带的&#xff1a; ②要换成传统项目的maven打包&#xff0c;如下图&#xff1a; 依…

《网络安全自学教程》- Nmap使用及扫描原理分析

《网络安全自学教程》 Nmap&#xff08;Network Mapper&#xff09;是一款免费的开源网络扫描器&#xff0c;向目标主机发送特定的数据包&#xff0c;根据返回的流量特征&#xff0c;分析主机信息。主要功能有&#xff1a;「端口扫描」、「主机探测」、「服务识别」和「系统识别…

(接口测试)接口测试理论 http理论 接口测试流程 接口文档解析

一.接口测试理论 1.接口和接口测试 服务器为客户端开了一个验证接口&#xff08;接口本质&#xff1a;函数方法&#xff09;客户端向服务器传送的消息可以相当于函数的参数&#xff0c;接口是用来让客户端传递数据的 接口&#xff1a;相当于开了一个通道 当服务器要给客户端响…

笔记整理—linux进程部分(6)进程间通信、alarm和pause

两个进程间通信可能是任何两个进程间的通信&#xff08;IPC&#xff09;。同一个进程是在同一块地址空间中的&#xff0c;在不同的函数与文件以变量进程传递&#xff0c;也可通过形参传递。2个不同进程处于不同的地址空间&#xff0c;要互相通信有难度&#xff08;内存隔离的原…

Awaken Likho恶意组织利用高级网络工具对俄罗斯政府发起“猛攻”

近日&#xff0c;俄罗斯政府机构和工业实体遭遇了一场名为“ Awaken Likho ”的网络活动攻击活动。 卡巴斯基表示&#xff0c;攻击者现在更倾向于使用合法MeshCentral平台的代理&#xff0c;而不是他们之前用来获得系统远程访问权限的UltraVNC模块。这家俄罗斯网络安全公司详细…

Golang | Leetcode Golang题解之第457题环形数组是否存在循环

题目&#xff1a; 题解&#xff1a; func circularArrayLoop(nums []int) bool {n : len(nums)next : func(cur int) int {return ((curnums[cur])%n n) % n // 保证返回值在 [0,n) 中}for i, num : range nums {if num 0 {continue}slow, fast : i, next(i)// 判断非零且方…