feat: AddMultiCardLeads 补全 — 连对/飞机/飞机带对

新增枚举:
- 连对(LianDui): 提取对子 → 排序 → 找≥3连续段(如334455)
- 飞机(FeiJi): 提取三张 → 排序 → 找≥2连续段(如333444)
- 飞机带对(FeijiDai2): 连续三张 + 每组附带1对子

辅助方法: SortByGameNum/AddConsecutiveGroups/GetConsecutiveRuns

10局验证: LianDui 5次出现
完整牌型: DanZhang 76 | DuiZi 37 | ShunZi 17 | SanDai2 7 | LianDui 5 | SiDai3 1
(飞机需≥2连续三张,16张牌罕见但逻辑已就位)
This commit is contained in:
2026-07-07 14:28:49 +08:00
parent 2dd0bc3f78
commit 6299e4e580
7 changed files with 77 additions and 0 deletions

View File

@ -359,6 +359,33 @@ namespace PdkFriendServer.Logic
// else: 炸弹已在上面处理
}
// 连对≥3对连续, 如 334455
var pairs = GetMultiGroups(hand, 2);
SortByGameNum(pairs);
AddConsecutiveGroups(pairs, 3, pos, candidates, ref multiCount);
// 飞机≥2组连续三张, 如 333444
SortByGameNum(triples);
AddConsecutiveGroups(triples, 2, pos, candidates, ref multiCount);
// 飞机带对: 连续三张 + 每组附带一个对子
var tripleConsecRuns = GetConsecutiveRuns(triples, 2);
foreach (var run in tripleConsecRuns)
{
var runCards = run.SelectMany(t => t).ToList();
int pairCount = run.Count; // 需要这么多对子
// 找不重叠的对子
var remainingPairs = GetMultiGroups(
hand.Where(c => !runCards.Any(r => r.ID == c.ID)).ToArray(), 2);
if (remainingPairs.Count >= pairCount)
{
SortByGameNum(remainingPairs);
var attached = remainingPairs.Take(pairCount).SelectMany(p => p).ToList();
runCards.AddRange(attached);
AddCandidate(runCards, pos, candidates, ref multiCount);
}
}
// 顺子≥5 张连续)
var straights = PokerLogic.GetShunZi(hand);
if (straights != null)
@ -391,6 +418,56 @@ namespace PdkFriendServer.Logic
return result;
}
/// <summary>按 GameNum 排序多牌组列表</summary>
private static void SortByGameNum(List<List<TCardInfoPdkF>> groups)
{
groups.Sort((a, b) => a[0].GameNum.CompareTo(b[0].GameNum));
}
/// <summary>找出所有连续段≥minLen每段生成一个候选</summary>
private static void AddConsecutiveGroups(List<List<TCardInfoPdkF>> groups, int minLen,
int pos, List<(PlayOutCardPdkF play, bool isMulti)> candidates, ref int multiCount)
{
var runs = GetConsecutiveRuns(groups, minLen);
foreach (var run in runs)
{
var cards = run.SelectMany(g => g).ToList();
AddCandidate(cards, pos, candidates, ref multiCount);
}
}
/// <summary>从已排序的组中提取所有连续段≥minLen 组)</summary>
private static List<List<List<TCardInfoPdkF>>> GetConsecutiveRuns(
List<List<TCardInfoPdkF>> groups, int minLen)
{
var runs = new List<List<List<TCardInfoPdkF>>>();
if (groups.Count < minLen) return runs;
var current = new List<List<TCardInfoPdkF>> { groups[0] };
int prevNum = groups[0][0].GameNum;
for (int i = 1; i < groups.Count; i++)
{
int curNum = groups[i][0].GameNum;
if (curNum == prevNum + 1)
{
current.Add(groups[i]);
}
else
{
if (current.Count >= minLen)
runs.Add(new List<List<TCardInfoPdkF>>(current));
current.Clear();
current.Add(groups[i]);
}
prevNum = curNum;
}
if (current.Count >= minLen)
runs.Add(current);
return runs;
}
/// <summary>
/// 从合法方案中选最优:优先出多张牌的组合,其次出最大的
/// P2修复: 之前只取 tips[0](最小单张),改为优先多牌组合