石头剪刀布游戏
2025华为OD机试双机位B卷 - 华为OD上机考试双机位B卷 100分题型
华为OD机试双机位B卷真题目录点击查看: 华为OD机试双机位B卷真题题库目录|机考题库 + 算法考点详解
题目描述
石头剪刀布游戏有 3 种出拳形状:石头、剪刀、布。分别用字母A、B、C表示。
游戏规则:
出拳形状之间的胜负规则如下:
A > B;
B > C;
C > A;“>” 左边一个字母,表示相对优势形状。右边一个字母,表示相对劣势形状。
当本场次中有且仅有一种出拳形状优于其他出拳形状,则该形状的玩家是胜利者。否则认为是平局。
例如1:三个玩家出拳分别是A,B,C。由于三方优势循环(即没有任何一方优于其他出拳者),判断为平局。
例如2:三个玩家出拳分别是A,B,B。出拳A的获胜。
例如3:三个玩家出拳全部是A。判为平局。
当发生平局,没有赢家。有多个胜利者时,同为赢家。
输入描述
在一场游戏中,每个玩家的信息为一行。玩家数量不超过1000。每个玩家信息有2个字段,用空格隔开;
- 玩家ID:一个仅由英文字母和数字组成的字符串
- 出拳形状:以英文大写字母表示,A、B、C形状。
例如:
abc1 A
xyz B
解释:玩家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为优胜方,有三个赢家
题解
思路:逻辑分析
- 可以使用
哈希表 / 二维数组存储各个手型的用户名称。 - 接下来分情况讨论得出结果:
- 如果只出现一种手型 或者三种手型说明是平局,则直接输出
NULL结束。 - 出现两种手型的话,肯定有胜者,接下来分以下情况
- 如果没有出现
A,代表出现B C, 那么出B的就是胜者 - 如果没有出现
B,代表出现A C, 那么出C的就是胜者 - 如果没有出现
C,代表出现A B, 那么出A的就是胜者
- 如果没有出现
- 如果只出现一种手型 或者三种手型说明是平局,则直接输出
- 如果存在胜者的话,将用户名按照字典序升序排序之后,输出结果即可。
c++
#include<iostream> #include<vector> #include<string> #include <utility> #include <sstream> #include<algorithm> #include<cmath> #include<map> using namespace std; // 通用 切割函数 函数 将字符串str根据delimiter进行切割 vector<string> split(const string& str, const string& delimiter) { vector<string> result; size_t start = 0; size_t end = str.find(delimiter); while (end != string::npos) { result.push_back(str.substr(start, end - start)); start = end + delimiter.length(); end = str.find(delimiter, start); } // 添加最后一个部分 result.push_back(str.substr(start)); return result; } int main() { // 存储每个手型的名字 map<string, vector<string>> mapping; string input; while (getline(cin, input)) { if (input.empty()) { break; } vector<string> tmp = split(input, " "); mapping[tmp[1]].push_back(tmp[0]); } // 三个手型或者一个手型都是平局 if (mapping.size() == 3 || mapping.size() == 1) { cout << "NULL"; return 0; } vector<string> res; // 没有石头只有 剪刀/布 剪刀赢 if (mapping["A"].empty()) { res = mapping["B"]; // 没有剪刀只有 石头/布 布赢 } else if (mapping["B"].empty()) { res = mapping["C"]; // 没有布 只有剪刀/石头 石头赢 } else { res = mapping["A"]; } // 升序 sort(res.begin(), res.end()); // 输出结果 for (int i = 0; i < res.size(); i++) { cout << res[i] << endl; } return 0; }JAVA
import java.io.*; import java.util.*; public class Main { public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 存储每个手型对应的玩家名字 Map<String, List<String>> mapping = new HashMap<>(); String line; while ((line = br.readLine()) != null) { if (line.trim().isEmpty()) { break; } String[] arr = line.split(" "); String name = arr[0]; String type = arr[1]; mapping.putIfAbsent(type, new ArrayList<>()); mapping.get(type).add(name); } // 三种手型或只有一种手型,都是平局 if (mapping.size() == 3 || mapping.size() == 1) { System.out.print("NULL"); return; } List<String> res; // 没有石头(A),只有剪刀(B)/布(C),剪刀赢 if (!mapping.containsKey("A")) { res = mapping.get("B"); } // 没有剪刀(B),只有石头(A)/布(C),布赢 else if (!mapping.containsKey("B")) { res = mapping.get("C"); } // 没有布(C),只有石头(A)/剪刀(B),石头赢 else { res = mapping.get("A"); } // 按名字升序输出 Collections.sort(res); for (String s : res) { System.out.println(s); } } }Python
importsysfromcollectionsimportdefaultdict# 存储每个手型对应的玩家名字mapping=defaultdict(list)# 读取输入,直到遇到空行或 EOFforlineinsys.stdin:line=line.strip()ifnotline:breakname,hand=line.split()mapping[hand].append(name)# 三种手型或只有一种手型,都是平局iflen(mapping)==3orlen(mapping)==1:print("NULL")sys.exit(0)# 判断胜者# 没有石头(A),剪刀(B)赢if"A"notinmapping:res=mapping["B"]# 没有剪刀(B),布(C)赢elif"B"notinmapping:res=mapping["C"]# 没有布(C),石头(A)赢else:res=mapping["A"]# 升序输出res.sort()fornameinres:print(name)JavaScript
constreadline=require('readline');// readline 接收输入constrl=readline.createInterface({input:process.stdin,output:process.stdout});constlines=[];rl.on('line',line=>{lines.push(line.trim());});rl.on('close',()=>{// 存储每个手型对应的玩家名字constmapping=newMap();for(constlineoflines){if(line==='')break;const[name,hand]=line.split(' ');if(!mapping.has(hand)){mapping.set(hand,[]);}mapping.get(hand).push(name);}// 三种手型或只有一种手型,都是平局if(mapping.size===3||mapping.size===1){console.log("NULL");return;}letres;// 没有石头(A),剪刀(B)赢if(!mapping.has("A")){res=mapping.get("B");}// 没有剪刀(B),布(C)赢elseif(!mapping.has("B")){res=mapping.get("C");}// 没有布(C),石头(A)赢else{res=mapping.get("A");}// 按字典序升序res.sort();// 输出结果for(constnameofres){console.log(name);}});Go
packagemainimport("bufio""fmt""os""sort""strings")funcmain(){in:=bufio.NewScanner(os.Stdin)// 存储每个手型对应的玩家名字mapping:=make(map[string][]string)// 逐行读取输入forin.Scan(){line:=strings.TrimSpace(in.Text())ifline==""{break}parts:=strings.Split(line," ")name:=parts[0]hand:=parts[1]mapping[hand]=append(mapping[hand],name)}// 三种手型或只有一种手型,都是平局iflen(mapping)==3||len(mapping)==1{fmt.Print("NULL")return}varres[]string// 没有石头(A),剪刀(B)赢if_,ok:=mapping["A"];!ok{res=mapping["B"]}elseif_,ok:=mapping["B"];!ok{// 没有剪刀(B),布(C)赢res=mapping["C"]}else{// 没有布(C),石头(A)赢res=mapping["A"]}// 升序排序sort.Strings(res)// 输出结果for_,name:=rangeres{fmt.Println(name)}}