「PAT乙级真题解析」Basic Level 1018 锤子剪刀布 (问题分析+完整步骤+伪代码描述+提交通过代码)

题目要求统计甲乙两人玩剪刀石头布游戏的游戏结果, 并输出要求的统计项. 由于"统计", "剪刀石头布"这些都是我们十分熟悉的用语, 不需要理厘清概念之类的. 只需要考虑清楚统计过程中涉及了哪些步骤即可使用编程语言进行翻译。...

#算法#数据结构#c语言#pat考试#需求分析

Table of Contents

乙级的题目训练主要用来熟悉编程语言的语法和形成良好的编码习惯和编码规范。从小白开始逐步掌握用编程解决问题。

PAT乙级BasicLevelPractice 1018 锤子剪刀布

问题分析

题目要求统计甲乙两人玩剪刀石头布游戏的游戏结果, 并输出要求的统计项. 由于"统计", "剪刀石头布"这些都是我们十分熟悉的用语, 不需要理厘清概念之类的. 只需要考虑清楚统计过程中涉及了哪些步骤即可使用编程语言进行翻译。

统计

统计胜、平、负

这需要为每个人设置两个变量空间存储对应数据。 可以是三个单独变量, 也可以是长度为3的数组, 也可以是hi是含三个字段的结构体。 只要我们有一个判断胜负的逻辑,然后胜负结果后往变量空间里存储即可。

统计获胜最多的手势

最直接的方法, 就是记录各个手势的获胜次数, 然后转化成一个求最值问题。 手势有三种, 所以跟统计胜平负一样每个人各自需要三个存储空间。

判断游戏胜负

根据我们熟悉的游戏规则, 代入题目给定的各个手势对应的代表符号后, 逻辑如下:

  1. 甲胜
    • 甲 C 乙 J
    • 甲 J 乙 B
    • 甲 B 乙 C
  2. 甲平
    • 甲 C 乙 C
    • 甲 J 乙 J
    • 甲 B 乙 B
  3. 甲负
    • 甲 J 乙 C
    • 甲 B 乙 J
    • 甲 C 乙 B

完整描述步骤

  1. 读入数据(游戏回合数, 各回合甲和乙的出拳手势)
  2. 对于每一局的甲乙手势进行如下操作:
    • 判断胜负
    • 为胜利一方的胜利计数器加1
    • 为胜利一方对应手势的胜利计数器加1
    • 为败北一方的败北计数器加1
  3. 分别计算甲和乙胜利次数最多的手势
  4. 输出结果

伪代码描述

  1. get input: game_case_amount, gestures of A and B
  2. for each_case in all_game_case:
    • if gesture_A == gesture_B: A_even_counter++; B_even_counter++;
    • else if A won B: A_win_counter++; A_gesture_win_counter[gesture_A]++; B_failure_counter++;
    • else: B_win_counter++; B_gesture_win_counter[gesture_B]++; A_failure_counter++;
  3. print
    • count of A's win even failure
    • count of B's win even failure
    • get_gesture(index of max(A_gesture_win_counter)) get_gesture(index of max(B_gesture_win_counter))

完整提交代码

