From b87139588410c57b9c3994846346c70df7b90ea0 Mon Sep 17 00:00:00 2001 From: xiaoou Date: Sat, 4 Jul 2026 11:22:46 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BA=A4=E4=BA=92=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E9=80=90=E5=9B=9E=E5=90=88=E5=B1=95=E7=A4=BA=20+=20Deal()?= =?UTF-8?q?=E5=85=AC=E5=BC=80=20+=20=E5=8F=91=E7=89=8C=E8=BE=93=E5=87=BA?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题: 1. 交互模式 Run() 直接跑完整局,只渲染最终状态 2. RenderGame 手牌.OrderBy()排序,洗牌后仍显顺序 3. 牌墙剩余显示0因为游戏已跑完 修复: - 交互模式: room.Deal()→RenderDeal→逐回合StepTurn+ReadLine - 发牌输出: 显示每人张数 + 牌墙剩余,不排序手牌 - 每回合: 显示事件(摸/打/碰/杠/胡) + 当前手牌 - Run()保留用于自动模式 --- Demo/Program.cs | 147 ++++++++++++++++++++++++++++---------- RuleEngine/MahjongRoom.cs | 2 +- 2 files changed, 112 insertions(+), 37 deletions(-) diff --git a/Demo/Program.cs b/Demo/Program.cs index 428dfb0..d6f0c10 100644 --- a/Demo/Program.cs +++ b/Demo/Program.cs @@ -43,12 +43,10 @@ catch (Exception ex) return 1; } -Console.WriteLine($"=== 麻将规则引擎 Demo — {rules.Game.Name} === ({(autoMode ? "自动模式" : "交互模式")})"); -Console.WriteLine(); - if (autoMode) { - // Batch mode: run N rounds + // Batch mode: run N rounds silently + Console.WriteLine($"=== 麻将规则引擎 Demo — {rules.Game.Name} === (自动模式 {count}局)"); int wins = 0, errors = 0; var stopwatch = System.Diagnostics.Stopwatch.StartNew(); @@ -78,53 +76,130 @@ if (autoMode) } else { - // Interactive mode: single game with full output - var room = new MahjongRoom(rules, new[] { "AI-东", "AI-南", "AI-西", "AI-北" }, autoMode: false); - room.Run(); + // Interactive mode: step-by-step with key-press advancement + Console.WriteLine($"=== 麻将规则引擎 Demo — {rules.Game.Name} === (交互模式,按 Enter 继续下一步)"); + Console.WriteLine(); - RenderGame(room); + var room = new MahjongRoom(rules, new[] { "AI-东", "AI-南", "AI-西", "AI-北" }, autoMode: false); + room.Deal(); + + // Show dealt hands + RenderDeal(room); + Console.Write("\n[按 Enter 开始对局]"); + Console.ReadLine(); + + // Step through each turn + int turnNumber = 0; + while (!room.IsFinished) + { + turnNumber++; + var events = room.StepTurn(); + + // Skip deal phase transition + if (room.State.Phase == "deal") continue; + + Console.WriteLine($"\n--- 第 {turnNumber} 回合 | 牌墙剩余 {room.State.Deck.Count} 张 ---"); + + // Show events for this turn + foreach (var evt in events) + { + switch (evt.Type) + { + case "draw": + Console.WriteLine($" [{evt.Player}] 摸牌: {MahjongTile.ToString(evt.Tile ?? 0)}"); + break; + case "discard": + Console.WriteLine($" [{evt.Player}] 出牌: {MahjongTile.ToString(evt.Tile ?? 0)}"); + break; + case "pung": + Console.WriteLine($" → {evt.Player}: 碰!{MahjongTile.ToString(evt.Tile ?? 0)}"); + break; + case "ming_kong": + Console.WriteLine($" → {evt.Player}: 明杠!{MahjongTile.ToString(evt.Tile ?? 0)}"); + break; + case "win": + Console.WriteLine($" ✅ {evt.Player}: 胡!{evt.Description}"); + break; + case "deck_exhausted": + Console.WriteLine($" ⚠ 牌墙耗尽!"); + break; + case "hua_zhu": + Console.WriteLine($" ⚠ {evt.Player}: 花猪(三色齐全)"); + break; + case "hua_zhu_ok": + break; + case "ting_checked": + Console.WriteLine($" ✓ {evt.Player}: 听牌"); + break; + case "ting_failed": + Console.WriteLine($" ✗ {evt.Player}: 未听牌"); + break; + case "settle": + Console.WriteLine($" 💰 结算"); + break; + } + } + + // Show current hands + if (!room.IsFinished) + { + Console.WriteLine(); + Console.WriteLine(" 当前手牌:"); + foreach (var p in room.State.PlayerOrder) + { + if (!room.State.AlivePlayers.Contains(p)) continue; + var hand = room.State.Hands[p]; + Console.WriteLine($" {p}: {string.Join(" ", hand.OrderBy(t => t).Select(MahjongTile.ToString))} ({hand.Count}张)"); + } + + Console.Write("\n[按 Enter 继续]"); + Console.ReadLine(); + } + } + + // Final render + Console.WriteLine("\n══════════════════════════════════════"); + RenderFinal(room); } return 0; -void RenderGame(MahjongRoom room) +void RenderDeal(MahjongRoom room) { var state = room.State; - - Console.WriteLine("══════════════════════════════════════"); - Console.WriteLine("[发牌]"); + Console.WriteLine("═══ 发牌 ═══"); foreach (var p in state.PlayerOrder) - Console.WriteLine($" {p}{(p == state.Dealer ? "(庄)" : "")}: {string.Join(", ", state.Hands[p].OrderBy(t => t).Select(MahjongTile.ToString))} ({state.Hands[p].Count}张)"); - Console.WriteLine($" 牌墙剩余: {state.Deck.Count} 张"); + Console.WriteLine($" {p}{(p == state.Dealer ? " (庄)" : "")}: {state.Hands[p].Count}张"); + Console.WriteLine($" 牌墙: {state.Deck.Count} 张"); + Console.WriteLine($" (手牌已洗牌,按 Enter 查看牌局)"); +} - // Replay events - foreach (var evt in state.RecentEvents) +void RenderFinal(MahjongRoom room) +{ + var state = room.State; + Console.WriteLine("[最终状态]"); + Console.WriteLine($" 游戏结束,牌墙剩余 {state.Deck.Count} 张"); + + Console.WriteLine(); + Console.WriteLine(" 最终手牌:"); + foreach (var p in state.PlayerOrder) { - if (evt.Type == "win") - Console.WriteLine($" ✅ {evt.Player}: 自摸!番型: {evt.Description}"); - else if (evt.Type == "discard") - Console.WriteLine($" [{evt.Player}] 出牌: {MahjongTile.ToString(evt.Tile ?? 0)}"); - else if (evt.Type == "pung") - Console.WriteLine($" → {evt.Player}: 碰!"); - else if (evt.Type == "draw") - Console.WriteLine($" [{evt.Player}] 摸牌: {MahjongTile.ToString(evt.Tile ?? 0)}"); - else if (evt.Type == "deck_exhausted") - Console.WriteLine($" 牌墙耗尽!"); - else if (evt.Type == "hua_zhu") - Console.WriteLine($" ⚠️ {evt.Player}: 花猪"); - else if (evt.Type == "ting_checked") - Console.WriteLine($" ✓ {evt.Player}: 听牌"); - else if (evt.Type == "ting_failed") - Console.WriteLine($" ❌ {evt.Player}: 未听牌"); - else if (evt.Type == "settle") - Console.WriteLine($" 💰 结算"); + var hand = state.Hands[p]; + var sorted = string.Join(", ", hand.OrderBy(t => t).Select(MahjongTile.ToString)); + Console.WriteLine($" {p}{(p == state.Dealer ? "(庄)" : "")}: {sorted} ({hand.Count}张)"); + } + + if (state.HuPlayers.Count > 0) + { + Console.WriteLine(); + Console.WriteLine($" 胡牌: {string.Join(", ", state.HuPlayers)}"); } Console.WriteLine(); Console.WriteLine("[最终结算]"); foreach (var (p, score) in state.Scores) - Console.WriteLine($" {p}: {(score >= 0 ? "+" : "")}{score}分"); + Console.WriteLine($" {p}: {(score >= 0 ? "+" : "")}{score}分"); int total = state.Scores.Values.Sum(); - Console.WriteLine($" 总分: {(total >= 0 ? "+" : "")}{total} {(total == 0 ? "✓" : "⚠️ 非零和")}"); + Console.WriteLine($" 总分: {(total >= 0 ? "+" : "")}{total} {(total == 0 ? "✓" : "⚠ 非零和")}"); Console.WriteLine("══════════════════════════════════════"); } diff --git a/RuleEngine/MahjongRoom.cs b/RuleEngine/MahjongRoom.cs index 428a2e5..79b6780 100644 --- a/RuleEngine/MahjongRoom.cs +++ b/RuleEngine/MahjongRoom.cs @@ -316,7 +316,7 @@ public class MahjongRoom IsFinished = true; } - private void Deal() + public void Deal() { int perPlayer = _rules.Deal.CardsPerPlayer; bool includeFlowers = _rules.Deck.IncludeFlowers;