Compare commits

...

2 Commits

Author SHA1 Message Date
b5bad05205 1 2024-11-30 13:56:34 +08:00
2292729566 Update chengdu_mahjong_engine.py 2024-11-30 13:41:00 +08:00
4 changed files with 90 additions and 65 deletions

View File

@@ -1,13 +1,40 @@
def draw_tile(state):
"""
当前玩家摸牌的动作逻辑。
参数:
- state: ChengduMahjongState 实例,表示当前游戏状态。
返回:
- tile: 当前玩家摸到的牌的索引。
异常:
- ValueError: 如果牌堆已经空了(流局条件)。
"""
if state.remaining_tiles == 0:
raise ValueError("牌堆已空")
tile = state.deck.pop(0)
state.remaining_tiles -= 1
state.hands[state.current_player][tile] += 1
raise ValueError("牌堆已空") # 牌堆为空时不能摸牌
tile = state.deck.pop(0) # 从牌堆顶取出一张牌
state.remaining_tiles -= 1 # 更新牌堆剩余数量
state.hands[state.current_player][tile] += 1 # 将摸到的牌添加到当前玩家的手牌中
return tile
def discard_tile(state, tile):
"""
当前玩家打出一张牌的动作逻辑。
参数:
- state: ChengduMahjongState 实例,表示当前游戏状态。
- tile: 玩家想要打出的牌的索引。
操作:
- 从当前玩家手牌中移除指定的牌。
- 将指定牌添加到当前玩家的牌河中。
异常:
- ValueError: 如果当前玩家的手牌中没有这张牌。
"""
if state.hands[state.current_player][tile] == 0:
raise ValueError("玩家没有这张牌")
state.hands[state.current_player][tile] -= 1
state.discards[state.current_player].append(tile)
raise ValueError("玩家没有这张牌") # 防止打出不存在的牌
state.hands[state.current_player][tile] -= 1 # 从手牌中移除该牌
state.discards[state.current_player].append(tile) # 将牌添加到牌河

View File

@@ -1,5 +1,4 @@
from .game_state import ChengduMahjongState
from .utils import get_suit
class ChengduMahjongEngine:
@@ -44,53 +43,11 @@ class ChengduMahjongEngine:
else:
raise ValueError("杠牌条件不满足")
# 设置缺门
def set_missing_suit(player, missing_suit):
# 确定玩家的缺门
valid_suits = ["", "", ""]
if missing_suit not in valid_suits:
raise ValueError("缺门设置无效")
player.missing_suit = missing_suit
# 判断是否可以流局
def check_blood_battle(self):
if len(self.winners) >= 3 or self.state.remaining_tiles == 0:
self.game_over = True
# 判断是否可以胡牌
def can_win(hand):
# 判断是否满足胡牌条件(四组+一对)
from collections import Counter
# 判断缺一门
suits = [get_suit(tile) for tile, count in enumerate(hand) if count > 0]
if len(set(suits)) > 2:
return False # 不满足缺一门
# 判断是否满足四组+一对
def is_valid_group(tiles):
# 判断是否为顺子、刻子或对子
return len(tiles) == 3 and (tiles[0] == tiles[1] == tiles[2] or
tiles[0] + 1 == tiles[1] and tiles[1] + 1 == tiles[2])
counter = Counter(hand)
pairs = [tile for tile, count in counter.items() if count >= 2]
for pair in pairs:
temp_hand = hand[:]
temp_hand[pair] -= 2
if is_valid_group(temp_hand):
return True
return False
# 计算番数
def calculate_fan(hand, melds, is_self_draw, is_cleared):
fan = 1 # 基本胡
if is_cleared:
fan += 2 # 清一色
if len(melds) >= 2:
fan += len(melds) # 根据杠加番
if is_self_draw:
fan += 1 # 自摸加番
return fan
def check_blood_battle(self):
"""
检查游戏是否流局或血战结束。
如果满足结束条件,设置 self.game_over 为 True。
"""
if len(self.state.winners) >= 3 or self.state.remaining_tiles == 0:
print(f"游戏结束,赢家列表: {self.state.winners}")
self.game_over = True

View File

@@ -1,3 +1,5 @@
from utils import get_suit
class ChengduMahjongState:
def __init__(self):
# 每个玩家的手牌
@@ -14,3 +16,34 @@ class ChengduMahjongState:
self.remaining_tiles = 108
# 胜利玩家列表
self.winners = []
def set_missing_suit(player, missing_suit):
# 确定玩家的缺门
valid_suits = ["", "", ""]
if missing_suit not in valid_suits:
raise ValueError("缺门设置无效")
player.missing_suit = missing_suit
def can_win(hand):
# 判断是否满足胡牌条件(四组+一对)
from collections import Counter
# 判断缺一门
suits = [get_suit(tile) for tile, count in enumerate(hand) if count > 0]
if len(set(suits)) > 2:
return False # 不满足缺一门
# 判断是否满足四组+一对
def is_valid_group(tiles):
# 判断是否为顺子、刻子或对子
return len(tiles) == 3 and (tiles[0] == tiles[1] == tiles[2] or
tiles[0] + 1 == tiles[1] and tiles[1] + 1 == tiles[2])
counter = Counter(hand)
pairs = [tile for tile, count in counter.items() if count >= 2]
for pair in pairs:
temp_hand = hand[:]
temp_hand[pair] -= 2
if is_valid_group(temp_hand):
return True
return False

View File

@@ -1,13 +1,21 @@
def can_win(hand):
# 判断是否满足胡牌条件
...
# 计算番数逻辑
def calculate_fan(hand, melds, is_self_draw, is_cleared):
"""
根据胡牌手牌、碰杠、是否自摸等情况计算番数。
参数:
- hand: 当前胡牌的手牌
- melds: 碰杠等明牌列表
- is_self_draw: 是否自摸
- is_cleared: 是否清一色
返回:
- fan: 计算出的番数
"""
fan = 1 # 基本胡
if is_cleared:
fan += 2 # 清一色
fan += 2 # 清一色加番
if len(melds) >= 2:
fan += len(melds)
fan += len(melds) # 每次碰杠额外加番
if is_self_draw:
fan += 1
fan += 1 # 自摸加番
return fan