【华为OD】C卷真题 200分: 贪吃蛇 C/C++代码实现[思路+代码]

【华为OD】C卷真题 200分: 贪吃蛇 python代码实现[思路+代码]-CSDN博客 

【华为OD】C卷真题 200分: 贪吃蛇 Java代码实现[思路+代码]-CSDN博客

题目描述:

贪吃蛇是一个经典游戏,蛇的身体由若干方格连接而成,身体随蛇头移动。蛇头触碰到食物时,蛇的长度会增加一格。蛇头和身体的任一方格或者游戏版图边界碰撞时,游戏结束。
下面让我们来完成贪吃蛇游戏的模拟。给定一个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时蛇头和第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和E会有多个。

输出描述:

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

示例1输入输出示例仅供调试,后台判题数据一般不包含示例

输入

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

输出

1

说明

贪吃蛇一开始就向下转向并且移动两步,此时蛇头已经和边界碰撞,游戏结束,蛇没有吃任何食物,故长度为1

示例2输入输出示例仅供调试,后台判题数据一般不包含示例

输入

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

输出

3

说明

贪吃蛇保存最初的向左方向移动三步,此时蛇头已经和边界碰撞,游戏结束,蛇吃了两个食物,故长度为3

     668                                                         
                                                            
              +---+                                                          
  3            |   |       ++                               +       +---|   
  |           |   | 3      +                6               +  |   +   |        +
  |      +     |   |       +         +                      +    |  +   |       +
  |      +    |   +---+    +        +        +++++          +   +  +   |        +
  |      +    | +      |   +   +----+        |   |          +   +  +   |        +
  |      +  3 | +      |   +   +    +      2 |   |     2    +   +  +   |        +
  |      +    | +      |   +   +    +        |   |          +   +  +   |        +
  |      +---+ |     |    |  |    +    ----+   |   +---+    |  |  +   |         +
  |      |     |     |    |  |    +    |       |   |   |    |  |  +   |         +
  |    1 |     |     | 8  |  |    +  1 |   |    | 1 |   | 1 |   |  +   |        +
  |      |     |     |    |  |    +    |   |    |   |   |   |   |  +   |        +
  |  +---+     |     +---+   |    ++---+    ++   +---+   +---+   |  +   |        +
  |  |         |         |   |    |         ++              |   |  |+   |        +
  |0 |         |         | 0 |  0 |         ++              | 0 |  |+   |        +
  |  |         |         |   |    |         ++              |   |  |+   |        +
  +---+         +          +-------+                       +---+| +|+   |        +
                +                                                    +   |        +
    0   1   2   3   4   5   6   7   8   9  10  11  12 + v:    w  u m    u 1 0 2 4
 

题目解析:

        模拟贪吃蛇的操作即可

代码实现:

#include <iostream>
#include <vector>
using namespace std;
int length = 1;
int cnt = 1;
void findTail(vector<vector<int>> &_map) {
	int cmp = 100000000;
	int index[2] = { 0 };
	for (int i = 0; i < _map.size(); ++i) {
		for (int j = 0; j < _map[0].size(); ++j) {
			if (_map[i][j] != 0 && cmp > _map[i][j]) {
				cmp = _map[i][j];
				index[0] = i;
				index[1] = j;
 			}
		}
	}
	_map[index[0]][index[1]] = 0;
}
bool play(vector<vector<char>> &data, vector<vector<int>> &_map, int * pos, char direction) {
	switch (direction) {
	case 'L': pos[1] -= 1; break;
	case 'R': pos[1] += 1; break;
	case 'U': pos[0] -= 1; break;
	case 'D': pos[0] += 1; break;
	}
	if (pos[0] < 0 || pos[0] >= data.size() || pos[1] < 0 || pos[1] >= data[0].size() || _map[pos[0]][pos[1]] != 0) {
		return true; 
	}
	_map[pos[0]][pos[1]] = cnt++;
	if (data[pos[0]][pos[1]] == 'F') {
		data[pos[0]][pos[1]] = 'E';
		length += 1;
		return false;
	}
	findTail(_map);
	return false;
}
int input() {
	vector<char> op;
	char t;
	int m, n;
	while (true) {
		cin.get(t);
		if (t == '\n') {
			break;
		}
		if(t != ' '){
            op.push_back(t);
        }
	}
	cin >> m >> n;
	int pos[2] = { 0 };
	cin.get(t);
	vector<vector<char>> data(m, vector<char>(n, 0));
	vector<vector<int>> _map(m, vector<int>(n, 0));
	for (int i = 0; i < m; ++i) {
		for (int j = 0; j < n; ++j) {
			cin.get(t);
			data[i][j] = t;
			if (t == 'H') {
				pos[0] = i; 
				pos[1] = j;
				_map[i][j] = cnt++;
			}
			cin.get(t);
		}
	}
	char direction = 'L';
	for (int i = 0; i < op.size(); ++i) {
		switch (op[i]) {
		case 'U': direction = 'U'; break;
		case 'D': direction = 'D'; break;
		case 'L': direction = 'L'; break;
		case 'R': direction = 'R'; break;
		default: if (play(data, _map, pos, direction)) {
					return length;
				 }
		}
	}
	return length;
}
int main() {
	cout << input() << endl;
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

五木大大

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

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

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

打赏作者

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

抵扣说明:

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

余额充值