namespace RuleEngine.Core; /// Mahjong tile int encoding + static utilities public static class MahjongTile { // Encoding: 万1-9=1-9, 条1-9=11-19, 筒1-9=21-29 // 字: 东=31,南=32,西=33,北=34,中=35,发=36,白=37 // 花: 春=41..菊=48 // 宝牌: 50-59 public static int Encode(string suit, int rank) { return suit switch { "万" => rank, "条" => 10 + rank, "筒" => 20 + rank, _ => throw new ArgumentException($"Unknown suit: {suit}") }; } public static string ToString(int tile) { if (tile >= 1 && tile <= 9) return $"{tile}万"; if (tile >= 11 && tile <= 19) return $"{tile - 10}条"; if (tile >= 21 && tile <= 29) return $"{tile - 20}筒"; return tile switch { 31 => "东", 32 => "南", 33 => "西", 34 => "北", 35 => "中", 36 => "发", 37 => "白", 41 => "春", 42 => "夏", 43 => "秋", 44 => "冬", 45 => "梅", 46 => "兰", 47 => "竹", 48 => "菊", >= 50 and <= 59 => "🃏", _ => $"?{tile}" }; } /// 0=万, 1=条, 2=筒, 3=字, 4=花, 5=宝牌 public static int Suit(int tile) { if (tile >= 1 && tile <= 9) return 0; if (tile >= 11 && tile <= 19) return 1; if (tile >= 21 && tile <= 29) return 2; if (tile >= 31 && tile <= 37) return 3; if (tile >= 41 && tile <= 48) return 4; if (tile >= 50 && tile <= 59) return 5; return -1; } public static int Rank(int tile) { if (tile >= 1 && tile <= 9) return tile; if (tile >= 11 && tile <= 19) return tile - 10; if (tile >= 21 && tile <= 29) return tile - 20; if (tile >= 31 && tile <= 37) return tile; if (tile >= 41 && tile <= 48) return tile; return tile; } public static string SuitName(int suit) => suit switch { 0 => "万", 1 => "条", 2 => "筒", 3 => "字", 4 => "花", 5 => "宝牌", _ => "?" }; public static bool IsHonor(int tile) => tile >= 31 && tile <= 37; public static bool IsFlower(int tile) => tile >= 41 && tile <= 48; public static bool IsWildcard(int tile) => tile >= 50 && tile <= 59; public static bool IsNumbered(int tile) => tile >= 1 && tile <= 29; public static bool IsTerminal(int tile) { if (IsHonor(tile)) return true; if (IsNumbered(tile)) { int r = Rank(tile); return r == 1 || r == 9; } return false; } public static bool SameSuit(int a, int b) => Suit(a) == Suit(b); public const int WildcardBase = 50; public static int[] AllTiles(bool includeHonors = false, bool includeFlowers = false, int wildcardCount = 0) { int count = 27 + (includeHonors ? 7 : 0) + (includeFlowers ? 8 : 0) + wildcardCount; var tiles = new int[count]; int idx = 0; for (int i = 1; i <= 9; i++) tiles[idx++] = i; for (int i = 1; i <= 9; i++) tiles[idx++] = 10 + i; for (int i = 1; i <= 9; i++) tiles[idx++] = 20 + i; if (includeHonors) { for (int i = 31; i <= 37; i++) tiles[idx++] = i; } if (includeFlowers) { for (int i = 41; i <= 48; i++) tiles[idx++] = i; } for (int i = 0; i < wildcardCount; i++) tiles[idx++] = WildcardBase + i; return tiles; } }