dev
parent
227800f0e8
commit
29592cd05b
|
|
@ -0,0 +1,43 @@
|
||||||
|
from src.engine.utils import try_win
|
||||||
|
|
||||||
|
def is_basic_win(hand):
|
||||||
|
# 将手牌转换为列表并按花色和数值排序
|
||||||
|
all_tiles = hand.tiles[:]
|
||||||
|
all_tiles.sort(key=lambda t: (t.suit, t.value))
|
||||||
|
|
||||||
|
# 调用递归函数检查是否符合平胡
|
||||||
|
if try_win(all_tiles):
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def is_cleared(hand, melds):
|
||||||
|
"""
|
||||||
|
检查手牌和明牌是否符合清一色的番型。
|
||||||
|
"""
|
||||||
|
# 获取手牌和明牌的所有牌
|
||||||
|
all_tiles = hand.tiles[:]
|
||||||
|
for meld in melds:
|
||||||
|
if meld.is_triplet():
|
||||||
|
all_tiles.extend([meld.tile] * 3)
|
||||||
|
elif meld.is_kong():
|
||||||
|
all_tiles.extend([meld.tile] * 4)
|
||||||
|
|
||||||
|
# 检查是否只有一种花色
|
||||||
|
suits = {tile.suit for tile in all_tiles}
|
||||||
|
if len(suits) != 1:
|
||||||
|
return 0 # 不是清一色
|
||||||
|
|
||||||
|
# 检查杠的数量
|
||||||
|
gang_count = sum(1 for meld in melds if meld.is_kong())
|
||||||
|
|
||||||
|
# 根据杠的数量和是否符合基本胡规则确定番数
|
||||||
|
sorted_tiles = sorted(all_tiles, key=lambda t: (t.suit, t.value))
|
||||||
|
if try_win(sorted_tiles): # 检查是否符合基本胡(四坎牌加一对将)
|
||||||
|
if gang_count == 0:
|
||||||
|
return 2 # 素清
|
||||||
|
elif gang_count == 1:
|
||||||
|
return 3 # 极品
|
||||||
|
elif gang_count >= 2:
|
||||||
|
return 4 # 极中极
|
||||||
|
return 0
|
||||||
|
|
@ -11,9 +11,59 @@ def get_suit(tile_index):
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"无效的牌索引: {tile_index}")
|
raise ValueError(f"无效的牌索引: {tile_index}")
|
||||||
|
|
||||||
|
|
||||||
def get_tile_name(tile_index):
|
def get_tile_name(tile_index):
|
||||||
"""
|
"""
|
||||||
根据牌的索引返回牌名(例如:1条,2筒等)。
|
根据牌的索引返回牌名(例如:1条,2筒等)。
|
||||||
"""
|
"""
|
||||||
suit = get_suit(tile_index)
|
suit = get_suit(tile_index)
|
||||||
return f"{tile_index % 36 + 1}{suit}"
|
return f"{tile_index % 36 + 1}{suit}"
|
||||||
|
|
||||||
|
|
||||||
|
def is_valid_group(tiles):
|
||||||
|
"""
|
||||||
|
判断是否是合法的刻子(AAA)或顺子(ABC)。
|
||||||
|
"""
|
||||||
|
if len(tiles) != 3:
|
||||||
|
return False
|
||||||
|
tiles.sort(key=lambda t: (t.suit, t.value)) # 按花色和数值排序
|
||||||
|
# 判断是否为刻子
|
||||||
|
if tiles[0].value == tiles[1].value == tiles[2].value and \
|
||||||
|
tiles[0].suit == tiles[1].suit == tiles[2].suit:
|
||||||
|
return True
|
||||||
|
# 判断是否为顺子
|
||||||
|
if tiles[0].value + 1 == tiles[1].value and \
|
||||||
|
tiles[1].value + 1 == tiles[2].value and \
|
||||||
|
tiles[0].suit == tiles[1].suit == tiles[2].suit:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def try_win(remaining_tiles, groups_formed=0):
|
||||||
|
"""
|
||||||
|
尝试将剩余牌分组为合法的刻子或顺子,并检查是否有一对将牌。
|
||||||
|
"""
|
||||||
|
# 如果没有剩余牌,检查是否形成了四坎牌
|
||||||
|
if not remaining_tiles:
|
||||||
|
return groups_formed == 4
|
||||||
|
|
||||||
|
# 检查是否可以找到一对将牌
|
||||||
|
for i in range(len(remaining_tiles) - 1):
|
||||||
|
if remaining_tiles[i] == remaining_tiles[i + 1]: # 找到对子
|
||||||
|
temp_tiles = remaining_tiles[:i] + remaining_tiles[i + 2:] # 移除对子
|
||||||
|
# 尝试分组剩余牌
|
||||||
|
if try_win(temp_tiles, groups_formed):
|
||||||
|
return True
|
||||||
|
|
||||||
|
# 检查是否可以形成合法组(刻子或顺子)
|
||||||
|
for i in range(len(remaining_tiles)):
|
||||||
|
for j in range(i + 1, len(remaining_tiles)):
|
||||||
|
for k in range(j + 1, len(remaining_tiles)):
|
||||||
|
group = [remaining_tiles[i], remaining_tiles[j], remaining_tiles[k]]
|
||||||
|
if is_valid_group(group):
|
||||||
|
temp_tiles = remaining_tiles[:i] + remaining_tiles[i + 1:j] + \
|
||||||
|
remaining_tiles[j + 1:k] + remaining_tiles[k + 1:]
|
||||||
|
if try_win(temp_tiles, groups_formed + 1):
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,36 @@
|
||||||
import pytest
|
import pytest
|
||||||
from src.engine.calculate_fan import calculate_fan, is_seven_pairs, is_cleared, is_big_pairs
|
from src.engine.calculate_fan import calculate_fan, is_seven_pairs, is_cleared, is_big_pairs
|
||||||
|
|
||||||
|
from src.engine.hand import Hand
|
||||||
|
from src.engine.mahjong_tile import MahjongTile
|
||||||
|
|
||||||
# 测试用例
|
# 测试用例
|
||||||
|
|
||||||
def test_basic_win():
|
def test_basic_win():
|
||||||
"""
|
"""
|
||||||
测试平胡(基本胡)计分
|
测试平胡(基本胡)计分
|
||||||
"""
|
"""
|
||||||
hand = [0] * 108
|
hand = Hand()
|
||||||
# 模拟平胡手牌: 四组顺子 + 一对将
|
# 模拟平胡手牌:四组顺子 + 一对将
|
||||||
hand[0] = 2 # 将: 两张1条
|
hand.add_tile(MahjongTile("筒", 1))
|
||||||
hand[3] = 1 # 2条
|
hand.add_tile(MahjongTile("筒", 1)) # 将
|
||||||
hand[4] = 1 # 3条
|
hand.add_tile(MahjongTile("筒", 2))
|
||||||
hand[5] = 1 # 4条
|
hand.add_tile(MahjongTile("筒", 3)) # 顺子
|
||||||
hand[10] = 1 # 5条
|
hand.add_tile(MahjongTile("筒", 4))
|
||||||
hand[11] = 1 # 6条
|
hand.add_tile(MahjongTile("筒", 5))
|
||||||
hand[12] = 1 # 7条
|
hand.add_tile(MahjongTile("筒", 6)) # 顺子
|
||||||
hand[20] = 1 # 8条
|
hand.add_tile(MahjongTile("筒", 7))
|
||||||
hand[21] = 1 # 9条
|
hand.add_tile(MahjongTile("筒", 7))
|
||||||
hand[22] = 1 # 1筒
|
hand.add_tile(MahjongTile("筒", 8))
|
||||||
hand[30] = 1 # 2筒
|
hand.add_tile(MahjongTile("筒", 9)) # 顺子
|
||||||
hand[31] = 1 # 3筒
|
hand.add_tile(MahjongTile("万", 1))
|
||||||
|
hand.add_tile(MahjongTile("万", 2))
|
||||||
|
hand.add_tile(MahjongTile("万", 3)) # 顺子
|
||||||
|
|
||||||
melds = []
|
melds = []
|
||||||
conditions = {}
|
conditions = {}
|
||||||
|
|
||||||
fan = calculate_fan(hand, melds, is_self_draw=False, is_cleared=False, conditions=conditions)
|
fan = calculate_fan(hand.tiles, melds, is_self_draw=False, is_cleared=False, conditions=conditions)
|
||||||
assert fan == 1, f"Expected 1 fan, got {fan}"
|
assert fan == 1, f"Expected 1 fan, got {fan}"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
from src.engine.hand import Hand
|
||||||
|
from src.engine.mahjong_tile import MahjongTile
|
||||||
|
from src.engine.fan_type import is_basic_win,is_cleared
|
||||||
|
from src.engine.meld import Meld
|
||||||
|
|
||||||
|
def test_is_basic_win():
|
||||||
|
"""
|
||||||
|
测试平胡(基本胡)的逻辑。
|
||||||
|
"""
|
||||||
|
hand = Hand()
|
||||||
|
# 添加牌到手牌中
|
||||||
|
hand.add_tile(MahjongTile("筒", 5))
|
||||||
|
hand.add_tile(MahjongTile("筒", 5))
|
||||||
|
hand.add_tile(MahjongTile("筒", 1))
|
||||||
|
hand.add_tile(MahjongTile("筒", 2))
|
||||||
|
hand.add_tile(MahjongTile("筒", 3))
|
||||||
|
hand.add_tile(MahjongTile("筒", 4))
|
||||||
|
hand.add_tile(MahjongTile("筒", 5))
|
||||||
|
hand.add_tile(MahjongTile("筒", 6))
|
||||||
|
hand.add_tile(MahjongTile("筒", 7))
|
||||||
|
hand.add_tile(MahjongTile("筒", 8))
|
||||||
|
hand.add_tile(MahjongTile("筒", 9))
|
||||||
|
hand.add_tile(MahjongTile("万", 3))
|
||||||
|
hand.add_tile(MahjongTile("万", 4))
|
||||||
|
hand.add_tile(MahjongTile("万", 5))
|
||||||
|
|
||||||
|
# 打印当前手牌
|
||||||
|
print(f"测试手牌: {hand}")
|
||||||
|
|
||||||
|
# 调用平胡逻辑函数
|
||||||
|
result = is_basic_win(hand)
|
||||||
|
|
||||||
|
# 使用断言验证
|
||||||
|
assert result, "测试失败:此手牌应该符合平胡(基本胡)规则"
|
||||||
|
print("测试通过:平胡(基本胡)逻辑正确")
|
||||||
|
|
||||||
|
def test_is_cleared_basic():
|
||||||
|
"""测试素清(不带杠的清一色)"""
|
||||||
|
hand = Hand()
|
||||||
|
# 添加手牌
|
||||||
|
hand.add_tile(MahjongTile("筒", 1))
|
||||||
|
hand.add_tile(MahjongTile("筒", 2))
|
||||||
|
hand.add_tile(MahjongTile("筒", 3))
|
||||||
|
hand.add_tile(MahjongTile("筒", 4))
|
||||||
|
hand.add_tile(MahjongTile("筒", 5))
|
||||||
|
hand.add_tile(MahjongTile("筒", 6))
|
||||||
|
hand.add_tile(MahjongTile("筒", 7))
|
||||||
|
hand.add_tile(MahjongTile("筒", 8))
|
||||||
|
hand.add_tile(MahjongTile("筒", 9))
|
||||||
|
hand.add_tile(MahjongTile("筒", 4))
|
||||||
|
hand.add_tile(MahjongTile("筒", 5))
|
||||||
|
hand.add_tile(MahjongTile("筒", 6))
|
||||||
|
hand.add_tile(MahjongTile("筒", 9))
|
||||||
|
hand.add_tile(MahjongTile("筒", 9))
|
||||||
|
|
||||||
|
melds = [] # 无杠
|
||||||
|
assert is_cleared(hand, melds) == 2, "测试失败:素清应为 2 番"
|
||||||
|
print("测试通过:素清")
|
||||||
|
|
||||||
|
def test_is_cleared_with_one_gang():
|
||||||
|
"""测试极品(带 1 杠的清一色)"""
|
||||||
|
hand = Hand()
|
||||||
|
# 添加手牌
|
||||||
|
hand.add_tile(MahjongTile("筒", 1))
|
||||||
|
hand.add_tile(MahjongTile("筒", 2))
|
||||||
|
hand.add_tile(MahjongTile("筒", 3))
|
||||||
|
hand.add_tile(MahjongTile("筒", 4))
|
||||||
|
hand.add_tile(MahjongTile("筒", 5))
|
||||||
|
hand.add_tile(MahjongTile("筒", 6))
|
||||||
|
hand.add_tile(MahjongTile("筒", 4))
|
||||||
|
hand.add_tile(MahjongTile("筒", 5))
|
||||||
|
hand.add_tile(MahjongTile("筒", 6))
|
||||||
|
hand.add_tile(MahjongTile("筒", 9))
|
||||||
|
hand.add_tile(MahjongTile("筒", 9))
|
||||||
|
|
||||||
|
melds = [Meld(MahjongTile("筒", 7), "杠")] # 带 1 杠
|
||||||
|
assert is_cleared(hand, melds) == 3, "测试失败:极品应为 3 番"
|
||||||
|
print("测试通过:极品")
|
||||||
|
|
||||||
Loading…
Reference in New Issue