#P7147. [THUPC2021 初赛] 麻将模拟器
[THUPC2021 初赛] 麻将模拟器
题目描述
麻将是一种休闲的四人博弈游戏。你的任务是写一个模拟器来模拟一局游戏的进程。
接下来将详细介绍游戏规则和每个玩家的决策。注意:为了实现方便和使游戏更加有趣味,这里介绍的规则和主流的几种麻将规则均略有不同。
基础规则:
- 一副麻将由 张牌组成,其中包含 种不同的牌,每种各 张。
- 这 种牌分别是:一万到九万(
1M ~ 9M
)、一筒到九筒(1P ~ 9P
)、一索到九索(1S ~ 9S
)、东(E
)、南(S
)、西(W
)、北(N
)、白(B
)、发(F
)、中(Z
),以及 种特殊牌:跳过(PASS
),反向(REVERSE
),双重回合(DOUBLE
)。 - 游戏共有 名玩家,不妨称其为
A
,B
,C
,D
。 - 游戏开始前,将 张牌随机洗乱后摆成一排,称为牌堆。此后玩家摸牌一定是从牌堆中摸取最靠前的一张牌。
- 从
A
开始按照ABCDABCD...
的顺序,每人依次从牌堆中摸一张牌,直到每人都有 张牌,这些牌组成每个玩家的手牌。 - 再从
A
开始按照ABCDABCD...
的顺序,依次进入每人的回合: - 在一个回合中,玩家先摸一张牌进入自己的手牌,再从自己的手牌中打出一张牌。
- 依次进行直到有人和牌或者无牌可摸时游戏结束。
特殊牌:
- 跳过(
PASS
):在出牌时打出这张牌,可以指定一名玩家,跳过他的下一个回合。 - 反向(
REVERSE
):在出牌时打出这张牌,反转进行回合的顺序,即由ABCDABCD...
变为ADCBADCB...
或由ADCBADCB...
变为ABCDABCD...
。出牌后即按照反转后的顺序,从出牌者原先的上家开始进行回合。 - 双重回合(
DOUBLE
):在出牌时打出这张牌,该名玩家立即进入一个额外的回合。
牌型:有如下 种牌型:
- 顺子: 张数字连续的万,或 张数字连续的筒,或 张数字连续的索,如
4P 5P 6P
。 - 刻子: 张完全一样的非特殊牌,如
B B B
。 - 对子: 张完全一样的非特殊牌,如
9M 9M
。
吃、碰:
- 当一名玩家打出一张非特殊牌时,其他玩家可以进行吃或碰:
- 吃(
CHOW
):当打出的这张牌跟自己的手牌中的某两张牌能组成一个顺子时,可以将手牌中能与之组成顺子的其余两张牌取出,与这张牌一起摆在旁边。 - 注意只有上一名出牌玩家的下家(按当前顺序原本应在下一个进行回合的玩家)才能吃。
- 碰(
PONG
):当打出的这张牌跟自己的手牌中的某两张牌能组成一个刻子时,可以将手牌中能与之组成刻子的其余两张牌取出,与这张牌一起摆在旁边。 - 碰没有吃的上述限制,任意其他玩家都能碰。
- 如果既有玩家能吃又有玩家能碰,则碰优先于吃。
- 吃(或碰)不是强制性的,也就是说玩家满足吃(或碰)的条件时,可以选择不吃(或碰)。
- 吃和碰统称为副露。为方便起见,不将副露视为手牌的一部分。
- 在任意一名玩家吃(或碰)后,跳过从上一名出牌的玩家到这名玩家之间的所有玩家的回合,直接从当前玩家开始进行新的回合。但该玩家在这一回合中跳过摸牌直接出牌,在下一回合(如果没有吃碰的话)恢复正常。
- 注意在本规则中不能杠。
胡牌规则:
- 称一名玩家的牌能和,当且仅当满足如下条件:
- 牌数为 ,其中 为该玩家副露(即吃碰)的个数;
- 这些牌中无特殊牌;
- 这些牌能够被分成 组,其中 组均为 张且均为顺子或刻子,其余一组为 张且为对子。
- 注意本规则中不支持七对子、十三幺、全不靠等特殊的和牌规则。
- 另外,定义一组包含 张牌的手牌的和牌距离为最小的 ,使得向这些牌中加入特定的 张牌,再去掉 张手牌后,每种牌仍不超过 张且能和。
- 定义一组包含 张牌的手牌的和牌距离为最小的 ,使得向这些牌中加入特定的 张牌,再去掉 张手牌后,每种牌仍不超过 张且能和。
- 特别地,一手能和的牌的和牌距离为 ;和牌距离为 的牌称为听牌。
- 注意这里的“每种牌仍不超过 张”的限制:如果一手牌是
1M 1M 1M 1M
且副露数为 ,再向其中加入一张1M
就能和,但是由于有 张1M
所以是不被允许的,故不认为其和牌距离为 。 - 但如果一手牌是
1M
且副露数为 ,但是曾进行过一次1M 1M 1M
的碰,仍然认为其和牌距离为 (虽然缺的这张1M
永远也等不到)。
终局:
- 荣和(
RON
):当一名玩家出牌后,某名其他玩家的手牌加上这张牌能和,则称这名玩家荣和。荣和优先于吃碰。 - 如果有多名玩家同时达到荣和的标准,规定只有从上一名出牌玩家开始,沿回合进行顺序的第一名能荣和的玩家才能荣和,其余玩家荣和不了,称这种情况为截和。
- 自摸(
SELFDRAWN
):一名玩家摸牌后其手牌能和,称这名玩家自摸。 - 一旦有一名玩家荣和或自摸,游戏立即结束,该名玩家胜利。
- 如果某名玩家摸牌时发现牌堆中已经无牌可摸,游戏立即结束,称此种情况为流局。
出牌策略:每名玩家的出牌策略相同且固定:
- 出牌时,若手里有特殊牌一定会优先出,且如果有多种特殊牌,按照
PASS
、REVERSE
、DOUBLE
的优先顺序;出的PASS
一定指定下家。 - 出牌时若手里没有特殊牌,则会对于每一种可能的出牌方法计算出完牌后的和牌距离,选择和牌距离最小的一种方案。如果有并列最小,按照
Z
,F
,B
,N
,W
,S
,E
,9S
,8S
,……,1S
,9P
,……,1P
,9M
,……,1M
的优先顺序出牌。 - 同一个人能吃且能碰时,优先考虑碰;因为每种牌只有 张所以不会有两名玩家同时可以碰的情况;当且仅当吃(或碰)后能使得和牌距离严格减小才会去吃(或碰);如果有多种吃的方案使得和牌距离严格减小,优先选择数字较大的方案。
- 能荣和一定荣和(除非被截和),能自摸一定自摸,不会拒和(能和时故意选择不和)。
输入格式
输入共 行,按照牌堆从前到后的顺序输入每一张牌。
每行输入一个字符串表示这一张牌。
用 1M
,2M
,……,9M
代表万,1P
,2P
,……,9P
代表筒,1S
,2S
,……,9S
代表索,E
,S
,W
,N
,B
,F
,Z
分别代表东、南、西、北、白、发、中,PASS
代表跳过,REVERSE
表示反向,DOUBLE
表示双重回合。
输出格式
按照如下几条规则进行输出:
- 当任意一名玩家摸牌时(包括游戏最开始的摸牌),输出一行:
x IN y
其中x
为玩家名称,y
为摸到的牌。 - 当任意一名玩家出牌时,如果出的牌不是
PASS
,输出一行:
x OUT y
其中x
为玩家名称,y
为出的牌。
如果出的牌是PASS
,应当输出一行:
x OUT PASS z
其中z
为PASS
指定的对象。 - 当任意一名玩家吃时,输出一行:
x CHOW y1 y2 y3
其中x
为玩家名称,y1
,y2
,y3
为吃涉及到的 张牌,按数字递增的顺序输出。 - 当任意一名玩家碰时,输出一行:
x PONG y1 y2 y3
其中x
为玩家名称,y1
,y2
,y3
为碰涉及到的 张牌,根据碰的规则,y1
,y2
,y3
应相同。 - 当任意一名玩家荣和时,输出一行:
x RON
其中x
为玩家名称。 - 当任意一名玩家自摸时,输出一行:
x SELFDRAWN
其中x
为玩家名称。 - 游戏的最后,如果某名玩家获得胜利,输出一行:
x WIN
其中x
为玩家名称。
如果出现流局,输出一行:
DRAW
需要特别注意的是,输入输出中出现的英文字母均为大写。
8M
Z
E
9P
3P
9S
5P
W
3M
8P
DOUBLE
5P
Z
2P
3M
8S
2S
5P
5M
E
6M
9S
6P
5S
7M
4S
3S
6M
3S
2M
9M
5S
Z
7P
5P
8M
3M
F
7M
2S
N
4P
3S
S
PASS
1P
6S
3P
9P
9S
4M
8P
N
Z
N
5M
DOUBLE
REVERSE
S
3P
4M
4S
1S
PASS
4P
6S
7S
7P
6S
9M
REVERSE
3P
7P
DOUBLE
B
9P
4S
5S
7S
7S
7P
6S
9S
B
9M
S
F
2P
1P
PASS
9P
DOUBLE
4P
PASS
5S
2M
2P
6P
W
1M
8S
REVERSE
8M
6M
5M
F
4M
F
8P
2S
1M
2M
3M
7M
3S
B
7S
1S
REVERSE
8P
6M
4S
2M
B
1M
S
6P
5M
W
7M
2S
8S
8M
1S
4P
E
4M
9M
1M
8S
1S
1P
2P
1P
W
6P
N
E
A IN 8M
B IN Z
C IN E
D IN 9P
A IN 3P
B IN 9S
C IN 5P
D IN W
A IN 3M
B IN 8P
C IN DOUBLE
D IN 5P
A IN Z
B IN 2P
C IN 3M
D IN 8S
A IN 2S
B IN 5P
C IN 5M
D IN E
A IN 6M
B IN 9S
C IN 6P
D IN 5S
A IN 7M
B IN 4S
C IN 3S
D IN 6M
A IN 3S
B IN 2M
C IN 9M
D IN 5S
A IN Z
B IN 7P
C IN 5P
D IN 8M
A IN 3M
B IN F
C IN 7M
D IN 2S
A IN N
B IN 4P
C IN 3S
D IN S
A IN PASS
B IN 1P
C IN 6S
D IN 3P
A IN 9P
B IN 9S
C IN 4M
D IN 8P
A IN N
A OUT PASS B
C IN Z
C OUT DOUBLE
C IN N
C OUT Z
A PONG Z Z Z
A OUT 9P
B CHOW 7P 8P 9P
B OUT Z
C IN 5M
C OUT N
A PONG N N N
A OUT 3P
B CHOW 3P 4P 5P
B OUT F
C IN DOUBLE
C OUT DOUBLE
C IN REVERSE
C OUT REVERSE
B IN S
B OUT S
A IN 3P
A OUT 3P
D IN 4M
D OUT W
C IN 4S
C OUT E
B IN 1S
B OUT 4S
A RON
A WIN
提示
【题目来源】
来自 2021 清华大学学生程序设计竞赛暨高校邀请赛(THUPC2021)初赛。
题解等资源可在 https://github.com/THUSAAC/THUPC2021-pre 查看。