Files
card-game-engine/RuleEngine.Tests/CoreTests.cs
xiaoou 1346733996 [verified] fix: wildcard count correction in CheckWin tile count check
根因: CheckWin 开头 tiles.Count != 14 检查未计入 wildcardCount,
导致 12 tiles + 2 wildcards = 14 被误判为手牌不足。

修复: tiles.Count + wildcardCount != 14
同步修正鬼牌_1wildcard补刻子测试用13 tiles + 1 wildcard = 14

测试: 33/33 全部通过
2026-07-03 17:57:16 +08:00

224 lines
7.2 KiB
C#

using RuleEngine.Core;
using RuleEngine.Patterns;
namespace RuleEngine.Tests;
public class MahjongTileTests
{
[Fact]
public void Encode_万1_Returns1() => Assert.Equal(1, MahjongTile.Encode("万", 1));
[Fact]
public void Encode_条9_Returns19() => Assert.Equal(19, MahjongTile.Encode("条", 9));
[Fact]
public void Encode_筒3_Returns23() => Assert.Equal(23, MahjongTile.Encode("筒", 3));
[Fact]
public void Suit_万1_Returns0() => Assert.Equal(0, MahjongTile.Suit(1));
[Fact]
public void Suit_条19_Returns1() => Assert.Equal(1, MahjongTile.Suit(19));
[Fact]
public void Rank_万9_Returns9() => Assert.Equal(9, MahjongTile.Rank(9));
[Fact]
public void Rank_条11_Returns1() => Assert.Equal(1, MahjongTile.Rank(11));
[Fact]
public void ToString_各类型正确()
{
Assert.Equal("5万", MahjongTile.ToString(5));
Assert.Equal("8条", MahjongTile.ToString(18));
Assert.Equal("3筒", MahjongTile.ToString(23));
Assert.Equal("东", MahjongTile.ToString(31));
Assert.Equal("春", MahjongTile.ToString(41));
Assert.Equal("🃏", MahjongTile.ToString(50));
}
[Fact]
public void AllTiles_108张() => Assert.Equal(27, MahjongTile.AllTiles().Length);
[Fact]
public void AllTiles_含字牌_34种() => Assert.Equal(34, MahjongTile.AllTiles(includeHonors: true).Length);
[Fact]
public void AllTiles_含花牌_35种() => Assert.Equal(35, MahjongTile.AllTiles(includeFlowers: true).Length);
[Fact]
public void IsWildcard_50_True() => Assert.True(MahjongTile.IsWildcard(50));
[Fact]
public void IsWildcard_普通牌_False() => Assert.False(MahjongTile.IsWildcard(1));
}
public class DeckTests
{
[Fact]
public void _108张()
{
var deck = new MahjongDeck(includeHonors: false, includeFlowers: false);
Assert.Equal(108, deck.Tiles.Count);
}
[Fact]
public void 广_136张()
{
// 108 numbered + 28 honors = 136 (no flowers)
var deck = new MahjongDeck(includeHonors: true, includeFlowers: false);
Assert.Equal(136, deck.Tiles.Count);
}
[Fact]
public void _144张()
{
// 108 numbered + 28 honors + 8 flowers = 144
var deck = new MahjongDeck(includeHonors: true, includeFlowers: true);
Assert.Equal(144, deck.Tiles.Count);
}
[Fact]
public void 4()
{
var deck = new MahjongDeck();
var groups = deck.Tiles.Where(t => !MahjongTile.IsFlower(t)).GroupBy(t => t);
Assert.All(groups, g => Assert.Equal(4, g.Count()));
}
[Fact]
public void _减少计数()
{
var deck = new MahjongDeck();
int before = deck.Count;
deck.Draw();
Assert.Equal(before - 1, deck.Count);
}
}
public class MeldsSolverTests
{
private readonly MeldsSolver _solver = new(new Dictionary<string, FanConfig>());
// === 标准胡牌 ===
[Fact]
public void _4面子1对_ShouldWin()
{
// 123万 456万 789万 111条 99条
var hand = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 11, 11, 19, 19 };
var result = _solver.CheckWin(hand);
Assert.True(result.IsWin);
}
[Fact]
public void _碰碰胡_ShouldWin()
{
// 111万 333万 555万 111条 99条
var hand = new List<int> { 1, 1, 1, 3, 3, 3, 5, 5, 5, 11, 11, 11, 19, 19 };
var result = _solver.CheckWin(hand);
Assert.True(result.IsWin);
}
[Fact]
public void _缺面子_ShouldNotWin()
{
// All sequential but wrong structure: 123 456 78? can't form 4 melds
var hand = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 14, 15, 16 };
var result = _solver.CheckWin(hand);
Assert.False(result.IsWin);
}
[Fact]
public void _14张全不同_ShouldNotWin()
{
var hand = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 21, 15, 19 };
var result = _solver.CheckWin(hand);
Assert.False(result.IsWin);
}
// === 七对 ===
[Fact]
public void _ShouldWin()
{
var hand = new List<int> { 1, 1, 3, 3, 5, 5, 7, 7, 11, 11, 13, 13, 21, 21 };
var result = _solver.CheckWin(hand);
Assert.True(result.IsWin);
}
[Fact]
public void _缺一对_ShouldNotWin()
{
var hand = new List<int> { 1, 1, 3, 3, 5, 5, 7, 7, 11, 11, 13, 13, 21, 5 };
var result = _solver.CheckWin(hand);
Assert.False(result.IsWin);
}
// === 十三幺 ===
[Fact]
public void _ShouldWin()
{
var hand = new List<int> { 1, 9, 11, 19, 21, 29, 31, 32, 33, 34, 35, 36, 37, 1 };
var result = _solver.CheckWin(hand);
Assert.True(result.IsWin);
}
[Fact]
public void _缺字牌_ShouldNotWin()
{
var hand = new List<int> { 1, 9, 11, 19, 21, 29, 2, 3, 4, 5, 6, 7, 8, 1 };
var result = _solver.CheckWin(hand);
Assert.False(result.IsWin);
}
// === 番型识别 ===
[Fact]
public void _ShouldIdentify()
{
// 全万: 111万 234万 567万 789万 99万
var hand = new List<int> { 1, 1, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9, 9, 9 };
var result = _solver.CheckWin(hand);
Assert.True(result.IsWin);
var fans = _solver.IdentifyFans(result!);
Assert.Contains("清一色", fans);
}
[Fact]
public void _ShouldIdentify()
{
var hand = new List<int> { 1, 1, 1, 3, 3, 3, 5, 5, 5, 11, 11, 11, 19, 19 };
var result = _solver.CheckWin(hand);
var fans = _solver.IdentifyFans(result!);
Assert.Contains("对对胡", fans);
}
// === Wildcard ===
[Fact]
public void _1wildcard补刻子_ShouldWin()
{
// 111万 234万 567万 (3 melds) + 条11,条11 + wildcard = 刻子 (4th meld) + 筒9,筒9 = pair
// 13 tiles + 1 wildcard = 14
var hand = new List<int> { 1, 1, 1, 2, 3, 4, 5, 6, 7, 11, 11, 9, 9 };
var result = _solver.CheckWin(hand, wildcardCount: 1);
Assert.True(result.IsWin);
}
[Fact]
public void _2wildcard做对_ShouldWin()
{
// 111万 234万 555万 888万 + 2 wildcards as the pair
var hand = new List<int> { 1, 1, 1, 2, 3, 4, 5, 5, 5, 8, 8, 8 };
var result = _solver.CheckWin(hand, wildcardCount: 2);
Assert.True(result.IsWin);
}
// === 258将 ===
[Fact]
public void _258将_2万_ShouldWin()
{
var hand = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 11, 11, 2, 2 };
var result = _solver.CheckWin(hand, require258Pair: true);
Assert.True(result.IsWin);
}
[Fact]
public void _258将_7万将_ShouldFail()
{
var hand = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 11, 11, 7, 7 };
var result = _solver.CheckWin(hand, require258Pair: true);
Assert.False(result.IsWin);
}
// === 全不靠 ===
[Fact]
public void _147万_258条_369筒_ShouldWin()
{
var hand = new List<int> { 1, 4, 7, 12, 15, 18, 23, 26, 29, 31, 32, 33, 34, 35 };
// Should be close enough for AllOrphans
// Note: This test may need adjustment based on exact implementation
}
}