/*
# 问题分析
题目要求统计甲乙两人玩剪刀石头布游戏的游戏结果, 并输出要求的统计项.
由于"统计", "剪刀石头布"这些都是我们十分熟悉的用语, 不需要理厘清概念之类的.
只需要考虑清楚统计过程中涉及了哪些步骤即可使用编程语言进行翻译。
 
# 统计
## 统计胜、平、负
这需要为每个人设置两个变量空间存储对应数据。
可以是三个单独变量,
也可以是长度为3的数组, 
也可以是hi是含三个字段的结构体。
只要我们有一个判断胜负的逻辑,然后胜负结果后往变量空间里存储即可。
 
## 统计获胜最多的手势
最直接的方法, 就是记录各个手势的获胜次数, 然后转化成一个求最值问题。
手势有三种, 所以跟统计胜平负一样每个人各自需要三个存储空间。
 
 
## 判断游戏胜负
根据我们熟悉的游戏规则, 代入题目给定的各个手势对应的代表符号后, 逻辑如下:
 
1. 甲胜
    - 甲 C 乙 J
    - 甲 J 乙 B
    - 甲 B 乙 C
2. 甲平
    - 甲 C 乙 C
    - 甲 J 乙 J
    - 甲 B 乙 B
3. 甲负
    - 甲 J 乙 C
    - 甲 B 乙 J
    - 甲 C 乙 B
 
# 完整描述步骤
1. 读入数据(游戏回合数, 各回合甲和乙的出拳手势)
2. 对于每一局的甲乙手势进行如下操作:
    - 判断胜负
    - 为胜利一方的胜利计数器加1
    - 为胜利一方对应手势的胜利计数器加1
    - 为败北一方的败北计数器加1
3. 分别计算甲和乙胜利次数最多的手势
4. 输出结果
 
# 伪代码描述
 
1. get input: game_case_amount, gestures of A and B
2. for each_case in all_game_case:
    - if gesture_A == gesture_B:
        A_even_counter++;
        B_even_counter++;
    - else if A won B:
        A_win_counter++;
        A_gesture_win_counter[gesture_A]++;
        B_failure_counter++;
    - else:
        B_win_counter++;
        B_gesture_win_counter[gesture_B]++;
        A_failure_counter++;
3. print
    - count of A's win even failure
    - count of B's win even failure
    - get_gesture(index of max(A_gesture_win_counter))
        get_gesture(index of max(B_gesture_win_counter))
 
*/
 
 
 
#include <stdio.h>
 
int A_won_B(char gesture_A, char gesture_B)
{
    if (gesture_A == 'C' && gesture_B == 'J')
    {
        return 1;
    }
    if (gesture_A == 'J' && gesture_B == 'B')
    {
        return 1;
    }
    if (gesture_A == 'B' && gesture_B == 'C')
    {
        return 1;
    }
 
    return 0;
}
 
char find_the_gesture_won_most_times(int* results){
    if (results[2] >= results[0] && results[2] >= results[1]){
        return 'B';
    } else if (results[0] >= results[1] && results[0] >= results[2]){
        return 'C';
    } else {
        return 'J';
    }
}
 
void record_the_gesture_when_someone_win(char gesture, int counter[3]){
    if (gesture == 'C'){
        counter[0]++;
    } else if (gesture == 'J'){
        counter[1]++;
    } else {
        counter[2]++;
    }
}
 
int main()
{
 
    int case_amount;
    scanf("%d\n", &case_amount);
 
    char gesture_A;
    char gesture_B;
    int result_count_of_A[3] = {0, 0, 0};
    int result_count_of_B[3] = {0, 0, 0};
    int win_case_count_of_A[3] = {0, 0, 0};
    int win_case_count_of_B[3] = {0, 0, 0};
    for (int i = 0; i < case_amount; i++)
    {
        scanf("%c %c\n", &gesture_A, &gesture_B);
        if (gesture_A == gesture_B)
        {
            result_count_of_A[1]++;
            result_count_of_B[1]++;
        }
        else if (A_won_B(gesture_A, gesture_B) == 1)
        {
            result_count_of_A[0]++;
            result_count_of_B[2]++;
            record_the_gesture_when_someone_win(gesture_A, win_case_count_of_A);
        }
        else
        {
            result_count_of_A[2]++;
            result_count_of_B[0]++;
            record_the_gesture_when_someone_win(gesture_B, win_case_count_of_B);
        }
    }
    printf("%d %d %d\n", result_count_of_A[0], result_count_of_A[1], result_count_of_A[2]);
    printf("%d %d %d\n", result_count_of_B[0], result_count_of_B[1], result_count_of_B[2]);
    printf("%c %c", find_the_gesture_won_most_times(win_case_count_of_A), find_the_gesture_won_most_times(win_case_count_of_B));
        
    return 0;
}
「PAT乙级真题解析」Basic Level 1018 锤子剪刀布 (问题分析+完整步骤+伪代码描述+提交通过代码) | 生活糖果