#C61. 【华为OD机考 统一考试机试C卷】石头剪刀布游戏
【华为OD机考 统一考试机试C卷】石头剪刀布游戏
题目链接
【华为OD机考 统一考试机试C卷】石头剪刀布游戏(C++ Java JavaScript Python)
https://blog.csdn.net/banxia_frontend/article/details/134909498
题目描述
石头剪刀布游戏有 3 种出拳形状:石头、剪刀、布。分别用字母 A , B , C 表示。
游戏规则:
出拳形状之间的胜负规则如下: A > B;B > C;C > A;">"左边一个字母,表示相对优势形状。右边一个字母,表示相对劣势形状。 当本场次中有且仅有一种出拳形状优于其它出拳形状,则该形状的玩家是胜利者。否则认为是平局。 当发生平局,没有赢家。有多个胜利者时,同为赢家。
-
例如 1: 三个玩家出拳分别是A, B, C ,由于出现三方优势循环(即没有任何一方优于其它出拳者),判断为平局。
-
例如 2: 两个玩家,出拳分别是 A, B ,出拳 A 的获胜。
-
例如 3: 三个玩家,出拳全部是 A ,判为平局。
输入描述
在一场游戏中,每个玩家的信息为一行。玩家数量不超过 1000
。每个玩家信息有 2
个字段,用空格隔开:
- 玩家 ID:一个仅由英文字母和数字组成的字符串
- 出拳形状:以英文大写字母表示,
A 、B 、C
形状。 例:
abc1 A
xyz B
输出描述
输出为赢家的玩家 ID 列表(一个或多个),每个 ID 一行,按字符串升序排列。如果没有赢家,输出为"NULL"
字符串。例如:
abc1
用例1
输入
abc1 A
xyz B
输出
abc1
说明
A比B有优势,abc1 胜出
用例2
输入
abc1 A
xyz A
输出
NULL
说明
没有优胜的出拳形状,平局
用例3
输入
abc1 A
def A
alic A
xyz B
输出
abc1
alic
def
说明
A为优胜方,有三个赢家
解题思路
- 创建一个映射,用来存储每种出拳形状(A、B、C)对应的玩家ID列表。
- 读取输入,将每个玩家的ID根据其出拳形状添加到映射中。
- 根据游戏规则,判断出拳形状的种类:
- 如果不是两种形状,即为0种(无输入)、1种(所有玩家出同一形状)或3种(每种形状至少一个玩家),则判定为平局。
- 如果是两种形状,根据出拳规则(A > B, B > C, C > A)确定胜出的形状,其对应的玩家ID即为胜利者。
- 如果有胜利者,对胜利者的ID进行排序并输出;如果没有胜利者,输出"NULL"。
为什么不需要考虑每种出拳形状的人数?
根据题目的游戏规则,只有当有且仅有一种出拳形状优于其他出拳形状时,才有赢家。这意味着只有两种出拳形状存在时,才能根据规则确定胜者。如果有三种形状或者只有一种形状,无论每种形状的人数是多少,都会判定为平局。因此,在判断胜负时,只需要关注出拳形状的种类,而不是每种形状的人数。
C++
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
// 存储每种出拳形状对应的玩家ID列表
map<string, vector<string>> shapeToPlayerIds;
string playerId, shape;
// 循环读取玩家ID和出拳形状
while (cin >> playerId >> shape) {
// 如果该出拳形状还未记录,则初始化玩家ID列表
if (shapeToPlayerIds.find(shape) == shapeToPlayerIds.end()) {
shapeToPlayerIds[shape] = vector<string>();
}
// 将玩家ID添加到对应出拳形状的列表中
shapeToPlayerIds[shape].push_back(playerId);
}
// 如果每种出拳形状都只有一种,或者三种都有,则判定为平局
if (shapeToPlayerIds.size() != 2) {
cout << "NULL" << endl;
return 0;
}
// 存储胜利玩家ID的列表
vector<string> winningPlayerIds;
// 根据出拳规则,确定胜利玩家ID列表
if (shapeToPlayerIds.count("A") && shapeToPlayerIds.count("B")) {
winningPlayerIds = shapeToPlayerIds["A"]; // A胜B
} else if (shapeToPlayerIds.count("B") && shapeToPlayerIds.count("C")) {
winningPlayerIds = shapeToPlayerIds["B"]; // B胜C
} else if (shapeToPlayerIds.count("A") && shapeToPlayerIds.count("C")) {
winningPlayerIds = shapeToPlayerIds["C"]; // C胜A
} else {
cout << "NULL" << endl;
return 0;
}
// 对胜利玩家ID进行排序
sort(winningPlayerIds.begin(), winningPlayerIds.end());
// 输出胜利玩家ID
for (const string& id : winningPlayerIds) {
cout << id << endl;
}
return 0;
}
Java
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
public class RockPaperScissors {
public static void main(String[] args) {
// 存储每种出拳形状对应的玩家ID列表
Map<String, List<String>> shapeToPlayerIds = new HashMap<>();
// 用于读取输入数据
Scanner scanner = new Scanner(System.in);
// 循环读取玩家ID和出拳形状
while (scanner.hasNext()) {
String playerId = scanner.next(); // 玩家ID
String shape = scanner.next(); // 出拳形状
// 如果该出拳形状还未记录,则初始化玩家ID列表
shapeToPlayerIds.putIfAbsent(shape, new ArrayList<>());
// 将玩家ID添加到对应出拳形状的列表中
shapeToPlayerIds.get(shape).add(playerId);
}
// 如果每种出拳形状都只有一种,或者三种都有,则判定为平局
if (shapeToPlayerIds.size() != 2) {
System.out.println("NULL");
return;
}
// 存储胜利玩家ID的列表
List<String> winningPlayerIds = new ArrayList<>();
// 根据出拳规则,确定胜利玩家ID列表
if (shapeToPlayerIds.containsKey("A") && shapeToPlayerIds.containsKey("B")) {
winningPlayerIds = shapeToPlayerIds.get("A"); // A胜B
} else if (shapeToPlayerIds.containsKey("B") && shapeToPlayerIds.containsKey("C")) {
winningPlayerIds = shapeToPlayerIds.get("B"); // B胜C
} else if (shapeToPlayerIds.containsKey("A") && shapeToPlayerIds.containsKey("C")) {
winningPlayerIds = shapeToPlayerIds.get("C"); // C胜A
} else { // 如果没有满足以上任何条件,则没有胜者
System.out.println("NULL");
return;
}
// 对胜利玩家ID进行排序
Collections.sort(winningPlayerIds);
// 输出胜利玩家ID
for (String playerId : winningPlayerIds) {
System.out.println(playerId);
}
}
}
javaScript
// Node.js代码
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
// 存储每种出拳形状对应的玩家ID列表
let shapeToPlayerIds = {};
rl.on('line', (line) => {
const [playerId, shape] = line.split(' ');
// 如果该出拳形状还未记录,则初始化玩家ID列表
shapeToPlayerIds[shape] = shapeToPlayerIds[shape] || [];
// 将玩家ID添加到对应出拳形状的列表中
shapeToPlayerIds[shape].push(playerId);
}).on('close', () => {
// 如果每种出拳形状都只有一种,或者三种都有,则判定为平局
const shapes = Object.keys(shapeToPlayerIds);
if (shapes.length !== 2) {
console.log('NULL');
process.exit(0);
}
// 存储胜利玩家ID的列表
let winningPlayerIds;
// 根据出拳规则,确定胜利玩家ID列表
if (shapeToPlayerIds['A'] && shapeToPlayerIds['B']) {
winningPlayerIds = shapeToPlayerIds['A']; // A胜B
} else if (shapeToPlayerIds['B'] && shapeToPlayerIds['C']) {
winningPlayerIds = shapeToPlayerIds['B']; // B胜C
} else if (shapeToPlayerIds['A'] && shapeToPlayerIds['C']) {
winningPlayerIds = shapeToPlayerIds['C']; // C胜A
} else {
console.log('NULL');
process.exit(0);
}
// 对胜利玩家ID进行排序
winningPlayerIds.sort();
// 输出胜利玩家ID
winningPlayerIds.forEach((id) => {
console.log(id);
});
});
Python
# Python代码
import sys
# 存储每种出拳形状对应的玩家ID列表
shape_to_player_ids = {}
# 循环读取玩家ID和出拳形状
for line in sys.stdin:
player_id, shape = line.strip().split()
# 如果该出拳形状还未记录,则初始化玩家ID列表
if shape not in shape_to_player_ids:
shape_to_player_ids[shape] = []
# 将玩家ID添加到对应出拳形状的列表中
shape_to_player_ids[shape].append(player_id)
# 如果每种出拳形状都只有一种,或者三种都有,则判定为平局
if len(shape_to_player_ids) != 2:
print("NULL")
else:
# 存储胜利玩家ID的列表
winning_player_ids = []
# 根据出拳规则,确定胜利玩家ID列表
if 'A' in shape_to_player_ids and 'B' in shape_to_player_ids:
winning_player_ids = shape_to_player_ids['A'] # A胜B
elif 'B' in shape_to_player_ids and 'C' in shape_to_player_ids:
winning_player_ids = shape_to_player_ids['B'] # B胜C
elif 'A' in shape_to_player_ids and 'C' in shape_to_player_ids:
winning_player_ids = shape_to_player_ids['C'] # C胜A
else:
print("NULL")
# 对胜利玩家ID进行排序
winning_player_ids.sort()
# 输出胜利玩家ID
for player_id in winning_player_ids:
print(player_id)
C语言
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义玩家结构体
typedef struct {
char id[100]; // 玩家ID
char shape; // 出拳形状
} Player;
// 比较函数,用于qsort排序
int compare(const void *a, const void *b) {
Player *playerA = (Player *)a;
Player *playerB = (Player *)b;
return strcmp(playerA->id, playerB->id);
}
int main() {
Player players[1000]; // 存储所有玩家信息
int countA = 0, countB = 0, countC = 0; // 记录每种出拳形状的玩家数量
int n = 0; // 玩家总数
char id[100], shape;
// 循环读取玩家ID和出拳形状
while (scanf("%s %c", id, &shape) != EOF) {
strcpy(players[n].id, id);
players[n].shape = shape;
// 根据出拳形状增加计数
if (shape == 'A') countA++;
if (shape == 'B') countB++;
if (shape == 'C') countC++;
n++;
}
// 如果每种出拳形状都只有一种,或者三种都有,则判定为平局
if (countA > 0 && countB > 0 && countC > 0 || countA == n || countB == n || countC == n) {
printf("NULL\n");
} else {
// 根据出拳规则,确定胜利玩家ID列表
char winShape = (countA > 0 && countC == 0) ? 'A' : (countB > 0 && countA == 0) ? 'B' : 'C';
Player winners[1000]; // 存储胜利玩家信息
int winCount = 0; // 胜利玩家数量
for (int i = 0; i < n; i++) {
if (players[i].shape == winShape) {
winners[winCount++] = players[i];
}
}
// 对胜利玩家ID进行排序
qsort(winners, winCount, sizeof(Player), compare);
// 输出胜利玩家ID
for (int i = 0; i < winCount; i++) {
printf("%s\n", winners[i].id);
}
}
return 0;
}
完整用例
用例1
player1 A
player2 B
player3 C
用例2
player1 A
player2 B
player3 B
用例3
player1 C
player2 C
player3 B
用例4
player1 B
player2 A
player3 A
用例5
player1 C
player2 A
player3 C
用例6
player1 B
player2 B
player3 B
用例7
player1 A
player2 C
player3 B
player4 A
用例8
player1 B
player2 C
player3 C
player4 B
用例9
player1 C
player2 B
player3 A
player4 C
player5 B
player6 A
用例10
player1 A
player2 A
player3 B
player4 B
player5 C
@[TOC]