题目描述
小的时候,你玩过纸牌游戏吗?有一种叫做"拉马车"的游戏,规则很简单,却很吸引小朋友。
其规则简述如下:
假设参加游戏的小朋友是 A 和 B ,游戏开始的时候,他们得到的随机的纸牌序列如下:
A 方:[K,8,X,K,A,2,A,9,5,A]
B 方:[2,7,K,5,J,5,Q,6,K,4]
其中的 X 表示 "10",我们忽略了纸牌的花色。
从 A 方开始,A、B双方轮流出牌。当轮到某一方出牌时,他从自己的纸牌队列的头部拿走一张,放到桌上,并且压在最上面一张纸牌上(如果有的话)。
此例中,游戏过程:
A出K,B出2,A出8,B出7,A出X,此时桌上的序列为:K287X。
此时,轮到B出牌,当 B 出牌时,他的牌 K 与桌上的纸牌序列中的 K 相同,则把包括 K 在内的以及两个 K 之间的纸牌都赢回来,并放入自己牌的队尾。注意:为了操作方便,放入牌的顺序是与桌上的顺序相反的。
此时,𝐴、𝐵 双方的手里牌为:
A方 : [K,A,2,A,9,5,A]
B方 : [5,J,5,Q,6,K,4,K,X,7,8,2,K]
赢牌的一方继续出牌。也就是 B接着出5,A出K,B出J,A出A,B出5,又赢牌了。此时桌上的序列为:
5,K,J,A,5
此时双方手里牌:
A方 : [2,A,9,5,4]
B方 : [Q,6,K,4,K,X,7,8,2,K,5,A,J,K,5]
注意:更多的时候赢牌的一方并不能把桌上的牌都赢走,而是拿走相同牌点及其中间的部分。但无论如何,都是赢牌的一方继续出牌,有的时候刚一出牌又赢了,也是允许的。
当某一方出掉手里最后一张牌,但无法从桌面上赢取牌时,游戏立即结束。
对于本例的初始手牌情况下,最后 A 会输掉,而 B 最后的手里牌为:
9K2462KAX58K57KJ5
本题的任务就是已知双方初始牌序,计算游戏结束时,赢的一方手里的牌序。当游戏无法结束时,输出 -1。
输入描述
输入为 2 行,2个串,分别表示 A、B 双方初始手里的牌序列。我们约定,输
入的串的长度不超过 30。
输出描述
输出为 1行,1 个串,表示 A 先出牌,最后赢的一方手里的牌序。
输入输出样例
示例
输入
96J5A898QA
6278A7Q973
输出
2J9A7QA6Q6889977
问题分析
该问题分为内外两层循环:
外层循环:不断判断出牌一方出牌后的手牌数量,若为0,则判定另一方胜利,打印另一方的手牌顺序,退出循环,游戏结束;如果遇到无法终止的情况,可以设置一个较大的循环次数,循环次数满足之后退出外层循环,游戏结束。
内层循环:不断判断出牌一方的手牌中第一张是否在桌牌上已有相同点数的牌,如果有,则为赢牌,找到桌牌上相同点数的牌的位置,将从该位置一直到末尾的牌加入赢家的手牌,并将第一张手牌从当前位置移入队列末尾;如果桌牌上没有相同点数的牌,则从手牌中去除该牌并添加到桌牌的末尾。
算法步骤
1.数据初始化:
首先将输入的玩家 A 和玩家 B 的手牌字符串转换为列表 hand_a 和 hand_b。然后创建一个空列表 desktop 用于存储出到桌面上的牌。
2.出牌逻辑函数 play(hand):
该函数接收某个玩家的手牌列表 hand 作为参数。然后检查该名玩家要出的第一张手牌 hand[0] 是否在桌面上:
如果要出的第一张手牌在桌面上,通过 index 方法找到该牌在桌面上的位置 ind。
出牌准备:存储要出的牌 put_card,并从手牌中删除这张牌。
出牌:将要出的牌添加到桌面上。
赢取桌面上从最后一张到 ind 位置(不包括 ind)的牌,并将其逆序添加到玩家手牌中,同时将 put_card 也添加到手牌中。
更新桌面上的牌,去掉被赢取的部分。
赢牌的玩家继续出牌,调用 play(hand) 函数自身。
如果要出的第一张手牌不在桌面上,则将其添加到桌面上,并从手牌中删除这张牌。
3.主游戏循环:
玩家 A 先出牌,调用 play(hand_a)。玩家 A 出牌后,检查玩家 A 的手牌是否为空,若为空则玩家 B 获胜,打印玩家 B 的手牌。
玩家 B 接着出牌,调用 play(hand_b)。玩家 B 出牌后,检查玩家 B 的手牌是否为空,若为空则玩家 A 获胜,打印玩家 A 的手牌。
代码实现
感谢 @徐金亚 老师提供的代码
python
import os
import sys
# 将输入的字符串转换为列表,得到玩家 A 手中的牌列表
hand_a = list(input())
# 将输入的字符串转换为列表,得到玩家 B 手中的牌列表
hand_b = list(input())
# 出到桌面上的牌列表,初始为空
desktop = []
def play(hand):
global desktop
# 如果当前选手要出的牌 hand[0] 与桌面上的某张牌相同
if hand[0] in desktop:
# 找到桌面上这张牌的位置
ind = desktop.index(hand[0])
# 存储当前玩家要出的牌
put_card = hand[0]
# 当前玩家将手上的第 1 张牌拿出来
del hand[0:1]
# 将拿出来的牌放到桌面上
desktop.append(put_card)
# 将赢取的牌逆序放到手上,赢取的牌包括桌面上的牌从最后一张到 ind 位置的牌,以及刚刚出的那张牌
hand.extend(desktop[:ind:-1] + [put_card])
# 桌面上的牌更新,即被赢取的部分被去掉
desktop = desktop[:ind]
# 接着出牌
play(hand)
else:
# 若当前玩家出的牌不在桌面上,将其添加到桌面上
desktop.append(hand[0])
# 将手上的第 1 张牌拿出来
del hand[0:1]
while True:
# 玩家 A 出牌
play(hand_a)
# 如果玩家 A 手中无牌,则玩家 B 获胜,打印玩家 B 手中的牌
if len(hand_a) == 0:
print(''.join(hand_b))
break
# 玩家 B 出牌
play(hand_b)
# 如果玩家 B 手中无牌,则玩家 A 获胜,打印玩家 A 手中的牌
if len(hand_b) == 0:
print(''.join(hand_a))
break