Python中的MjViewer()函数:可视化麻将游戏回放
发布时间:2024-01-04 14:10:18
MjViewer()函数是Python中一个可视化麻将游戏回放的函数,它可以将麻将游戏的历史记录转化为一个可视化的动画。这个函数是基于Python的matplotlib库实现的,可以用来展示麻将游戏的每一步操作,包括玩家的出牌、吃碰杠等操作,以及显示当前的手牌情况和计分情况。
下面是一个使用MjViewer()函数的例子:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from matplotlib.animation import FuncAnimation
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
def MjViewer(playback):
# 创建游戏画面
fig, ax = plt.subplots(figsize=(8, 8), dpi=80)
ax.set_xlim(0, 10)
ax.set_ylim(0, 10)
ax.axis('off')
# 定义牌的图片路径和大小
mahjong_images = {
# 万
'1m': ('mahjong_images/1m.png', [0.06, 0.035]),
'2m': ('mahjong_images/2m.png', [0.06, 0.035]),
# 条
'1s': ('mahjong_images/1s.png', [0.06, 0.035]),
'2s': ('mahjong_images/2s.png', [0.06, 0.035]),
# 饼
'1p': ('mahjong_images/1p.png', [0.06, 0.035]),
'2p': ('mahjong_images/2p.png', [0.06, 0.035]),
# 字牌
'dong': ('mahjong_images/dong.png', [0.08, 0.05]),
'xi': ('mahjong_images/xi.png', [0.08, 0.05]),
'nan': ('mahjong_images/nan.png', [0.08, 0.05]),
'bei': ('mahjong_images/bei.png', [0.08, 0.05]),
}
def update(frame):
ax.clear()
# 绘制玩家手牌
player_hand = playback[frame]['player_hand']
draw_hand(player_hand, 1, 1.5, 5, 1)
# 绘制其他玩家的手牌
for i, other_hand in enumerate(playback[frame]['other_hands']):
draw_hand(other_hand, 1, 8.5 - i * 1.5, 13, 1)
# 绘制牌堆
draw_tiles(playback[frame]['tiles'], 2.5, 1, 1)
# 绘制弃牌堆
draw_tiles(playback[frame]['discard_pile'], 6.5, 1, 1)
# 绘制当前操作
current_action = playback[frame]['current_action']
if current_action:
action_string = f"玩家{current_action['player']} "
if current_action['type'] == 'discard':
action_string += f"出牌 {current_action['tile']}"
elif current_action['type'] == 'draw':
action_string += "摸牌"
elif current_action['type'] == 'pong':
action_string += f"碰 {current_action['tile']}"
elif current_action['type'] == 'chow':
action_string += f"吃 {current_action['chow_tiles']}"
elif current_action['type'] == 'kong':
action_string += f"杠 {current_action['kong_tiles']}"
ax.text(4, 9, action_string, fontsize=10)
def draw_hand(hand, x, y, width, height):
for i, tile in enumerate(hand):
mahjong_image = mahjong_images[tile]
mahjong_path = mahjong_image[0]
mahjong_size = mahjong_image[1]
x_offset = mahjong_size[0] * i
y_offset = mahjong_size[1] * i
x_pos = x + x_offset
y_pos = y - y_offset
image = OffsetImage(plt.imread(mahjong_path), zoom=1)
ab = AnnotationBbox(image, (x_pos, y_pos), frameon=False)
ax.add_artist(ab)
def draw_tiles(tiles, x, y, rows):
nrows = len(tiles) // rows
for i, tile in enumerate(tiles):
tile_image = mahjong_images[tile]
tile_path = tile_image[0]
tile_size = tile_image[1]
row = i % rows
col = i // rows
x_pos = x + tile_size[0] * row
y_pos = y - tile_size[1] * col
image = OffsetImage(plt.imread(tile_path), zoom=1)
ab = AnnotationBbox(image, (x_pos, y_pos), frameon=False)
ax.add_artist(ab)
# 创建动画
anim = FuncAnimation(fig, update, frames=len(playback), interval=1000, repeat=False)
plt.show()
使用上述的MjViewer()函数,我们可以播放一个麻将游戏的回放。下面是一个示例的游戏回放数据:
playback = [
{
'player_hand': ['1m', '2m', '1s', '2s', '1p', '2p', 'dong', 'xi', 'nan', 'bei'],
'other_hands': [['1m', '2m', '1s', '2s', '1p', '2p', 'dong', 'nan', 'bei'],
['1m', '2m', '1s', '2s', '1p', '2p', 'xi', 'dong', 'nan'],
['1m', '2m', '1s', '2s', '1p', '2p', 'bei', 'xi', 'dong']],
'tiles': ['1m', '2m', '1s', '2s', '1p', '2p', 'dong', 'xi', 'nan', 'bei'],
'discard_pile': [],
'current_action': {'player': 1, 'type': 'draw'},
},
{
'player_hand': ['1m', '2m', '1s', '2s', '1p', '2p', 'dong', 'xi', 'bei'],
'other_hands': [['1m', '2m', '1s', '2s', '1p', '2p', 'dong', 'nan', 'bei'],
['1m', '2m', '1s', '2s', '1p', '2p', 'xi', 'dong', 'nan'],
['1m', '2m', '1s', '2s', '1p', '2p', 'bei', 'xi', 'dong']],
'tiles': ['1m', '2m', '1s', '2s', '1p', '2p', 'dong', 'xi', 'nan'],
'discard_pile': ['bei'],
'current_action': {'player': 1, 'type': 'discard', 'tile': 'nan'},
},
...
]
以上代码中的playback列表记录了游戏的每一步操作。每个元素表示一个回合的数据,包括玩家手牌(player_hand)、其他玩家手牌(other_hands)、牌堆(tiles)、弃牌堆(discard_pile)和当前操作(current_action)。
使用MjViewer()函数,我们可以将上述的回放数据进行可视化展示。运行下面的代码即可播放麻将游戏的回放动画:
MjViewer(playback)
在动画中,我们可以观察到玩家的手牌、其他玩家的手牌、牌堆、弃牌堆以及当前操作的变化。
