程序麻将机裁判系统
下面是一个完整的程序麻将机裁判系统的实现,包含洗牌、发牌、游戏流程管理和胡牌判断等功能。
import random
from collections import defaultdict
from enum import Enum
import sys
class Suit(Enum):
"""麻将花色枚举"""
CHARACTERS = '万' # 万
BAMBOO = '条' # 条
DOTS = '筒' # 筒
HONOR = '字' # 字牌
class HonorType(Enum):
"""字牌类型枚举"""
EAST = '东'
SOUTH = '南'
WEST = '西'
NORTH = '北'
RED = '中'
GREEN = '发'
WHITE = '白'
class Tile:
"""麻将牌类"""
def __init__(self, suit, value=None, honor=None):
self.suit = suit
self.value = value # 数值牌的值(1-9)
self.honor = honor # 字牌类型
def __str__(self):
if self.suit == Suit.HONOR:
return f"{self.honor.value}"
return f"{self.value}{self.suit.value}"
def __repr__(self):
return str(self)
def __eq__(self, other):
return (self.suit == other.suit and
self.value == other.value and
self.honor == other.honor)
def __hash__(self):
return hash((self.suit, self.value, self.honor))
class Player:
"""玩家类"""
def __init__(self, name, position):
self.name = name
self.position = position # 玩家位置(东、南、西、北)
self.hand = [] # 手牌
self.melds = [] # 碰杠牌组
self.discards = [] # 弃牌
self.ready_hand = False # 是否听牌
def draw_tile(self, tile):
"""摸牌"""
self.hand.append(tile)
self.hand.sort(key=lambda t: (t.suit.value, t.value or 0, t.honor.value if t.honor else ''))
def discard_tile(self, tile):
"""打牌"""
if tile in self.hand:
self.hand.remove(tile)
self.discards.append(tile)
return tile
return None
def can_pung(self, tile):
"""是否可以碰牌"""
return sum(1 for t in self.hand if t == tile) >= 2
def pung(self, tile):
"""碰牌"""
if self.can_pung(tile):
# 移除两张相同的牌
removed = []
for _ in range(2):
for t in self.hand:
if t == tile:
self.hand.remove(t)
removed.append(t)
break
# 添加到碰牌组
self.melds.append(('碰', [removed[0], removed[1], tile]))
return True
return False
def can_kong(self, tile, from_self=False):
"""是否可以杠牌"""
count = sum(1 for t in self.hand if t == tile)
if from_self:
# 暗杠或加杠
return count == 4 or any(meld[0] == '碰' and meld[1][0] == tile for meld in self.melds)
else:
# 明杠
return count == 3
def kong(self, tile, from_self=False, from_meld=False):
"""杠牌"""
if from_self:
# 暗杠或加杠
if sum(1 for t in self.hand if t == tile) == 4:
# 暗杠
removed = [t for t in self.hand if t == tile][:4]
self.hand = [t for t in self.hand if t not in removed]
self.melds.append(('杠', removed))
return True, '暗杠'
elif from_meld:
# 加杠
for i, meld in enumerate(self.melds):
if meld[0] == '碰' and meld[1][0] == tile:
# 找到对应的碰牌组
self.melds[i] = ('杠', meld[1] + [tile])
self.hand.remove(tile)
return True, '加杠'
else:
# 明杠
if sum(1 for t in self.hand if t == tile) == 3:
# 移除三张相同的牌
removed = [t for t in self.hand if t == tile][:3]
self.hand = [t for t in self.hand if t not in removed]
# 添加到杠牌组
self.melds.append(('杠', removed + [tile]))
return True, '明杠'
return False, None
def can_win(self, tile=None):
"""检查是否可以胡牌"""
hand_to_check = self.hand.copy()
if tile:
hand_to_check.append(tile)
return is_winning_hand(hand_to_check)
def __str__(self):
return f"{self.name} ({self.position.value}): 手牌: {self.hand} 碰杠: {self.melds} 弃牌: {self.discards}"
class MahjongReferee:
"""麻将裁判系统"""
def __init__(self, players):
self.players = players
self.wall = [] # 牌墙
self.dead_wall = [] # 杠牌区
self.current_player = 0 # 当前玩家索引
self.last_discard = None # 最后一张打出的牌
self.game_over = False # 游戏是否结束
self.winner = None # 获胜者
self.dora_indicators = [] # 宝牌指示牌
self.round = 1 # 当前轮次
self.dealer = 0 # 庄家索引
def initialize_tiles(self):
"""初始化麻将牌"""
tiles = []
# 万、条、筒各36张 (1-9各4张)
for suit in [Suit.CHARACTERS, Suit.BAMBOO, Suit.DOTS]:
for value in range(1, 10):
for _ in range(4):
tiles.append(Tile(suit, value))
# 字牌各4张 (东南西北中发白)
for honor in HonorType:
for _ in range(4):
tiles.append(Tile(Suit.HONOR, honor=honor))
return tiles
def shuffle_tiles(self):
"""洗牌"""
self.wall = self.initialize_tiles()
random.shuffle(self.wall
<<上一篇
宣和麻将机传感器误判修复指南,告别误判,畅享牌局
下一篇>>
告别噪音!宣和麻将机电机异响全面解决指南