79 lines
3.6 KiB
Markdown
79 lines
3.6 KiB
Markdown
# 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。
|