feat: initial commit - HJHA game server full source

6 major server modules (PdkFriendServer/GlobalSever/ServerCore/GameModule/GameNetModule) +
game logic (GameFix/GameDAL/ServerData) +
network layer (NetWorkMessage) +
data layer (ObjectModel) +
utilities (MrWu/Core/Config/CloudAPI/dll) +
adapters (zyxAdapter/base)

.NET 8.0 C# solution, 16 projects, 958 source files
This commit is contained in:
2026-07-07 12:02:15 +08:00
commit e9616125ce
958 changed files with 158203 additions and 0 deletions

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: cce19ec85cde409c8ba213a878216016
timeCreated: 1741678598

View File

@ -0,0 +1,14 @@
using System.Collections.Generic;
using System.Linq;
namespace GameFix.Poker
{
/// <summary>
/// 三顺 (3个起)
/// </summary>
public class CardStyle111222333Helper : CardStyle111222Helper
{
public override int CardStyle => DataCardConst.CardStyle111222333;
public override int CardCnt => 9;
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a48ff248eb6640c9817ac501c87c11cb
timeCreated: 1748935610

View File

@ -0,0 +1,88 @@
using System.Collections.Generic;
using System.Linq;
using GameMessage;
namespace GameFix.Poker
{
public class CardStyle111222Helper : CardStyleBaseHelper
{
public override int CardStyle => DataCardConst.CardStyle111222;
public override int CardCnt => 6;
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count >= CardCnt && group.Cards.Count % 3 == 0)
{
if (IsContinuous(group.CardGroupList, 3, out var shunCnt)
&& shunCnt.Count * 3 == group.Cards.Count)
{
cardStyleInfo = CardStyleHelper.CreateCardStyleInfo(CardStyle, group.Cards);
return true;
}
}
return false;
}
internal override bool CheckStyleWithLZ(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count >= CardCnt && group.Cards.Count % 3 == 0)
{
if (IsAllSame(group.NoLZCards)) return false;
if (IsMaxContinuousByLZ(group.CardGroupList, 3, group.LZCards.Count,
out var shunValueList, out var lackValueList))
{
if (shunValueList.Count * 3 == group.Cards.Count)
{
cardStyleInfo = new CardStyleInfo(CardStyle, shunValueList[0], shunValueList.Count * 3);
cardStyleInfo.CardLackValues = lackValueList.ToArray();
return true;
}
}
}
return false;
}
internal override List<CardGroupList> GetAllEatTipGroup(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var groupCnt = group.CardGroupList.Count;
var groupList = new List<CardGroupList>(groupCnt);
var minValue = eatStyleInfo != null ? eatStyleInfo.CardValue + 1 : 3;
var continuousCnt = eatStyleInfo?.CardCnt ?? -1;
List<Card> continuousList = new List<Card>();
for (int i = minValue; i < group.CardGroupList.Count; i++)
{
continuousList.Clear();
for (int j = 0; j < group.CardGroupList.Count; j++)
{
if (i + j >= group.CardGroupList.Count)
break;
if (group.CardGroupList[i + j].Count <= 2)
break;
continuousList.AddRange(group.CardGroupList[i + j].GetRange(0, 3));
if (continuousList.Count >= CardCnt && continuousList.Count % 3 == 0)
{
if (continuousCnt == -1 || continuousCnt == continuousList.Count)
{
groupList.Add(new CardGroupList(continuousList));
}
}
}
}
return groupList;
}
internal override List<CardGroupList> GetAllEatTipGroupWithLZ(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{// 这里不处理直接找炸弹
return new List<CardGroupList>();
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0c80edd1dc98428c973c5a3a193aa748
timeCreated: 1741684811

View File

@ -0,0 +1,123 @@
using System.Collections.Generic;
using System.Linq;
using GameMessage;
namespace GameFix.Poker
{
public class CardStyle112233Helper : CardStyleBaseHelper
{
public override int CardStyle => DataCardConst.CardStyle112233;
public override int CardCnt => 6;
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count >= CardCnt && group.Cards.Count % 2 == 0)
{
if (IsContinuous(group.CardGroupList, 2, out var shunCnt)
&& shunCnt.Count * 2 == group.Cards.Count)
{
cardStyleInfo = CardStyleHelper.CreateCardStyleInfo(CardStyle, group.Cards);
return true;
}
}
return false;
}
internal override bool CheckStyleWithLZ(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count >= CardCnt && group.Cards.Count % 2 == 0)
{
if (IsAllSame(group.NoLZCards)) return false;
if (IsMaxContinuousByLZ(group.CardGroupList, 2, group.LZCards.Count,
out var shunValueList, out var lackValueList))
{
if (shunValueList.Count * 2 == group.Cards.Count)
{
cardStyleInfo = new CardStyleInfo(CardStyle, shunValueList[0], shunValueList.Count * 2);
cardStyleInfo.CardLackValues = lackValueList.ToArray();
return true;
}
}
}
return false;
}
internal override List<CardGroupList> GetAllEatTipGroup(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var groupCnt = group.CardGroupList.Count;
var groupList = new List<CardGroupList>(groupCnt);
var minValue = eatStyleInfo != null ? eatStyleInfo.CardValue + 1 : 3;
var continuousCnt = eatStyleInfo?.CardCnt ?? -1;
List<Card> continuousList = new List<Card>();
for (int i = minValue; i < group.CardGroupList.Count; i++)
{
continuousList.Clear();
for (int j = 0; j < group.CardGroupList.Count; j++)
{
if (i + j >= group.CardGroupList.Count)
break;
if (group.CardGroupList[i + j].Count <= 1)
break;
continuousList.AddRange(group.CardGroupList[i + j].GetRange(0, 2));
if (continuousList.Count >= CardCnt && continuousList.Count % 2 == 0)
{
if (continuousCnt == -1 || continuousCnt == continuousList.Count)
{
groupList.Add(new CardGroupList(continuousList));
}
}
}
}
return groupList;
}
internal override List<CardGroupList> GetAllEatTipGroupWithLZ(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var minValue = eatStyleInfo != null ? eatStyleInfo.CardValue + 1 : 3;
var continuousCnt = eatStyleInfo?.CardCnt ?? -1;
var groupList = new List<CardGroupList>();
List<Card> continuousList = new List<Card>();
List<int> lackValueList = new List<int>();
int needCnt = 0;
for (int i = minValue; i < group.CardGroupList.Count; i++)
{
var count = group.CardGroupList[i].Count;
if (count >= 2)
{
continuousList.AddRange(group.CardGroupList[i].GetRange(0, 2));
}
else
{
needCnt += (2 - count);
lackValueList.AddRange(Enumerable.Repeat(i, (2 - count)));
}
bool isBreak = group.CardGroupList[i].Count < 2 && needCnt > group.LZCards.Count;
if (continuousList.Count + needCnt >= CardCnt && needCnt <= group.LZCards.Count)
{
if (continuousCnt == -1 || continuousCnt == continuousList.Count + needCnt)
{
continuousList.AddRange(group.LZCards.GetRange(0, needCnt));
groupList.Add(new CardGroupList(continuousList));
break;
}
} else if (isBreak)
{
continuousList.Clear();
needCnt = 0;
}
}
return groupList;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8a1287609db44ab2a55656eb154266d4
timeCreated: 1741684811

View File

@ -0,0 +1,11 @@
using System.Collections.Generic;
using System.Linq;
namespace GameFix.Poker
{
public class CardStyle1122Helper : CardStyle112233Helper
{
public override int CardStyle => DataCardConst.CardStyle1122;
public override int CardCnt => 4;
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 57d250baed484c6ca90c588c01bc11f0
timeCreated: 1741763235

View File

@ -0,0 +1,123 @@
using System.Collections.Generic;
using System.Linq;
using GameMessage;
namespace GameFix.Poker
{
public class CardStyle123Helper : CardStyleBaseHelper
{
public override int CardStyle => DataCardConst.CardStyle123;
public override int CardCnt => 5;
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count >= CardCnt)
{
if (IsContinuous(group.CardGroupList, 1, out var shunCnt)
&& shunCnt.Count == group.Cards.Count)
{
cardStyleInfo = CardStyleHelper.CreateCardStyleInfo(CardStyle, group.Cards);
return true;
}
}
return false;
}
internal override bool CheckStyleWithLZ(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count >= CardCnt)
{
if (IsAllSame(group.NoLZCards)) return false; // 直接组成炸弹
if (IsMaxContinuousByLZ(group.CardGroupList, 1, group.LZCards.Count,
out var shunValueList, out var lackValueList))
{
if (shunValueList.Count == group.Cards.Count)
{
cardStyleInfo = new CardStyleInfo(CardStyle, shunValueList[0], shunValueList.Count);
cardStyleInfo.CardLackValues = lackValueList.ToArray();
return true;
}
}
}
return false;
}
internal override List<CardGroupList> GetAllEatTipGroup(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var groupCnt = group.CardGroupList.Count;
var groupList = new List<CardGroupList>(groupCnt);
var minValue = eatStyleInfo != null ? eatStyleInfo.CardValue + 1 : 3;
var continuousCnt = eatStyleInfo?.CardCnt ?? -1;
List<Card> continuousList = new List<Card>();
for (int i = minValue; i < group.CardGroupList.Count; i++)
{
continuousList.Clear();
for (int j = 0; j < group.CardGroupList.Count; j++)
{
if (i + j >= group.CardGroupList.Count)
break;
if (group.CardGroupList[i + j].Count == 0)
break;
continuousList.Add(group.CardGroupList[i + j].First());
if (continuousList.Count >= 5)
{
if (continuousCnt == -1 || continuousCnt == continuousList.Count)
{
groupList.Add(new CardGroupList(continuousList));
}
}
}
}
return groupList;
}
internal override List<CardGroupList> GetAllEatTipGroupWithLZ(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var minValue = eatStyleInfo != null ? eatStyleInfo.CardValue + 1 : 3;
var continuousCnt = eatStyleInfo?.CardCnt ?? -1;
var groupList = new List<CardGroupList>();
List<Card> continuousList = new List<Card>();
List<int> lackValues = new List<int>();
int needCnt = 0;
for (int i = minValue; i < MaxShunLogicNum; i++)
{
if (group.CardGroupList[i].Count > 0)
{
continuousList.Add(group.CardGroupList[i].First());
}
else
{
needCnt++;
lackValues.Add(i);
}
bool isBreak = group.CardGroupList[i].Count < 1 && needCnt > group.LZCards.Count;
if (continuousList.Count + needCnt >= CardCnt && needCnt <= group.LZCards.Count)
{
if (continuousCnt == -1 || continuousCnt == continuousList.Count + needCnt)
{
continuousList.AddRange(group.LZCards.GetRange(0, needCnt));
groupList.Add(new CardGroupList(continuousList));
break;
}
} else if (isBreak)
{
lackValues.Clear();
continuousList.Clear();
needCnt = 0;
}
}
return groupList;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7b1e3edc09a540b587d0f0b36cbf4f2d
timeCreated: 1741684811

View File

@ -0,0 +1,79 @@
using System.Collections.Generic;
using System.Linq;
using GameMessage;
namespace GameFix.Poker
{
public class CardStyle1Helper : CardStyleBaseHelper
{
public override int CardStyle => DataCardConst.CardStyle1;
public override int CardCnt => 1;
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count == CardCnt)
{
cardStyleInfo = CardStyleHelper.CreateCardStyleInfo(CardStyle, group.Cards);
return true;
}
return false;
}
internal override bool CheckStyleWithLZ(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count != CardCnt) return false;
// 单张癞子只能当普通牌
if (group.LZCards.Count == group.Cards.Count)
{
cardStyleInfo = CardStyleHelper.CreateCardStyleInfo(CardStyle, group.LZCards);
return true;
}
return false;
}
internal override List<CardGroupList> GetAllEatTipGroup(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var groupCnt = group.CardGroupList.Count;
var groupList = new List<CardGroupList>(groupCnt);
for (int i = 0; i < groupCnt; i++)
{
var cardGroup = group.CardGroupList[i];
if (cardGroup.Count >= CardCnt && cardGroup.Count < 4 && IsSameGroupGreater(cardGroup, eatStyleInfo))
{
groupList.Add(new CardGroupList(cardGroup));
}
}
// 从单牌到三张排序,优先不拆组合牌
if (groupList.Count > 0)
{
groupList = groupList.OrderBy(x=>x.Count).ToList();
groupList.ForEach(x => x.RemoveRange(1, x.Count - 1));
}
return groupList;
}
internal override List<CardGroupList> GetAllEatTipGroupWithLZ(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
// 在常规情况下没有找到单牌可以出 (说明只剩下癞子)
// 单牌也只能按原始牌值出
var groupList = new List<CardGroupList>(group.LZCards.Count);
for (int i = 0; i < group.LZCards.Count; i++)
{
var lzCard = group.LZCards[i];
if (lzCard.Value > eatStyleInfo.CardValue)
{
var lzCards = new CardGroupList();
lzCards.Add(lzCard);
groupList.Add(lzCards);
}
}
return groupList;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1a22e938dae646c8bf2d19ddf7fc9456
timeCreated: 1741678606

View File

@ -0,0 +1,98 @@
using System.Collections.Generic;
using System.Linq;
using GameMessage;
namespace GameFix.Poker
{
public class CardStyle2Helper : CardStyleBaseHelper
{
public override int CardStyle => DataCardConst.CardStyle2;
public override int CardCnt => 2;
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count == CardCnt && IsAllSame(group.Cards))
{
cardStyleInfo = CardStyleHelper.CreateCardStyleInfo(CardStyle, group.Cards);
return true;
}
return false;
}
internal override bool CheckStyleWithLZ(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count != CardCnt) return false;
if (IsContainJoker(group.NoLZCards)) return false;
if (group.LZCards.Count == group.Cards.Count && IsAllSame(group.LZCards))
{
cardStyleInfo = CardStyleHelper.CreateCardStyleInfo(CardStyle, group.LZCards);
return true;
}
if (IsAllSame(group.NoLZCards))
{
var cardV = group.NoLZCards[0].Value;
cardStyleInfo = new CardStyleInfo(CardStyle, cardV, CardCnt);
cardStyleInfo.CardLackValues = Enumerable.Repeat((int)cardV, group.LZCards.Count).ToArray();
return true;
}
return false;
}
internal override List<CardGroupList> GetAllEatTipGroup(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var groupCnt = group.CardGroupList.Count;
var groupList = new List<CardGroupList>(groupCnt);
for (int i = 0; i < groupCnt; i++)
{
var cardGroup = group.CardGroupList[i];
if (cardGroup.Count >= CardCnt && cardGroup.Count < 4 && IsSameGroupGreater(cardGroup, eatStyleInfo))
{
groupList.Add(new CardGroupList(cardGroup));
}
}
// 从两张牌到三张排序,优先不拆组合牌
if (groupList.Count > 0)
{
groupList = groupList.OrderBy(x=>x.Count).ToList();
groupList.ForEach(x => x.RemoveRange(2, x.Count - 2));
}
return groupList;
}
internal override List<CardGroupList> GetAllEatTipGroupWithLZ(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var cardGroupList = group.CardGroupDic.Where(kv => kv.Key >= 1).SelectMany(kv => kv.Value).ToList();
var groupList = new List<CardGroupList>();
foreach (var cardGroup in cardGroupList)
{
if (cardGroup.Count > 0
&& cardGroup.First().Value > eatStyleInfo.CardValue
&& !IsJoker(cardGroup))
{
List<Card> tmpList = new List<Card>();
tmpList.Add(cardGroup.First());
tmpList.Add(group.LZCards.First());
groupList.Add(new CardGroupList(tmpList));
}
}
if (groupList.Count == 0
&& group.LZCards.Count >= CardCnt
&& IsAllSame(group.LZCards)
&& group.LZCards.First().Value > eatStyleInfo.CardValue)
{
var cardList = group.LZCards.GetRange(0, CardCnt);
groupList.Add(new CardGroupList(cardList));
}
return groupList;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: cbbf72f272f140c2bf88d78ca167115b
timeCreated: 1741678606

View File

@ -0,0 +1,36 @@
using System.Collections.Generic;
using System.Linq;
using GameMessage;
namespace GameFix.Poker
{
public class CardStyle311Helper : CardStyle31Helper
{
public override int CardStyle => DataCardConst.CardStyle311;
public override int CardCnt => 5;
// 4个相同得带一个是否能够出
private bool _isSame4Enable = true;
public CardStyle311Helper(){}
public CardStyle311Helper(bool isSame4Enable){ _isSame4Enable = isSame4Enable; }
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count == CardCnt)
{
for (int i = 0; i < group.CardGroupList.Count; i++)
{
if (group.CardGroupList[i].Count == 3 || (_isSame4Enable && group.CardGroupList[i].Count == 4))
{
cardStyleInfo = new CardStyleInfo(CardStyle, i, group.Cards.Count);
return true;
}
}
}
return false;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f30f25213583439d8ee4b70ecc0b0a32
timeCreated: 1741833322

View File

@ -0,0 +1,46 @@
using System.Collections.Generic;
using GameMessage;
namespace GameFix.Poker
{
/// <summary>
/// 3带2张 特殊牌型
/// 最后一手牌可以带一张或者不带
/// </summary>
public class CardStyle311SpecialHelper : CardStyleBaseHelper
{
public override int CardStyle => DataCardConst.CardStyle311;
public override int CardCnt => 5;
private readonly CardStyle311Helper _cardStyle311 = new();
private readonly CardStyle31Helper _cardStyle31 = new();
private readonly CardStyle3Helper _cardStyle3 = new();
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group is not CardHandGroup) return false;
bool isStyle = false;
if (group.SelfCards.Count == _cardStyle3.CardCnt)
isStyle = _cardStyle3.CheckStyleNormal(group, out cardStyleInfo);
else if (group.SelfCards.Count == _cardStyle31.CardCnt)
isStyle = _cardStyle31.CheckStyleNormal(group, out cardStyleInfo);
else
isStyle = _cardStyle311.CheckStyleNormal(group, out cardStyleInfo);
if (isStyle)
cardStyleInfo.CardStyle = CardStyle;
return isStyle;
}
internal override List<CardGroupList> GetAllEatTipGroup(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
if (group is not CardHandGroup) return new List<CardGroupList>();
if (group.SelfCards.Count == _cardStyle3.CardCnt)
return _cardStyle3.GetAllEatTipGroup(group, eatStyleInfo);
if (group.SelfCards.Count == _cardStyle31.CardCnt)
return _cardStyle31.GetAllEatTipGroup(group, eatStyleInfo);
var allEatTipGroup = _cardStyle311.GetAllEatTipGroup(group, eatStyleInfo);
return allEatTipGroup;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: dd25a8723adf4b9cb658aef67a327ea2
timeCreated: 1779153231

View File

@ -0,0 +1,127 @@
using System.Collections.Generic;
using System.Linq;
using GameMessage;
namespace GameFix.Poker
{
public class CardStyle31Helper : CardStyleBaseHelper
{
public override int CardStyle => DataCardConst.CardStyle31;
public override int CardCnt => 4;
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count == CardCnt)
{
for (int i = 0; i < group.CardGroupList.Count; i++)
{
if (group.CardGroupList[i].Count == 3)
{
cardStyleInfo = new CardStyleInfo(CardStyle, i, group.Cards.Count);
return true;
}
}
}
return false;
}
internal override bool CheckStyleWithLZ(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count == CardCnt)
{
if (IsAllSame(group.NoLZCards)) return false; // 直接组成炸弹
int maxCV = 0;
for (int i = 0; i < group.CardGroupList.Count; i++)
{
if (group.CardGroupList[i].Count + group.LZCards.Count == 3 && i>maxCV)
{
maxCV = i;
}
}
if (maxCV != 0)
{
cardStyleInfo = new CardStyleInfo(CardStyle, maxCV, CardCnt);
cardStyleInfo.CardLackValues = Enumerable.Repeat(maxCV, group.LZCards.Count).ToArray();
return true;
}
}
return false;
}
internal override List<CardGroupList> GetAllEatTipGroup(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var groupCnt = group.CardGroupList.Count;
var groupList = new List<CardGroupList>(groupCnt);
var sortGroupList = group.CardGroupList.OrderBy((x) => x.Count).ToList();
for (int i = 0; i < groupCnt; i++)
{
var cardGroup = group.CardGroupList[i];
if (cardGroup.Count == 3 && IsSameGroupGreater(cardGroup, eatStyleInfo))
{
// 从其他组中找牌
var newCardGroup = new CardGroupList(cardGroup);
for (int j = 0; j < groupCnt; j++)
{
if (sortGroupList[j] != cardGroup && sortGroupList[j].Count >= 1)
{
int needCnt = CardCnt - newCardGroup.Count;
needCnt = needCnt > sortGroupList[j].Count ? sortGroupList[j].Count : needCnt;
newCardGroup.AddRange(sortGroupList[j].GetRange(0, needCnt));
if (newCardGroup.Count == CardCnt)
{
groupList.Add(newCardGroup);
break;
}
}
}
}
}
return groupList;
}
internal override List<CardGroupList> GetAllEatTipGroupWithLZ(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var cardGroupList = group.CardGroupDic.Where(kv => kv.Key >= 1)
.SelectMany(kv => kv.Value).OrderByDescending(x=>x.Count).ToList();
var groupList = new List<CardGroupList>();
foreach (var cardGroup in cardGroupList)
{
if (cardGroup.Count > 0
&& cardGroup.First().Value > eatStyleInfo.CardValue
&& !IsJoker(cardGroup))
{
var needCnt = CardCnt - cardGroup.Count - 1;
if (needCnt <= group.LZCards.Count)
{
List<Card> tmpList = new List<Card>();
tmpList.AddRange(cardGroup);
tmpList.AddRange(group.LZCards.GetRange(0, needCnt));
for (int i = cardGroupList.Count - 1; i >= 0; i--)
{
if (cardGroupList[i] != cardGroup)
{
int wingNeedCnt = CardCnt - tmpList.Count;
wingNeedCnt = wingNeedCnt > cardGroupList[i].Count ? cardGroupList[i].Count : wingNeedCnt;
tmpList.AddRange(cardGroupList[i].GetRange(0, wingNeedCnt));
break;
}
}
if (tmpList.Count == CardCnt)
{
groupList.Add(new CardGroupList(tmpList));
}
}
}
}
return groupList;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1d6a6678f5c6491fb155a6900558fc47
timeCreated: 1741684811

View File

@ -0,0 +1,156 @@
using System.Collections.Generic;
using System.Linq;
using GameMessage;
namespace GameFix.Poker
{
public class CardStyle32Helper : CardStyleBaseHelper
{
public override int CardStyle => DataCardConst.CardStyle32;
public override int CardCnt => 5;
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count == CardCnt)
{
int mainValue = 0, withValue = 0;
for (int i = 0; i < group.CardGroupList.Count; i++)
{
if (group.CardGroupList[i].Count == 3)
{
mainValue = i;
}
if (group.CardGroupList[i].Count == 2)
{
withValue = i;
}
}
if (mainValue > 0 && withValue > 0)
{
cardStyleInfo = new CardStyleInfo(CardStyle, mainValue, group.Cards.Count);
return true;
}
}
return false;
}
internal override bool CheckStyleWithLZ(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count == CardCnt)
{
if (IsAllSame(group.NoLZCards)) return false; // 直接组成炸弹
int lzCount = group.LZCards.Count;
int threeCV = 0, pairCV = 0;
List<int> lackValues = new List<int>(group.LZCards.Count);
for (int i = group.CardGroupList.Count - 1; i >= 0; i--)
{
int cardV = i;
int count = group.CardGroupList[i].Count;
if (count == 0) continue;
int needCnt = 0;
if ((3 - count) <= lzCount)
{
// 找到三张相同的牌
needCnt = 3 - count;
threeCV = cardV;
}
else if ((2 - count) <= lzCount)
{
// 找到两张相同的牌
needCnt = 2 - count;
pairCV = cardV;
}
lzCount -= needCnt;
lackValues.AddRange(Enumerable.Repeat(cardV, needCnt));
}
if (threeCV != 0 && pairCV != 0 && lzCount == 0)
{
cardStyleInfo = new CardStyleInfo(CardStyle, threeCV, CardCnt);
cardStyleInfo.CardLackValues = lackValues.ToArray();
return true;
}
}
return false;
}
internal override List<CardGroupList> GetAllEatTipGroup(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var groupCnt = group.CardGroupList.Count;
var groupList = new List<CardGroupList>(groupCnt);
var sortGroupList = group.CardGroupList.OrderBy((x) => x.Count).ToList();
for (int i = 0; i < groupCnt; i++)
{
var cardGroup = group.CardGroupList[i];
if (cardGroup.Count == 3 && IsSameGroupGreater(cardGroup, eatStyleInfo))
{
// 从其他组中找一对
for (int j = 0; j < groupCnt; j++)
{
if (sortGroupList[j] != cardGroup && sortGroupList[j].Count >= 2)
{
var newCardGroup = new CardGroupList(cardGroup);
newCardGroup.AddRange(sortGroupList[j].GetRange(0, 2));
groupList.Add(newCardGroup);
}
}
}
}
return groupList;
}
internal override List<CardGroupList> GetAllEatTipGroupWithLZ(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var cardGroupList = group.CardGroupDic.Where(kv => kv.Key >= 1)
.SelectMany(kv => kv.Value).OrderByDescending(x=>x.Count).ToList();
var groupList = new List<CardGroupList>();
foreach (var cardGroup in cardGroupList)
{
if (cardGroup.Count > 0
&& cardGroup.First().Value > eatStyleInfo.CardValue
&& !IsJoker(cardGroup))
{
var needCnt = CardCnt - cardGroup.Count - 2;
if (needCnt <= group.LZCards.Count)
{
List<Card> tmpList = new List<Card>();
tmpList.AddRange(cardGroup);
// 获取一个对子,不够用癞子补充
for (int i = cardGroupList.Count - 1; i >= 0; i--)
{
if (cardGroupList[i] != cardGroup && !IsJoker(cardGroupList[i]))
{
if (cardGroupList[i].Count >= 2)
{
tmpList.AddRange(cardGroupList[i].GetRange(0, 2));
break;
}
else if (2 - cardGroupList[i].Count <= group.LZCards.Count - needCnt)
{
tmpList.AddRange(cardGroupList[i]);
needCnt += (2 - cardGroupList[i].Count);
break;
}
}
}
tmpList.AddRange(group.LZCards.GetRange(0, needCnt));
if (tmpList.Count == CardCnt)
{
groupList.Add(new CardGroupList(tmpList));
}
}
}
}
return groupList;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e0e6ce2f17c14aeeb059d36fd28bdb71
timeCreated: 1741684811

View File

@ -0,0 +1,9 @@
namespace GameFix.Poker
{
public class CardStyle3311Helper : CardStyle331Helper
{
public override int CardStyle => DataCardConst.CardStyle3311;
public override int CardCnt => 10;
protected override int GroupCnt => 5;
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b880249d8307412788972a6c10632d88
timeCreated: 1741844953

View File

@ -0,0 +1,71 @@
using System.Collections.Generic;
using GameMessage;
namespace GameFix.Poker
{
/// <summary>
/// 飞机 带 4张
/// 最后一手牌可以少带或者不带
/// </summary>
public class CardStyle3311SpecialHelper : CardStyleBaseHelper
{
public override int CardStyle => DataCardConst.CardStyle3311;
public override int CardCnt => 10;
private readonly CardStyle3311Helper _cardStyle3311 = new();
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
// 手牌对象才检测
if (group is not CardHandGroup) return false;
// 只要是飞机就可以带剩下得牌
// 先过滤是否看有三个得牌
var cardList = new List<CardGroupList>();
foreach (var cardGroup in group.SelfCardGroupDic)
{
if (cardGroup.Key >= 3)
cardList.AddRange(cardGroup.Value);
}
if (cardList.Count >= 2)
{
if (group.SelfCards.Count == group.Cards.Count)
{
// 剩下得牌都出完
if (IsMaxContinuous(group.CardGroupList, 3, out var shunValueList)
&& shunValueList.Count >= 2
&& shunValueList.Count * 5 >= group.Cards.Count)
{
cardStyleInfo = new CardStyleInfo(CardStyle, shunValueList[0], group.Cards.Count);
return true;
}
return false;
}
return _cardStyle3311.CheckStyleNormal(group, out cardStyleInfo);
}
return false;
}
internal override List<CardGroupList> GetAllEatTipGroup(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
// 一定要检测手牌
var ret = new List<CardGroupList>();
if (group is not CardHandGroup handGroup) return ret;
if (group.SelfCardGroupDic.TryGetValue(3, out var cardList)
&& cardList.Count >= 2)
{
// 手上得牌是否可以成为飞机
var cardStyle = handGroup.GetCardStyleInfo(group.SelfCards);
if (cardStyle.CardStyle == CardStyle)
{
ret.Add(new CardGroupList(group.SelfCards));
return ret;
}
return _cardStyle3311.GetAllEatTipGroup(group, eatStyleInfo);
}
return ret;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1590d41252e54faa99b790979e1bbef5
timeCreated: 1779156320

View File

@ -0,0 +1,105 @@
using System.Collections.Generic;
using System.Linq;
using GameMessage;
namespace GameFix.Poker
{
public class CardStyle331Helper : CardStyleBaseHelper
{
public override int CardStyle => DataCardConst.CardStyle331;
public override int CardCnt => 8;
protected virtual int GroupCnt => 4;
// 特殊情况
// 333444 666777888999101010JJJ (理论不存在)
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count >= CardCnt && group.Cards.Count % GroupCnt == 0)
{
if (IsMaxContinuous(group.CardGroupList, 3, out var shunValueList)
&& shunValueList.Count * GroupCnt == group.Cards.Count)
{
cardStyleInfo = new CardStyleInfo(CardStyle, shunValueList[0], group.Cards.Count);
return true;
}
}
return false;
}
internal override bool CheckStyleWithLZ(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count >= CardCnt && group.Cards.Count % GroupCnt == 0)
{
if (IsAllSame(group.NoLZCards)) return false; // 直接组成炸弹
if (IsMaxContinuousByLZ(group.CardGroupList, 3, group.LZCards.Count,
out var shunValueList, out var lackValueList))
{
if (shunValueList.Count * GroupCnt == group.Cards.Count)
{
cardStyleInfo = new CardStyleInfo(CardStyle, shunValueList[0], shunValueList.Count * 4);
cardStyleInfo.CardLackValues = lackValueList.ToArray();
return true;
}
}
}
return false;
}
// 333444555 888
internal override List<CardGroupList> GetAllEatTipGroup(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var groupCnt = group.CardGroupList.Count;
var groupList = new List<CardGroupList>(groupCnt);
var planeHelper = new CardStyle111222Helper();
// 先找到所有的飞机
CardStyleInfo tmpEatStyleInfo = null;
if (eatStyleInfo != null)
tmpEatStyleInfo = new CardStyleInfo(
eatStyleInfo.CardStyle,
eatStyleInfo.CardValue,
eatStyleInfo.CardCnt / GroupCnt * 3);
var allPlaneList = planeHelper.GetAllEatTipGroup(group, tmpEatStyleInfo);
List<Card> wingCards = new List<Card>();
foreach (var plane in allPlaneList)
{
var singleCnt = (plane.Count / 3) * (GroupCnt - 3); // 需要单牌得数量
// 找到符合条件得所有翅膀
var wingGroupList = group.CardGroupDic
.Where(kv => kv.Key >= 1).SelectMany(kv=>kv.Value).ToList();
wingCards.Clear();
foreach (var wingGroup in wingGroupList)
{
if (wingGroup.Count >= 3 && plane.Intersect(wingGroup).Any()) // 翅膀不应该来源于飞机
continue;
// 将翅膀加入列表中
var needCnt = singleCnt - wingCards.Count;
needCnt = needCnt > wingGroup.Count ? wingGroup.Count : needCnt;
wingCards.AddRange(wingGroup.GetRange(0, needCnt));
if (wingCards.Count == singleCnt)
{
plane.AddRange(wingCards);
groupList.Add(new CardGroupList(plane));
break;
}
}
}
return groupList;
}
internal override List<CardGroupList> GetAllEatTipGroupWithLZ(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{// 这里不处理直接找炸弹
return new List<CardGroupList>();
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b2b52aa3f44a4eb792d5f2e8c0137f79
timeCreated: 1741684811

View File

@ -0,0 +1,152 @@
using System;
using System.Collections.Generic;
using System.Linq;
using GameMessage;
namespace GameFix.Poker
{
public class CardStyle332Helper : CardStyleBaseHelper
{
public override int CardStyle => DataCardConst.CardStyle332;
public override int CardCnt => 10;
// 特殊牌型
// 888999 7777
// 666777888999 33334444
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count >= CardCnt && group.Cards.Count % 5 == 0)
{
if (IsMaxContinuous(group.CardGroupList, 3, out var shunValueList))
{
// 检测剩下的是否都是都是一对
int doubleNum = 0;
for (int i = 0; i < group.CardGroupList.Count; i++)
{
var cnt = group.CardGroupList[i].Count;
if (shunValueList.Contains(i))
{ // 超出部分可以组成对子
if (cnt <= 3) continue;
if (cnt % 2 == 0)
{ // 拆了这个组合
doubleNum += cnt / 2;
shunValueList.Remove(i);
} else if ((cnt - 3) % 2 == 0)
{
doubleNum += (cnt - 3) / 2;
}
continue;
}
if (group.CardGroupList[i].Count % 2 == 0)
doubleNum += group.CardGroupList[i].Count / 2;
}
if (IsContinuous(shunValueList)
&& doubleNum == shunValueList.Count
&& shunValueList.Count * 5 == group.Cards.Count)
{
cardStyleInfo = new CardStyleInfo(CardStyle, shunValueList[0], group.Cards.Count);
return true;
}
}
}
return false;
}
internal override bool CheckStyleWithLZ(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count >= CardCnt && group.Cards.Count % 5 == 0)
{
if (IsAllSame(group.NoLZCards)) return false; // 直接组成炸弹
if (IsMaxContinuousByLZ(group.CardGroupList, 3, group.LZCards.Count,
out var shunValueList, out var lackValueList))
{
// 判断剩下得牌是否都是一对
int doubleNum = 0;
int lzCount = group.LZCards.Count - lackValueList.Count;
for (int i = 0; i < group.CardGroupList.Count; i++)
{
int count = group.CardGroupList[i].Count;
if (shunValueList.Contains(i) || count == 0) continue;
if (count == 2 || ((2 - count) <= lzCount && (2 - count) > 0))
{
doubleNum++;
lzCount -= (2 - count);
shunValueList.AddRange(Enumerable.Repeat(i, (2 - count)));
} else if (count == 4 || ((4 - count) <= lzCount && (4 - count) > 0))
{
doubleNum += 2;
lzCount -= (4 - count);
shunValueList.AddRange(Enumerable.Repeat(i, (4 - count)));
}
}
if (doubleNum == shunValueList.Count
&& shunValueList.Count * 5 == group.Cards.Count)
{
cardStyleInfo = new CardStyleInfo(CardStyle, shunValueList[0], shunValueList.Count * 5);
cardStyleInfo.CardLackValues = lackValueList.ToArray();
return true;
}
}
}
return false;
}
internal override List<CardGroupList> GetAllEatTipGroup(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var groupCnt = group.CardGroupList.Count;
var groupList = new List<CardGroupList>(groupCnt);
var planeHelper = new CardStyle111222Helper();
// 先找到所有的飞机
CardStyleInfo tmpEatStyleInfo = null;
if (eatStyleInfo != null)
tmpEatStyleInfo = new CardStyleInfo(
eatStyleInfo.CardStyle,
eatStyleInfo.CardValue,
eatStyleInfo.CardCnt / 5 * 3);
var allPlaneList= planeHelper.GetAllEatTipGroup(group, tmpEatStyleInfo);
List<Card> wingCards = new List<Card>();
foreach (var plane in allPlaneList)
{
var doubleCnt = plane.Count / 3; // 需要对子得数量
// 找到符合条件得所有翅膀
var wingGroupList = group.CardGroupDic
.Where(kv => kv.Key >= 2).SelectMany(kv=>kv.Value).ToList();
wingCards.Clear();
foreach (var wingGroup in wingGroupList)
{
if (wingGroup.Count >= 3 && plane.Intersect(wingGroup).Any()) // 翅膀不应该来源于飞机
continue;
// 将翅膀加入列表中
var needCnt = doubleCnt * 2 - wingCards.Count;
needCnt = needCnt > wingGroup.Count ? wingGroup.Count : needCnt;
needCnt = needCnt % 2 == 0 ? needCnt : needCnt - 1; // 不能为奇数
wingCards.AddRange(wingGroup.GetRange(0, needCnt));
if (wingCards.Count == doubleCnt * 2)
{
plane.AddRange(wingCards);
groupList.Add(new CardGroupList(plane));
break;
}
}
}
return groupList;
}
internal override List<CardGroupList> GetAllEatTipGroupWithLZ(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{// 这里不处理直接找炸弹
return new List<CardGroupList>();
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: eac176f1d3544cdb9160610fe6353bc1
timeCreated: 1741684811

View File

@ -0,0 +1,96 @@
using System.Collections.Generic;
using System.Linq;
using GameMessage;
namespace GameFix.Poker
{
public class CardStyle3Helper : CardStyleBaseHelper
{
public override int CardStyle => DataCardConst.CardStyle3;
public override int CardCnt => 3;
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count == CardCnt && IsAllSame(group.Cards))
{
cardStyleInfo = CardStyleHelper.CreateCardStyleInfo(CardStyle, group.Cards);
return true;
}
return false;
}
internal override bool CheckStyleWithLZ(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count != CardCnt) return false;
if (IsContainJoker(group.NoLZCards)) return false;
if (group.LZCards.Count == group.Cards.Count && IsAllSame(group.LZCards))
{
cardStyleInfo = CardStyleHelper.CreateCardStyleInfo(CardStyle, group.LZCards);
return true;
}
if (IsAllSame(group.NoLZCards))
{
var cardV = group.NoLZCards[0].Value;
cardStyleInfo = new CardStyleInfo(CardStyle, cardV, CardCnt);
cardStyleInfo.CardLackValues = Enumerable.Repeat((int)cardV, group.LZCards.Count).ToArray();
return true;
}
return false;
}
internal override List<CardGroupList> GetAllEatTipGroup(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var groupCnt = group.CardGroupList.Count;
var groupList = new List<CardGroupList>(groupCnt);
for (int i = 0; i < groupCnt; i++)
{
var cardGroup = group.CardGroupList[i];
if (cardGroup.Count == CardCnt && IsSameGroupGreater(cardGroup, eatStyleInfo))
{
groupList.Add(new CardGroupList(cardGroup));
}
}
return groupList;
}
internal override List<CardGroupList> GetAllEatTipGroupWithLZ(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var cardGroupList = group.CardGroupDic.Where(kv => kv.Key >= 1)
.SelectMany(kv => kv.Value).OrderByDescending(x=>x.Count).ToList();
var groupList = new List<CardGroupList>();
foreach (var cardGroup in cardGroupList)
{
if (cardGroup.Count > 0
&& cardGroup.First().Value > eatStyleInfo.CardValue
&& !IsJoker(cardGroup))
{
var needCnt = CardCnt - cardGroup.Count;
if (needCnt < group.LZCards.Count)
{
List<Card> tmpList = new List<Card>();
tmpList.AddRange(cardGroup);
tmpList.AddRange(group.LZCards.GetRange(0, needCnt));
groupList.Add(new CardGroupList(tmpList));
}
}
}
if (groupList.Count == 0
&& group.LZCards.Count >= CardCnt
&& IsAllSame(group.LZCards)
&& group.LZCards.First().Value > eatStyleInfo.CardValue)
{
var cardList = group.LZCards.GetRange(0, CardCnt);
groupList.Add(new CardGroupList(cardList));
}
return groupList;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a5e550c003fb4dc2ad87fd3fd0be483f
timeCreated: 1741684811

View File

@ -0,0 +1,105 @@
using System.Collections.Generic;
using System.Linq;
using GameMessage;
namespace GameFix.Poker
{
public class CardStyle41Helper : CardStyleBaseHelper
{
public override int CardStyle => DataCardConst.CardStyle41;
public override int CardCnt => 6;
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count == CardCnt)
{
for (int i = 0; i < group.CardGroupList.Count; i++)
{
if (group.CardGroupList[i].Count == 4)
{
cardStyleInfo = new CardStyleInfo(CardStyle, i, group.Cards.Count);
return true;
}
}
}
return false;
}
internal override bool CheckStyleWithLZ(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count == CardCnt)
{
if (IsAllSame(group.NoLZCards)) return false; // 直接组成炸弹
int lzCount = group.LZCards.Count;
int fourCV = 0;
List<int> lackValues = new List<int>(group.LZCards.Count);
for (int i = group.CardGroupList.Count - 1; i >= 0; i--)
{
int cardV = i;
int count = group.CardGroupList[i].Count;
int needCnt = 0;
if ((4 - count) <= lzCount)
{
// 找到4张相同的牌
needCnt = 4 - count;
fourCV = cardV;
}
lzCount -= needCnt;
lackValues.AddRange(Enumerable.Repeat(cardV, needCnt));
}
if (lzCount > 0)
{
// 可能还会剩下癞子 (剩下得癞子当成普通牌)
// 也可以处理成替代剩下得牌
lzCount = 0;
}
if (fourCV != 0 && lzCount == 0)
{
cardStyleInfo = new CardStyleInfo(CardStyle, fourCV, CardCnt);
cardStyleInfo.CardLackValues = lackValues.ToArray();
return true;
}
}
return false;
}
internal override List<CardGroupList> GetAllEatTipGroup(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var groupCnt = group.CardGroupList.Count;
var groupList = new List<CardGroupList>(groupCnt);
if (!group.CardGroupDic.ContainsKey(4)) return groupList;
//所有得四张牌组
foreach (var fourCardGroup in group.CardGroupDic[4])
{
if (!IsSameGroupGreater(fourCardGroup, eatStyleInfo)) continue;
// 找两个单张 (不拆牌)
if (group.CardGroupDic.ContainsKey(1) && group.CardGroupDic[1].Count >= 2)
{
var cardGroup42 = new CardGroupList(fourCardGroup);
cardGroup42.AddRange(group.CardGroupDic[1][0]);
cardGroup42.AddRange(group.CardGroupDic[1][1]);
groupList.Add(cardGroup42);
} else if (group.CardGroupDic.ContainsKey(2) && group.CardGroupDic[2].Count >= 1)
{
var cardGroup42 = new CardGroupList(fourCardGroup);
cardGroup42.AddRange(group.CardGroupDic[2][0]);
groupList.Add(cardGroup42);
}
}
return groupList;
}
internal override List<CardGroupList> GetAllEatTipGroupWithLZ(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{// 这里不处理直接找炸弹
return new List<CardGroupList>();
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e7ace734247b43a3b13487dc54d7359d
timeCreated: 1741684811

View File

@ -0,0 +1,111 @@
using System.Collections.Generic;
using System.Linq;
using GameMessage;
namespace GameFix.Poker
{
public class CardStyle42Helper : CardStyleBaseHelper
{
public override int CardStyle => DataCardConst.CardStyle42;
public override int CardCnt => 8;
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count == CardCnt)
{
int mainValue = 0, withValue = 0, withNum = 0;
for (int i = 0; i < group.CardGroupList.Count; i++)
{
if (group.CardGroupList[i].Count == 4)
{
mainValue = i;
}
if (group.CardGroupList[i].Count == 2)
{
withValue = i;
withNum++;
}
}
if (mainValue > 0 && withNum == 2)
{
cardStyleInfo = new CardStyleInfo(CardStyle, mainValue, group.Cards.Count);
return true;
}
}
return false;
}
internal override bool CheckStyleWithLZ(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count == CardCnt)
{
if (IsAllSame(group.NoLZCards)) return false; // 直接组成炸弹
int lzCount = group.LZCards.Count;
int fourCV = 0;
int pairCnt = 0;
List<int> lackValues = new List<int>(group.LZCards.Count);
for (int i = group.CardGroupList.Count - 1; i >= 0; i--)
{
int cardV = i;
int count = group.CardGroupList[i].Count;
int needCnt = 0;
if ((4 - count) <= lzCount)
{
// 找到4张相同的牌
needCnt = 4 - count;
fourCV = cardV;
} else if ((2 - count) <= lzCount && (2 - count) >= 0)
{
// 两对
needCnt = 2 - count;
pairCnt++;
}
lzCount -= needCnt;
lackValues.AddRange(Enumerable.Repeat(cardV, needCnt));
}
if (fourCV != 0 && lzCount == 0 && pairCnt == 2)
{
cardStyleInfo = new CardStyleInfo(CardStyle, fourCV, CardCnt);
cardStyleInfo.CardLackValues = lackValues.ToArray();
return true;
}
}
return false;
}
internal override List<CardGroupList> GetAllEatTipGroup(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var groupCnt = group.CardGroupList.Count;
var groupList = new List<CardGroupList>(groupCnt);
if (!group.CardGroupDic.ContainsKey(4)) return groupList;
//所有得四张牌组
foreach (var fourCardGroup in group.CardGroupDic[4])
{
if (!IsSameGroupGreater(fourCardGroup, eatStyleInfo)) continue;
// 找两个单张 (不拆牌)
if (group.CardGroupDic.ContainsKey(2) && group.CardGroupDic[2].Count >= 2)
{
var cardGroup42 = new CardGroupList(fourCardGroup);
cardGroup42.AddRange(group.CardGroupDic[2][0]);
cardGroup42.AddRange(group.CardGroupDic[2][1]);
groupList.Add(cardGroup42);
}
}
return groupList;
}
internal override List<CardGroupList> GetAllEatTipGroupWithLZ(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{// 这里不处理直接找炸弹
return new List<CardGroupList>();
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 89f4eda5352c47999ae95ed5cfc018bc
timeCreated: 1741684811

View File

@ -0,0 +1,82 @@
using System.Collections.Generic;
using System.Linq;
using GameMessage;
namespace GameFix.Poker
{
public class CardStyle510KHelper : CardStyleBaseHelper
{
public override int CardStyle => DataCardConst.CardStyle510K;
public override int CardCnt => 3;
protected List<int> V_510K = new List<int>(){DataCardConst.CardValue5, DataCardConst.CardValue10, DataCardConst.CardValueK};
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count == CardCnt)
{
var values = group.Cards.Select(x=>(int)x.Value).ToList();
values.Sort();
if (V_510K.SequenceEqual(values))
{
cardStyleInfo = CardStyleHelper.CreateCardStyleInfo(CardStyle, group.Cards);
return true;
}
}
return false;
}
internal override bool CheckStyleWithLZ(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count == CardCnt && group.LZCards.Count == 1)
{ // 只有一个癞子,不然会被当成三个相同
var values = group.Cards.Select(x=>(int)x.Value).ToList();
var exceptV = values.Except(V_510K).ToList();
if (exceptV.Count == 1)
{ // 只有一个不同
cardStyleInfo = CardStyleHelper.CreateCardStyleInfo(CardStyle, group.Cards);
cardStyleInfo.CardLackValues = new[] { exceptV.First() };
return true;
}
}
return false;
}
internal override List<CardGroupList> GetAllEatTipGroup(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var groupList = new List<CardGroupList>(1);
CardGroupList cardGroupList = new CardGroupList();
for (int i = 0; i < V_510K.Count; i++)
{
if (group.CardGroupList[V_510K[i]].Count > 0)
cardGroupList.Add(group.CardGroupList[V_510K[i]].First());
}
if (cardGroupList.Count == CardCnt)
groupList.Add(cardGroupList);
return groupList;
}
internal override List<CardGroupList> GetAllEatTipGroupWithLZ(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var groupList = new List<CardGroupList>(1);
CardGroupList cardGroupList = new CardGroupList();
for (int i = 0; i < V_510K.Count; i++)
{
if (group.CardGroupList[V_510K[i]].Count > 0)
cardGroupList.Add(group.CardGroupList[V_510K[i]].First());
}
if (cardGroupList.Count == 2)
{
cardGroupList.Add(group.LZCards.First());
groupList.Add(cardGroupList);
}
return new List<CardGroupList>(0);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9c9da57bc34c4c26a04ccdecd95fa88b
timeCreated: 1741784659

View File

@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using GameMessage;
namespace GameFix.Poker
{
/// <summary>
/// 多副510K (可带 510k单牌)
/// </summary>
public class CardStyle510KMultExtendHelper : CardStyle510KMultHelper
{
public CardStyle510KMultExtendHelper(int mult) : base(mult)
{
}
internal override List<CardGroupList> GetAllStyleCards(CardBaseGroup group, bool isSplitCard)
{
List<CardGroupList> ret = new List<CardGroupList>();
var c510KList = CardFunc.Get510KList(group.SelfCards, _mult);
if (c510KList.Count > 0)
{
// 剩下得 5 10 k也添加上
var c510KGroup = new CardGroupList(c510KList.SelectMany(x => x));
var c510KCards = group.SelfCards.Where(x => V_510K.Contains(x.Value)).ToList();
c510KGroup.AddRange(c510KCards);
ret.Add(c510KGroup);
}
return ret;
}
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count >= CardCnt)
{
var c510KList = CardFunc.Get510KList(group.Cards, _mult);
var c510KListLong = c510KList.SelectMany(x => x).ToList();
var remainCardList = group.Cards.Where(x => !c510KListLong.Contains(x) && V_510K.Contains(x.Value)).ToList();
if (remainCardList.Count + c510KListLong.Count == group.Cards.Count)
{
cardStyleInfo = new CardStyleInfo(CardStyle, 0, c510KList.Count);
cardStyleInfo.CustomInt = c510KList.Count; // 510K的个数
return true;
}
}
return false;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0ea53d109ec74ae794ff0f676067516c
timeCreated: 1779787226

View File

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Linq;
using GameMessage;
namespace GameFix.Poker
{
/// <summary>
/// 多副510K
/// </summary>
public class CardStyle510KMultHelper : CardStyleBaseHelper
{
public override int CardStyle => DataCardConst.CardStyle510KMult;
public override int CardCnt { get; } = 0;
protected int _mult;
protected List<int> V_510K = new List<int>(){DataCardConst.CardValue5, DataCardConst.CardValue10, DataCardConst.CardValueK};
/// <summary>
/// 几幅起算
/// </summary>
public CardStyle510KMultHelper(int mult)
{
CardCnt = mult * 3;
_mult = mult;
}
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count >= CardCnt)
{
var c510KList = CardFunc.Get510KList(group.Cards, _mult);
if (c510KList.Count * 3 == group.Cards.Count)
{
cardStyleInfo = new CardStyleInfo(CardStyle, 0, c510KList.Count);
cardStyleInfo.CustomInt = c510KList.Count; // 510K的个数
return true;
}
}
return false;
}
internal override List<CardGroupList> GetAllEatTipGroup(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
return GetAllStyleCards(group, false);
}
internal override List<CardGroupList> GetAllStyleCards(CardBaseGroup group, bool isSplitCard)
{
List<CardGroupList> ret = new List<CardGroupList>();
var c510KList = CardFunc.Get510KList(group.SelfCards, _mult);
if (c510KList.Count > 0)
ret.Add(new CardGroupList(c510KList.SelectMany(x=>x)));
return ret;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 871d6a388b274cd9acb178bdf5637f0d
timeCreated: 1779076036

View File

@ -0,0 +1,78 @@
using System.Collections.Generic;
using System.Linq;
using GameMessage;
namespace GameFix.Poker
{
/// <summary>
/// 正510K
/// </summary>
public class CardStyle510KPlusHelper : CardStyle510KHelper
{
public override int CardStyle => DataCardConst.CardStyle510KPlus;
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
var isRight = base.CheckStyleNormal(group, out cardStyleInfo);
if (isRight)
return group.Cards.Select(x => x.Suit).AllElementsSame();
return false;
}
internal override bool CheckStyleWithLZ(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
var isRight = base.CheckStyleNormal(group, out cardStyleInfo);
if (isRight)
return group.Cards.Select(x => x.Suit).AllElementsSame();
return false;
}
internal override List<CardGroupList> GetAllEatTipGroup(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{// 只提示一个
var groupList = new List<CardGroupList>(1);
List<Card> cards = new List<Card>();
foreach (var v in V_510K)
{
if (group.CardGroupList[v].Count > 0)
cards.AddRange(group.CardGroupList[v]);
}
// 按照花色分组
var suitCardDict = cards.GroupBy(x => x.Suit)
.ToDictionary(g => g.Key, g => g.Distinct(new CardValueEqualityComparer()).ToList());
foreach (var suitCards in suitCardDict.Values)
{
if (suitCards.Count != CardCnt) continue;
groupList.Add(new CardGroupList(suitCards));
break;
}
return groupList;
}
internal override List<CardGroupList> GetAllEatTipGroupWithLZ(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var groupList = new List<CardGroupList>(1);
List<Card> cards = new List<Card>();
foreach (var v in V_510K)
{
if (group.CardGroupList[v].Count > 0)
cards.AddRange(group.CardGroupList[v]);
}
// 按照花色分组
var suitCardDict = cards.GroupBy(x => x.Suit)
.ToDictionary(g => g.Key, g => g.Distinct().ToList());
foreach (var suitCards in suitCardDict.Values)
{
if (suitCards.Count != 2) continue;
var cardGroupList = new CardGroupList(suitCards);
cardGroupList.Add(group.LZCards.First());
groupList.Add(cardGroupList);
break;
}
return new List<CardGroupList>(0);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ec36b04d78bd4e08808ff6ecfa8fe62c
timeCreated: 1741828989

View File

@ -0,0 +1,51 @@
using System.Collections.Generic;
using System.Linq;
using GameMessage;
namespace GameFix.Poker
{
public class CardStyle5Helper : CardStyleBaseHelper
{
public override int CardStyle => DataCardConst.CardStyle5;
public override int CardCnt => 2;
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count == CardCnt
&& group.Cards.Count(x=>DataCardConst.JokerValues.Contains(x.Value)) == CardCnt
&& group.Cards[0].Value != group.Cards[1].Value)
{
cardStyleInfo = CardStyleHelper.CreateCardStyleInfo(CardStyle, group.Cards);
return true;
}
return false;
}
internal override bool CheckStyleWithLZ(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
return false;
}
internal override List<CardGroupList> GetAllEatTipGroup(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var groupList = new List<CardGroupList>(1);
if (group.CardGroupList[18].Count>0 && group.CardGroupList[19].Count>0)
{
var cardGroup = new CardGroupList();
cardGroup.AddRange(group.CardGroupList[18]);
cardGroup.AddRange(group.CardGroupList[19]);
groupList.Add(cardGroup);
}
return groupList;
}
internal override List<CardGroupList> GetAllEatTipGroupWithLZ(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
return new List<CardGroupList>(0);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 14e95f3c416848eab6ef7899c7b535f6
timeCreated: 1741684811

View File

@ -0,0 +1,71 @@
using System.Collections.Generic;
using System.Linq;
using GameMessage;
namespace GameFix.Poker
{
/// <summary>
/// 全王炸弹
/// </summary>
public class CardStyleAllJokerBombHelper: CardStyleBaseHelper
{
public override int CardStyle => DataCardConst.CardStyleAllJokerBomb;
public override int CardCnt => mCardCnt;
private int mCardCnt = 4;
public CardStyleAllJokerBombHelper() { }
/// <summary>
/// 构造
/// </summary>
/// <param name="cardCnt">几个王起算炸</param>
public CardStyleAllJokerBombHelper(int cardCnt)
{
mCardCnt = cardCnt;
}
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count >= CardCnt)
{
var isOtherCards = group.Cards.Any(x=>!DataCardConst.JokerValues.Contains(x.Value));
if (isOtherCards) return false;
cardStyleInfo = CardStyleHelper.CreateCardStyleInfo(CardStyle, group.Cards);
return true;
}
return false;
}
internal override bool CheckStyleWithLZ(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
// 癞子不当王
cardStyleInfo = null;
return false;
}
internal override List<CardGroupList> GetAllStyleCards(CardBaseGroup group, bool isSplitCard)
{
List<CardGroupList> ret = new List<CardGroupList>();
var jokerCards = group.SelfCards.Where(x=>DataCardConst.JokerValues.Contains(x.Value)).ToList();
if (jokerCards.Count < CardCnt) return ret;
CardGroupList cardGroupList = new CardGroupList();
cardGroupList.AddRange(jokerCards);
ret.Add(cardGroupList);
return ret;
}
internal override List<CardGroupList> GetAllEatTipGroup(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
return GetAllStyleCards(group, false);
}
internal override List<CardGroupList> GetAllEatTipGroupWithLZ(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
// 癞子不当王
return new List<CardGroupList>();
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1d6cb6966142468396f4d242cd41eab0
timeCreated: 1748936998

View File

@ -0,0 +1,219 @@
using System;
using System.Collections.Generic;
using System.Linq;
using GameMessage;
namespace GameFix.Poker
{
/// <summary>
/// 连炸 3连以上
/// CardStyleInfo.CustomInt: 表示几个相同炸弹组成
/// </summary>
public class CardStyleBomb123Helper : CardStyleBaseHelper
{
public override int CardStyle => DataCardConst.CardStyleBomb123;
public override int CardCnt => 12;
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count >= CardCnt)
{
var keysCnt = group.CardGroupDic.Keys.Count;
if (keysCnt != 1) return false;
var bombSize = group.CardGroupDic.Keys.First(); // 单个炸弹的大小
if (bombSize < 4) return false;
// 判断是否连续
if (IsContinuous(group.CardGroupList, bombSize, out var shunCnt)
&& shunCnt.Count * bombSize == group.Cards.Count)
{
cardStyleInfo = CardStyleHelper.CreateCardStyleInfo(CardStyle, group.Cards);
cardStyleInfo.CustomInt = group.Cards.Count / bombSize;
return true;
}
}
return false;
}
internal override bool CheckStyleWithLZ(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count < CardCnt) return false;
var lzCnt = group.LZCards.Count;
var bombSize = group.CardGroupDic.Keys.Max(); // 最大的数量作为单个炸弹的大小
if (bombSize < 4) lzCnt -= (bombSize - 4);
if (lzCnt < 0) return false;
for (int i = 0; i < group.CardGroupDic.Keys.Count; i++)
{
var key = group.CardGroupDic.Keys.ElementAt(i);
var vList = group.CardGroupDic[key];
var diffSize = bombSize - key;
lzCnt -= diffSize * vList.Count;
if (lzCnt < 0) return false;
}
// 判断是否连续
if (IsMaxContinuousByLZ(group.CardGroupList, bombSize, group.LZCards.Count,
out var shunValueList, out var lackValueList)
&& shunValueList.Count * bombSize == group.Cards.Count)
{
cardStyleInfo = new CardStyleInfo(CardStyle, shunValueList[0], shunValueList.Count * bombSize);
cardStyleInfo.CardLackValues = lackValueList.ToArray();
cardStyleInfo.CustomInt = group.Cards.Count / bombSize;
return true;
}
return false;
}
internal override List<CardGroupList> GetAllEatTipGroup(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var groupCnt = group.CardGroupList.Count;
var groupList = new List<CardGroupList>(groupCnt);
// 找最大的连炸
List<Card> continuousList = new List<Card>();
int minBombSize = Int32.MaxValue;
for (int i = 0; i < group.CardGroupList.Count; i++)
{
if (group.CardGroupList[i].Count >= 4)
{
minBombSize = Math.Min(minBombSize, group.CardGroupList[i].Count);
continuousList.AddRange(group.CardGroupList[i]);
} else if (continuousList.Count >= CardCnt)
{
// 把一些多余的牌删除
var filterList = continuousList.GroupBy(c=>c.Value)
.Select(g=>
Tuple.Create(g.Key,g.ToList().GetRange(0, minBombSize)))
.SelectMany(g=>g.Item2)
.ToList();
// 判断是否属于连炸
var targetGroup = group.mDeck.CreateCardGroup(filterList);
if (targetGroup.GetCardStyleInfo().CardStyle == CardStyle)
{
groupList.Add(new CardGroupList(filterList));
}
minBombSize = Int32.MaxValue;
continuousList.Clear();
}
else if (continuousList.Count > 0)
{
minBombSize = Int32.MaxValue;
continuousList.Clear();
}
}
return groupList;
}
internal override List<CardGroupList> GetAllEatTipGroupWithLZ(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var groupList = new List<CardGroupList>();
// 找最大的连炸
List<Card> continuousList = new List<Card>();
int lzCnt = group.LZCards.Count;
int continuousCnt = 0;
// 2233344444555
for (int i = 0; i < group.CardGroupList.Count; i++)
{
continuousList.Clear();
continuousCnt = 0;
for (int j = 0; j < group.CardGroupList.Count; j++)
{
var index = i + j;
if (index >= group.CardGroupList.Count) break;
if (group.CardGroupList[index].Count == 0) break;
if (group.CardGroupList[index].Count >= 4
|| group.CardGroupList[index].Count + lzCnt >= 4)
{
continuousList.AddRange(group.CardGroupList[index]);
continuousCnt++;
if (continuousCnt >= 3)
{
groupList.Add(new CardGroupList(continuousList));
}
} else
{
continuousList.Clear();
continuousCnt = 0;
}
}
}
// 继续检查每个连炸是否符合要求
for (int i = groupList.Count - 1; i >= 0 ; i--)
{
var bomb = groupList[i];
var bombDict = bomb.GroupBy(c => c.Value)
.ToDictionary(g => g.Key, g => g.ToList());
var bombLine = bombDict.Values.Select(g => g.Count).ToList();
var bombMax = bombLine.Max();
int needCnt = 0;
if (bombMax >= 4)
{
int oldBomMax = bombMax;
while (bombMax >= 4)
{
needCnt = 0;
for (int j = 0; j < bombLine.Count; j++)
{
needCnt += bombMax - bombLine[j];
}
if (needCnt <= lzCnt) break;
bombMax--;
}
if (needCnt > lzCnt)
{
groupList.RemoveAt(i);
continue;
}
// 删除多余得牌
foreach (var bd in bombDict)
{
var rmCards = bd.Value.GetRange(0, oldBomMax - bombMax);
for (int j = rmCards.Count - 1; j >= 0 ; j--)
{
bomb.Remove(rmCards[j]);
}
}
}
else
{
for (int j = 0; j < bombLine.Count; j++)
{
needCnt += 4 - bombLine[j];
}
if (needCnt > lzCnt)
{
groupList.RemoveAt(i);
continue;
}
}
// 再检验一次
bomb.AddRange(group.LZCards.GetRange(0, needCnt));
var bombGroup = group.mDeck.CreateCardGroup(bomb);
if (bombGroup.GetCardStyleInfo().CardStyle != CardStyle)
{
groupList.RemoveAt(i);
}
}
return groupList;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3b2b8f2ee2ed48f2991a8c65d46732fa
timeCreated: 1749020659

View File

@ -0,0 +1,12 @@
namespace GameFix.Poker
{
/// <summary>
/// 连炸 2连以上
/// CardStyleInfo.CustomInt: 表示几个相同炸弹组成
/// </summary>
public class CardStyleBomb12Helper : CardStyleBomb123Helper
{
public override int CardStyle => DataCardConst.CardStyleBomb12;
public override int CardCnt => 8;
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b58721a51e0b4276a356d4e7b914c66d
timeCreated: 1765874379

View File

@ -0,0 +1,120 @@
using System.Collections.Generic;
using System.Linq;
using GameMessage;
namespace GameFix.Poker
{
/// <summary>
/// 炸弹 (四张以上)
/// </summary>
public class CardStyleBombHelper : CardStyleBaseHelper
{
public override int CardStyle => DataCardConst.CardStyleBomb;
public override int CardCnt => 4;
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count >= CardCnt && IsAllSame(group.Cards))
{
cardStyleInfo = CardStyleHelper.CreateCardStyleInfo(CardStyle, group.Cards);
return true;
}
return false;
}
internal override bool CheckStyleWithLZ(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count < CardCnt) return false;
if (group.LZCards.Count == group.Cards.Count && IsAllSame(group.LZCards))
{
cardStyleInfo = CardStyleHelper.CreateCardStyleInfo(CardStyle, group.LZCards);
return true;
}
if (IsAllSame(group.NoLZCards))
{
var cardV = group.NoLZCards[0].Value;
cardStyleInfo = new CardStyleInfo(CardStyle, cardV, group.Cards.Count);
cardStyleInfo.CardLackValues = Enumerable.Repeat((int)cardV, group.LZCards.Count).ToArray();
return true;
}
return false;
}
internal override List<CardGroupList> GetAllStyleCards(CardBaseGroup group, bool isSplitCard)
{
List<CardGroupList> ret = new List<CardGroupList>();
var groupCnt = group.CardGroupList.Count;
for (int i = 0; i < groupCnt; i++)
{
var cardGroup = group.CardGroupList[i];
if (cardGroup.Count >= CardCnt)
{
ret.Add(new CardGroupList(cardGroup));
}
}
return ret;
}
internal override List<CardGroupList> GetAllEatTipGroup(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var groupCnt = group.CardGroupList.Count;
var groupList = new List<CardGroupList>(groupCnt);
for (int i = 0; i < groupCnt; i++)
{
var cardGroup = group.CardGroupList[i];
if (cardGroup.Count >= CardCnt)
{
var cardStyleInfo = CardStyleHelper.CreateCardStyleInfo(CardStyle, cardGroup);
if (eatStyleInfo == null || group.mStyleComparer.Greater(cardStyleInfo, eatStyleInfo))
{
groupList.Add(new CardGroupList(cardGroup));
}
}
}
return groupList;
}
internal override List<CardGroupList> GetAllEatTipGroupWithLZ(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var cardGroupList = group.CardGroupDic.Where(kv => kv.Key >= 1)
.SelectMany(kv => kv.Value).OrderByDescending(x=>x.Count).ToList();
var groupList = new List<CardGroupList>();
if (eatStyleInfo == null)
eatStyleInfo = new CardStyleInfo(CardStyle, 0, CardCnt);
foreach (var cardGroup in cardGroupList)
{
if (cardGroup.Count == 0 || IsJoker(cardGroup)) continue;
var totalCnt = cardGroup.Count + group.LZCards.Count;
if (totalCnt < CardCnt) continue;
var tmpStyleInfo = new CardStyleInfo(CardStyle, cardGroup.First().Value, totalCnt);
int needCnt = 0;
if (group.mStyleComparer.Greater(tmpStyleInfo, eatStyleInfo))
{
needCnt = tmpStyleInfo.CardCnt - cardGroup.Count;
List<Card> tmpList = new List<Card>();
tmpList.AddRange(cardGroup);
tmpList.AddRange(group.LZCards.GetRange(0, needCnt));
groupList.Add(new CardGroupList(tmpList));
}
}
if (groupList.Count == 0)
{ // 癞子是否可以组成炸弹
var tmpStyleInfo = new CardStyleInfo(CardStyle, group.LZCards.First().Value, group.LZCards.Count);
if (group.mStyleComparer.Greater(tmpStyleInfo, eatStyleInfo))
groupList.Add(new CardGroupList(group.LZCards));
}
return groupList;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ee5d4c36a107495aa91cf175575de0d5
timeCreated: 1741848881

View File

@ -0,0 +1,168 @@
using System.Collections.Generic;
using System.Linq;
using GameMessage;
namespace GameFix.Poker
{
/// <summary>
/// 带王炸弹 (四张以上)
/// </summary>
public class CardStyleJokerBombHelper : CardStyleBombHelper
{
public override int CardStyle => DataCardConst.CardStyleJokerBomb;
public override int CardCnt => 4;
private bool isAllJoker = true; // 是否可以组成全王炸弹
public CardStyleJokerBombHelper()
{
}
public CardStyleJokerBombHelper(bool allJoker)
{
isAllJoker = allJoker;
}
internal override bool CheckStyleNormal(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count >= CardCnt)
{
// 先排除王
var bombCards = group.Cards.Where(x=>!DataCardConst.JokerValues.Contains(x.Value)).ToList();
// 判断是否都是王
if (isAllJoker && bombCards.Count == 0)
{
cardStyleInfo = new CardStyleInfo(CardStyle, DataCardConst.JokerValues[0], group.Cards.Count);
return true;
}
if (IsAllSame(bombCards) && bombCards.Count >= CardCnt)
{
cardStyleInfo = new CardStyleInfo(CardStyle, bombCards.First().Value, group.Cards.Count);
return true;
}
}
return false;
}
internal override bool CheckStyleWithLZ(CardBaseGroup group, out CardStyleInfo cardStyleInfo)
{
cardStyleInfo = null;
if (group.Cards.Count < CardCnt) return false;
if (group.LZCards.Count == group.Cards.Count && IsAllSame(group.LZCards))
{
cardStyleInfo = CardStyleHelper.CreateCardStyleInfo(CardStyle, group.LZCards);
return true;
}
// 先排除王
var bombCards = group.NoLZCards.Where(x=>!DataCardConst.JokerValues.Contains(x.Value)).ToList();
// 判断是否都是王
if (isAllJoker && bombCards.Count == 0)
{
cardStyleInfo = new CardStyleInfo(CardStyle, DataCardConst.JokerValues[0], group.Cards.Count);
return true;
}
if (IsAllSame(bombCards) && bombCards.Count + group.LZCards.Count >= CardCnt)
{
var cardV = bombCards[0].Value;
cardStyleInfo = new CardStyleInfo(CardStyle, cardV, group.Cards.Count);
cardStyleInfo.CardLackValues = Enumerable.Repeat((int)cardV, group.LZCards.Count).ToArray();
return true;
}
return false;
}
internal override List<CardGroupList> GetAllEatTipGroup(CardBaseGroup group, CardStyleInfo eatStyleInfo)
{
var groupCnt = group.CardGroupList.Count;
var groupList = new List<CardGroupList>(groupCnt);
var jokerList = group.Cards.Where(x=>DataCardConst.JokerValues.Contains(x.Value)).ToList();
if (eatStyleInfo == null)
eatStyleInfo = new CardStyleInfo(CardStyle, 0, CardCnt);
if (isAllJoker && jokerList.Count >= CardCnt)
{ // 先提示全王
var tmpStyleInfo = new CardStyleInfo(CardStyle, DataCardConst.JokerValues[0], jokerList.Count);
if (group.mStyleComparer.Greater(tmpStyleInfo, eatStyleInfo))
{
groupList.Add(new CardGroupList(jokerList));
}
}
var filterGroupList = group.CardGroupList.Where(x => x.Count >= CardCnt).ToList();
for (int i = 0; i < filterGroupList.Count; i++)
{
var cardGroup = filterGroupList[i];
if (IsJoker(cardGroup)) continue;
var tmpStyleInfo = new CardStyleInfo(CardStyle, cardGroup.First().Value, cardGroup.Count);
if (group.mStyleComparer.Greater(tmpStyleInfo, eatStyleInfo) && filterGroupList.Count > 1)
{
groupList.Add(new CardGroupList(cardGroup));
} else {
tmpStyleInfo = new CardStyleInfo(CardStyle, cardGroup.First().Value, cardGroup.Count + jokerList.Count);
if (group.mStyleComparer.Greater(tmpStyleInfo, eatStyleInfo))
{
var cardGroupList = new CardGroupList(cardGroup);
cardGroupList.AddRange(jokerList);
groupList.Add(cardGroupList);
}
}
}
return groupList;
}
/// <summary>
/// 获取所有得炸弹
/// </summary>
public List<CardGroupList> GetAllBombs(CardBaseGroup group)
{
List<CardGroupList> groupList = new List<CardGroupList>();
var jokerList = group.Cards
.Where(x => DataCardConst.JokerValues.Contains(x.Value) && x.CardType != DataCardConst.CardTypeLZ)
.ToList();
var descCardGroupList = group.CardGroupList.Select(x => x).OrderByDescending(x => x.Count).ToList();
var lzCnt = group.LZCards.Count;
for (int i = 0; i < descCardGroupList.Count; i++)
{
if (IsJoker(descCardGroupList[i]) ||descCardGroupList[i].Count + lzCnt < CardCnt) continue;
CardGroupList cardGroupList = new CardGroupList();
cardGroupList.AddRange(descCardGroupList[i]);
if (lzCnt > 0)
{
cardGroupList.AddRange(group.LZCards);
lzCnt = 0;
}
if (jokerList.Count > 0)
{
cardGroupList.AddRange(jokerList);
jokerList.Clear();
}
CardStyleInfo styleInfo =
new CardStyleInfo(CardStyle, descCardGroupList[i].First().Value, cardGroupList.Count);
cardGroupList.CardStyleInfo = styleInfo;
groupList.Add(cardGroupList);
}
if (jokerList.Count > CardCnt && isAllJoker)
{
CardGroupList cardGroupList = new CardGroupList();
cardGroupList.AddRange(jokerList);
jokerList.Clear();
CardStyleInfo styleInfo =
new CardStyleInfo(CardStyle, jokerList.First().Value, cardGroupList.Count);
cardGroupList.CardStyleInfo = styleInfo;
groupList.Add(cardGroupList);
}
return groupList;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b4ef4d49fafc4db09cc09e3d471c45c5
timeCreated: 1741850722