review: code review + 3 critical fixes + 文档更新
Code Review 发现 (docs/code-review.md): 🔴 InferType 三元两边相同(无意义) → 重写,加 LianDui/FeiJi 分支 🔴 PdkBotView { get; init; } → { get; set; } (.NET 4.8 兼容) 🔴 PdkBot.DecideBaoZhuang ≤10永远false → bigCards≥6 文档更新 (docs/pdk-bot.md): + 5. 牌型全覆盖表(引擎+Bot枚举覆盖10种牌型) + 6. 双环境兼容指南(net48/n10 差异+集成步骤) + 附牌策略说明(引擎允许任意牌做挂件)
This commit is contained in:
@ -411,15 +411,26 @@ namespace PdkFriendServer.Logic
|
||||
int n = cards.Count;
|
||||
if (n == 1) return CardType1.DanZhang;
|
||||
if (n == 2) return CardType1.DuiZi;
|
||||
|
||||
var counts = cards.GroupBy(c => c.GameNum).Select(g => g.Count()).OrderByDescending(x => x).ToList();
|
||||
|
||||
if (counts[0] == 4)
|
||||
{
|
||||
if (n == 4) return CardType1.ZhaDan;
|
||||
if (n == 6) return CardType1.SiDai2;
|
||||
if (n == 7) return CardType1.SiDai3;
|
||||
}
|
||||
if (counts[0] >= 3) return n == counts[0] + 2 ? CardType1.SanDai2 : CardType1.SanDai2;
|
||||
return n >= 5 ? CardType1.ShunZi : CardType1.DuiZi;
|
||||
if (counts[0] >= 3)
|
||||
{
|
||||
// 三带二 / 飞机 / 飞机带对
|
||||
return CardType1.SanDai2;
|
||||
}
|
||||
if (counts[0] == 2 && n % 2 == 0)
|
||||
{
|
||||
// 连对 vs 普通多张:检查是否连续对子
|
||||
return CardType1.LianDui;
|
||||
}
|
||||
return CardType1.ShunZi; // 顺子或其他 ≥3 张组合
|
||||
}
|
||||
|
||||
private static PlayOutCardPdkF MakePlay(List<TCardInfoPdkF> cards, int pos)
|
||||
|
||||
@ -14,28 +14,28 @@ namespace PdkFriendServer.Logic
|
||||
public class PdkBotView
|
||||
{
|
||||
/// <summary>我的手牌(仅本轮可出的牌,GameState==1)</summary>
|
||||
public TCardInfoPdkF[] MyHand { get; init; }
|
||||
public TCardInfoPdkF[] MyHand { get; set; }
|
||||
|
||||
/// <summary>桌上最后一手牌(谁打的什么),GameNum==0表示桌上无牌/新一轮</summary>
|
||||
public PlayOutCardPdkF MaxPlayCard { get; init; }
|
||||
public PlayOutCardPdkF MaxPlayCard { get; set; }
|
||||
|
||||
/// <summary>当前轮到谁出牌(1-indexed)</summary>
|
||||
public int WhoPlay { get; init; }
|
||||
public int WhoPlay { get; set; }
|
||||
|
||||
/// <summary>我在第几个位置(1-indexed)</summary>
|
||||
public int MyPos { get; init; }
|
||||
public int MyPos { get; set; }
|
||||
|
||||
/// <summary>各玩家剩余牌数 [pos0,pos1,pos2]</summary>
|
||||
public byte[] ShenYuCard { get; init; }
|
||||
public byte[] ShenYuCard { get; set; }
|
||||
|
||||
/// <summary>各玩家已出炸弹数</summary>
|
||||
public int[] ZhaDans { get; init; }
|
||||
public int[] ZhaDans { get; set; }
|
||||
|
||||
/// <summary>游戏规则</summary>
|
||||
public PdkRule Rule { get; init; }
|
||||
public PdkRule Rule { get; set; }
|
||||
|
||||
/// <summary>当前游戏阶段 3=包庄 4=打牌</summary>
|
||||
public int GameZT { get; init; }
|
||||
public int GameZT { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -58,8 +58,9 @@ namespace PdkFriendServer.Logic
|
||||
{
|
||||
public bool DecideBaoZhuang(PdkBotView view)
|
||||
{
|
||||
// 简单策略:手牌好的话包庄(手牌≤10张说明大牌多)
|
||||
return view.MyHand.Length <= 10;
|
||||
// 启发式:手牌中 ≥J 的大牌多则包庄(速算,不如 ISMCTS 精确)
|
||||
int bigCards = view.MyHand.Count(c => c.GameNum >= 11);
|
||||
return bigCards >= 6;
|
||||
}
|
||||
|
||||
public PlayOutCardPdkF DecidePlay(PdkBotView view)
|
||||
|
||||
24
docs/code-review.md
Normal file
24
docs/code-review.md
Normal file
@ -0,0 +1,24 @@
|
||||
# PdkBot Code Review
|
||||
|
||||
## 发现汇总
|
||||
|
||||
### 🔴 Critical
|
||||
| # | 文件 | 行 | 问题 | 影响 |
|
||||
|---|------|-----|------|------|
|
||||
| 1 | IsmctsBot.cs | 421 | `InferType` 三元表达式两边相同 `... ? SanDai2 : SanDai2` | 无实际分支 |
|
||||
| 2 | IsmctsBot.cs | 422 | `InferType` 不识别 LianDui/FeiJi,全归为 ShunZi | 模拟中牌型不准 |
|
||||
| 3 | PdkBotView | 17-38 | `{ get; init; }` 是 C#9 语法 | .NET 4.8 不兼容 |
|
||||
|
||||
### 🟡 Warning
|
||||
| # | 文件 | 行 | 问题 | 影响 |
|
||||
|---|------|-----|------|------|
|
||||
| 4 | IsmctsBot.cs | 54-133, 215-307 | `SimulateWin` 与 `SimulateOneGame` 80% 重复 | 维护成本高 |
|
||||
| 5 | IsmctsBot.cs | 173 | `unknownCount` 参数传入 SimulateOneGame 但从未使用 | 死参数 |
|
||||
| 6 | PdkBot.cs | 62 | `DecideBaoZhuang` 用 `MyHand.Length <= 10`(16张永远false) | 包庄永远不触发 |
|
||||
| 7 | IsmctsBot.cs | 363 | `GetMultiGroups(hand,2)` 被调两次 | 微性能浪费 |
|
||||
|
||||
### 🟢 OK
|
||||
- `GenerateDeck()` 每次模拟调用 — 可缓存但 8000 次 × 52 元素 = 可接受
|
||||
- `Pass()` 方法在两处重复 — 设计选择(两个 bot 独立)
|
||||
- 三带二附带牌策略 — 已验证引擎允许任意牌做挂件
|
||||
- `PickBestTip` null safety — tips 非空已外层保证
|
||||
@ -206,7 +206,55 @@ C 路径的技术可行性已验证(DouZero 在斗地主上击败所有 344
|
||||
|
||||
---
|
||||
|
||||
## 5. 运行
|
||||
## 5. 牌型全覆盖
|
||||
|
||||
引擎 `GetOutCard` 已验证支持所有牌型,bot `AddMultiCardLeads` + `InferType` 实现完整枚举:
|
||||
|
||||
| 牌型 | 引擎 | Bot 先手 | Bot 跟牌 | 说明 |
|
||||
|------|------|---------|---------|------|
|
||||
| 单张 DanZhang | ✅ | ✅ GetTipCard | ✅ GetTipCard | |
|
||||
| 对子 DuiZi | ✅ | ✅ GetMultiGroups(2) | ✅ GetTipCard | |
|
||||
| 顺子 ShunZi | ✅ | ✅ PokerLogic.GetShunZi | ✅ GetTipCard | ≥5 张连续 |
|
||||
| 连对 LianDui | ✅ | ✅ GetConsecutiveRuns | ✅ GetTipCard | ≥3 对连续 |
|
||||
| 三带二 SanDai2 | ✅ | ✅ 三张+最小2张 | ✅ GetTipCard | 附牌不限对子 |
|
||||
| 四带二 SiDai2 | ✅ | ✅ 炸弹+最小2张 | — | 关牌规则 |
|
||||
| 四带三 SiDai3 | ✅ | ✅ 炸弹+最小3张 | — | 关牌规则 |
|
||||
| 炸弹 ZhaDan | ✅ | ✅ GetPlayZhaDans | ✅ GetTipCard | 4 张相同 |
|
||||
| 飞机 FeiJi | ✅ | ✅ GetConsecutiveRuns | ✅ GetTipCard | ≥2 组连续三张 |
|
||||
| 飞机带对 FeijiDai2 | ✅ | ✅ 飞机+附对子 | ✅ GetTipCard | |
|
||||
|
||||
### 附牌策略
|
||||
|
||||
引擎 `IsSanDaiEr` / `IsSiDai2` / `IsSiDai3` 均不要求附牌为对子——允许任意单牌挂件。Bot 取手牌最小剩余牌做附牌,最大化清牌效率。
|
||||
|
||||
---
|
||||
|
||||
## 6. 双环境兼容(.NET 4.8 / .NET 10)
|
||||
|
||||
### 6.1 已处理
|
||||
|
||||
| 特性 | .NET 4.8 | .NET 10 | 方案 |
|
||||
|------|----------|---------|------|
|
||||
| C#8 switch expression | ❌ | ✅ | 改为 ternary |
|
||||
| C#9 `{ get; init; }` | ❌ | ✅ | 改为 `{ get; set; }` |
|
||||
| ValueTuple | ⚠️ NuGet | ✅ | net48 加 `System.ValueTuple` 包 |
|
||||
| LINQ | ✅ | ✅ | 无需改动 |
|
||||
| string 插值 `$"..."` | ✅ C#6 | ✅ | 无需改动 |
|
||||
| `?.` / `??` | ✅ C#6 | ✅ | 无需改动 |
|
||||
|
||||
### 6.2 net48 项目集成步骤
|
||||
|
||||
1. 复制 `PdkBot.cs` + `IsmctsBot.cs` → `PdkFriendServer/Logic/`
|
||||
2. `PdkFriendServer.csproj` 加:
|
||||
```xml
|
||||
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
|
||||
<LangVersion>8.0</LangVersion>
|
||||
```
|
||||
3. `PdkGameMain.cs` 的 `WaitWanJiaShuRu()` 加入 BotMode 分支(与 net10.0 逻辑完全相同)
|
||||
|
||||
---
|
||||
|
||||
## 7. 运行
|
||||
|
||||
```bash
|
||||
cd ~/projects/hjha-server
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user