1 条题解

  • 0
    @ 2025-5-6 5:36:24

    解题思路:

    本题模拟Snap卡牌游戏,核心在于正确处理牌堆的动态变化及Snap时的牌堆转移逻辑,同时严格遵循输出格式和终止条件。

    关键步骤:

    1. 数据结构选择

      • 使用队列(queue<char>queue<char>)模拟玩家当前的面朝下牌堆,保证从顶部依次出牌。
      • 使用向量(vector<char>vector<char>)临时存储每轮打出的牌,便于处理Snap时的牌堆合并。
    2. 游戏流程模拟

      • 出牌阶段:每轮双方各出一张牌到临时向量。若牌相同,触发Snap判断。
      • Snap处理:根据随机结果决定胜者,将对方的临时牌堆合并到己方队列顶部,并清空对方临时牌堆。
      • 牌堆翻转:当队列为空时,将临时向量中的牌倒序压回队列,模拟牌堆翻转逻辑。
    3. 终止条件判断

      • 轮数限制:最多进行10001000轮,超时输出“Keeps going and going ...”。
      • 胜负判定:当任一玩家的队列和临时向量总牌数等于初始总牌数时,该玩家获胜。
    4. 输出细节处理

      • Snap发生时,按题目要求输出对应玩家的临时牌堆(需逆序打印,因向量存储顺序为从顶到底)。
      • 使用rand()/99rand() / 99 % 2模拟随机决策,00代表Jane先喊,11代表John先喊。

    代码解释:

    • 初始化:读取Jane和John的初始牌堆,存入队列ppqq
    • 主循环
      • 每轮从队列头部取牌存入临时向量vpvpvqvq
      • 若牌相同,根据随机结果转移牌堆并输出对应信息。
      • 队列空时,将临时向量倒序压回队列(模拟牌堆翻转)。
    • 终止判断:检查轮数或牌堆归属,输出结果。

    C++实现:

    #include <queue>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    int main() {
        char s1[1000], s2[1000];
        while (~scanf("%s%s", s1, s2)) {  // 读取输入
            int len = strlen(s1);
            queue<char> p, q;             // Jane和John的当前牌堆
            vector<char> vp, vq;          // 临时存放打出的牌
            // 初始化队列
            for (int i = 0; s1[i]; i++) p.push(s1[i]);
            for (int i = 0; s2[i]; i++) q.push(s2[i]);
            
            int cnt = 0;                  // 轮数计数器
            bool ongoing = true;          // 游戏进行标志
            
            while (cnt < 1000 && ongoing) {
                // 出牌阶段
                if (p.empty() || q.empty()) break;  // 牌堆为空则游戏结束
                vp.push_back(p.front()); p.pop();
                vq.push_back(q.front()); q.pop();
                cnt++;
                
                // 检查Snap
                if (!vp.empty() && !vq.empty() && vp.back() == vq.back()) {
                    int t = rand() / 99 % 2;  // 随机决定胜者
                    if (t == 0) {              // Jane获胜
                        // 转移John的牌到Jane的队列
                        for (char c : vq) p.push(c);
                        vq.clear();
                        // 输出Jane的牌堆(逆序)
                        printf("Snap! for Jane: ");
                        for (auto it = vp.rbegin(); it != vp.rend(); ++it)
                            printf("%c", *it);
                        puts("");
                    } else {                   // John获胜
                        // 转移Jane的牌到John的队列
                        for (char c : vp) q.push(c);
                        vp.clear();
                        // 输出John的牌堆(逆序)
                        printf("Snap! for John: ");
                        for (auto it = vq.rbegin(); it != vq.rend(); ++it)
                            printf("%c", *it);
                        puts("");
                    }
                    // 清空临时向量
                    vp.clear();
                    vq.clear();
                }
                
                // 牌堆翻转逻辑
                if (p.empty()) {
                    for (int i = vp.size()-1; i >= 0; i--)
                        p.push(vp[i]);
                    vp.clear();
                }
                if (q.empty()) {
                    for (int i = vq.size()-1; i >= 0; i--)
                        q.push(vq[i]);
                    vq.clear();
                }
                
                // 检查胜负
                if (p.size() + vp.size() == 2 * len) {
                    ongoing = false;
                    puts("Jane wins.");
                }
                if (q.size() + vq.size() == 2 * len) {
                    ongoing = false;
                    puts("John wins.");
                }
            }
            // 超时未结束
            if (cnt == 1000 && ongoing)
                puts("Keeps going and going ...");
        }
        return 0;
    }
    
    • 1

    信息

    ID
    1590
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    7
    已通过
    1
    上传者