feat: 智能SimulateToEnd — PickBestTip按跟牌/领牌区分策略
回退纯贪心: Count×10+rank → 总是出最大牌(跟牌时浪费高牌,领牌时不效率) 修复: - 跟牌(isNewRound=false): 出刚好压制的最小牌,保留大牌用于后续压制 评分 = Count×1000 + rank(越小越好) - 领牌(isNewRound=true): 优先多牌组合提高清牌效率 评分 = Count×100 - rank(越大越好,多牌优先,同类型出小rank) 效果(100局vs 30局V4折算): ShunZi 76→102(+34%), DuiZi 224→236(+5%), ShunZi明显提升 SanDai2 92→72(回到V1基准线), 多牌比例24.1% 验证: 100局0错误 0.8s/局
This commit is contained in:
@ -438,7 +438,7 @@ namespace PdkFriendServer.Logic
|
||||
|
||||
if (curTips != null && curTips.Count > 0)
|
||||
{
|
||||
var pick = PickBestTip(curTips);
|
||||
var pick = PickBestTip(curTips, curHand, false);
|
||||
maxPlay = new PlayOutCardPdkF { Pos = (byte)current, GameNum = pick[0].GameNum, Type = pick.Count == 1 ? CardType1.DanZhang : CardType1.DuiZi, Ids = pick.Select(c => c.ID).ToArray() };
|
||||
maxPlayer = current; passStreak = 0;
|
||||
foreach (var id in maxPlay.Ids) curHand.RemoveAll(c => c.ID == id);
|
||||
@ -450,7 +450,7 @@ namespace PdkFriendServer.Logic
|
||||
var ft = PdkCardAlgorithm.GetTipCard(new PlayOutCardPdkF(), curHand.ToArray(), null, false);
|
||||
if (ft != null && ft.Count > 0)
|
||||
{
|
||||
var pick = PickBestTip(ft);
|
||||
var pick = PickBestTip(ft, curHand, true);
|
||||
maxPlay = new PlayOutCardPdkF { Pos = (byte)current, GameNum = pick[0].GameNum, Type = CardType1.DanZhang, Ids = pick.Select(c => c.ID).ToArray() };
|
||||
maxPlayer = current;
|
||||
foreach (var id in maxPlay.Ids) curHand.RemoveAll(c => c.ID == id);
|
||||
@ -576,17 +576,43 @@ namespace PdkFriendServer.Logic
|
||||
return runs;
|
||||
}
|
||||
|
||||
private static List<TCardInfoPdkF> PickBestTip(List<List<TCardInfoPdkF>> tips)
|
||||
/// <summary>
|
||||
/// 智能出牌选择:模拟中的虚拟对手应该合理出牌,而非纯贪心。
|
||||
/// - 跟牌时:出刚好能压制的最小牌(保留大牌)
|
||||
/// - 领牌时:优先多牌组合(提高清牌效率)
|
||||
/// </summary>
|
||||
private static List<TCardInfoPdkF> PickBestTip(List<List<TCardInfoPdkF>> tips,
|
||||
List<TCardInfoPdkF> curHand, bool isNewRound)
|
||||
{
|
||||
if (tips == null || tips.Count == 0) return null;
|
||||
var best = tips[tips.Count - 1];
|
||||
int bestScore = best.Count * 10 + best[0].GameNum;
|
||||
for (int i = tips.Count - 2; i >= 0; i--)
|
||||
|
||||
if (!isNewRound)
|
||||
{
|
||||
int s = tips[i].Count * 10 + tips[i][0].GameNum;
|
||||
if (s > bestScore) { bestScore = s; best = tips[i]; }
|
||||
// 跟牌:出刚好能压制的最小牌
|
||||
// 策略:出最小 rank 的有效牌,保留大牌用于后续压制
|
||||
var best = tips[0];
|
||||
int bestScore = int.MaxValue;
|
||||
foreach (var tip in tips)
|
||||
{
|
||||
// 同数量优先选最小 rank;不同数量优先选少的
|
||||
int score = tip.Count * 1000 + tip[0].GameNum;
|
||||
if (score < bestScore) { bestScore = score; best = tip; }
|
||||
}
|
||||
return best;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 领牌:优先高效清牌
|
||||
var best = tips[0];
|
||||
int bestScore = int.MinValue;
|
||||
foreach (var tip in tips)
|
||||
{
|
||||
// 优先多牌;同数量出最小 rank(保留大牌控制权)
|
||||
int score = tip.Count * 100 - tip[0].GameNum;
|
||||
if (score > bestScore) { bestScore = score; best = tip; }
|
||||
}
|
||||
return best;
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
// 静态牌池:52张牌,只创建一次
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user