# 2.3 纸牌游戏 ## 2.3.1 问题描述 设有两个玩家PA和PB,他们玩一副具有$N(N<10)$个不同面值的扑克牌,每个面值有两张牌。 玩法1:顺序抓牌顺序出牌。 第一步,发牌。将扑克牌均分成两份,玩家PA、PB各得一份,或轮流抓牌各得一半牌。牌按得牌顺序前后有序。 第二步,玩牌。当双方手中都有牌时,双方依得牌顺序交替出牌,设出牌面值为X,重复下列操作。 1. 如果桌面上没有与X相同面值的牌,将牌X放到牌桌上且压在已有牌的上方。 2. 如果桌面上有与X相同面值的牌,出牌人赢牌,执行下列操作。 1. 把出的牌X添加到牌尾。 2. 把桌面上的牌直到面值为X的牌依次添加到出牌人的牌尾。 第三步,赢家。如果有一方玩家手中无牌,游戏结束,无牌的玩家为输家,有牌的玩家为赢家。 第四步,摊牌。输出赢家手中的牌和桌上的牌。 玩法2:玩家1依得牌顺序出牌,玩家2随意出牌。 此玩法中,显然玩家1的玩法与玩法1相同,顺序出牌,顺序将赢的牌插人牌尾;而玩家2可以根据赢的可能性出牌。 ## 2.3.2 分析与设计提示 1. 牌的信息 牌只有牌面值一个信息。玩家和桌上均有若干张牌,可以分别用整型数组表示。 2. 功能设计 该任务的完成主要涉及以下功能: 1. 发牌。 2. 玩法1。 3. 玩法2。 4. 摊牌。 3. 存储设计 对于玩法1的设计如下。 1. 玩家手中的牌是先抓到的牌先出,赢的牌添加在牌尾,具有“先来先服务”特性,可以用队列表示。 2. 桌上的牌是后出的牌压在先出牌的上面,可以用栈存储。 3. 由于牌总数可知,所以队列和栈均可用顺序存储。 对于玩法2的设计如下。 1. 与玩法1相同的理由,玩家1手中的牌用顺序队列存储;桌上的牌是后出的牌压在先出牌的上面,用顺序栈存储。 2. 玩家2手中的牌没有出牌顺序要求,采用链表较好。 4. 算法设计 1. 发牌。 通过初始化或随机数,为两个玩家分牌。 2. 玩法1。 设队列QA和QB分别表示玩家PA和玩家PB手中的牌,堆栈S表示桌上的牌。设玩家PA先出牌,根据玩法,玩牌的操作如下。 **Step 1** 只要QA和QB均不空,重复下列操作。 1. 取QA队队头元素pa. 2. 如果堆栈中有值等于PA的牌sa。 1. pa入QA队尾。 2. sa前的元素依次出栈、入队列QA,sa出栈入队列QA。 3. 如果堆栈中没有值等于pa的牌,pa入栈。 **Step 2** 只要QA和QB中有一个为空队,进行下列操作。 1. 空队列的玩家为输家。 2. 显示赢家手中的牌信息及桌上牌信息。 3. 游戏结束。 3. 玩法2。 为了减少对方赢的可能,需要一些策略,如不出对方有的牌;出手中成对的牌,以便能收回等。请自行从实际中总结经验,决定出牌策略。 4. 摊牌。 赢家手中的牌,对于玩法1,依次出队输出;对于玩法2,遍历线性表输出。桌上的牌,依次出栈并输出。 ## 2.3.3 性能要求 本系统的性能要求如下。 1. 展示玩家得牌信息。 2. 展示玩牌中出牌和赢牌信息。 3. 思考以复杂度$O(1)$判断桌上是否有当前出的牌。 4. 多组数据测试,说明玩法1是否一定会产生赢家。 5. 多组数据测试,说明自行出牌的玩家是否一定能赢。 6. 牌的点数不超过10。