using System.Collections.Generic; using System.Linq; using GameFix.Poker; using GameMessage; using GameMessage.PaoDeKuaiF; namespace GameFix.PaoDeKuaiF { /// /// 跑得快牌运算逻辑 /// public class PdkCardAlgorithm { /// /// 获取提示的牌 /// /// 当前出的牌 /// 玩家在手里的牌,没有出下去的牌 /// 当前出牌人的手牌 /// 3A是不是炸弹,默认不是 /// 只要一种提示 true是 false不是 /// public static List> GetTipCardByBtn(PlayOutCardPdkF outCard, TCardInfoPdkF[] shoupai, TCardInfoPdkF[] maxShouPai, bool aaaIsZhaDan = false, bool isOne = false) { if (shoupai == null || shoupai.Length <= 0) return null; List> result = new List>(); if (outCard.GameNum <= 0) { //如果是自己先出的话, 就从尾部一张一张提示过去 for (int i = shoupai.Length - 1; i >= 0; i--) { List chu = new List(); chu.Add(shoupai[i]); result.Add(chu); } return result; } switch (outCard.Type) { case CardType1.DanZhang: var danzhangs = PokerLogic.GetDanZhang(outCard, shoupai); if (danzhangs == null || danzhangs.Count <= 0) { danzhangs = PokerLogic.GetDanZhang(outCard, shoupai, true); } if (danzhangs != null && danzhangs.Count > 0) { danzhangs.Sort((x, y) => x.GameNum.CompareTo(y.GameNum)); foreach (var item in danzhangs) { List chu = new List { item }; result.Add(chu); } } break; case CardType1.DuiZi: result = PokerLogic.GetCountCard(outCard, shoupai, 2); if (result == null || result.Count <= 0) { result = PokerLogic.GetCountCard(outCard, shoupai, 2, true); } if (result != null) { result.Sort((x, y) => x[0].GameNum.CompareTo(y[0].GameNum)); } break; case CardType1.SanDai2: result = PokerLogic.GetCountCard(outCard, shoupai, 3, true); if (result != null) result.Sort((x, y) => x[0].GameNum.CompareTo(y[0].GameNum)); break; case CardType1.ShunZi: result = PokerLogic.GetShunZi(outCard, shoupai); if (result != null) result.Sort((x, y) => x[0].GameNum.CompareTo(y[0].GameNum)); break; case CardType1.LianDui: result = PokerLogic.GetLianCount(outCard, shoupai, 2, null); if (result != null) result.Sort((x, y) => x[0].GameNum.CompareTo(y[0].GameNum)); break; case CardType1.FeiJi: result = PokerLogic.GetLianCount(outCard, shoupai, 3, maxShouPai); if (result != null) result.Sort((x, y) => x[0].GameNum.CompareTo(y[0].GameNum)); break; case CardType1.ZhaDan: PokerLogic.GetPlayZhaDan(shoupai, out var cards); if (cards.Count > 4) { int c = cards.Count / 4; for (int i = 0; i < c; i++) { var tx = cards.Skip(i * 4).Take(4).ToList(); if (tx != null && tx[0].GameNum > outCard.GameNum) { result.Add(tx); } } } else { if (cards != null && cards.Count > 0 && cards[0].GameNum > outCard.GameNum) { result.Add(cards); } } break; } if (isOne && result != null && result.Count > 0) { //只要一种提示 } else { if (result == null) result = new List>(); if (aaaIsZhaDan) { var aaa = GetAAAZhaDan(shoupai); if (aaa != null && aaa.Count >= 3) { result.Add(aaa); } } if (outCard.Type != CardType1.ZhaDan) { PokerLogic.GetPlayZhaDan(shoupai, out var cards); if (cards != null && cards.Count > 0) { int c = cards.Count / 4; if (c <= 0) { result.Add(cards); } else { for (int i = 0; i < c; i++) { result.Add(cards.Skip(i * 4).Take(4).ToList()); } } } } } return result; } /// /// 获取提示的牌 /// /// 当前出的牌 /// 玩家在手里的牌,没有出下去的牌 /// 当前出牌人的手牌 /// 3A是不是炸弹,默认不是 /// 只要一种提示 true是 false不是 /// public static List> GetTipCard(PlayOutCardPdkF outCard, TCardInfoPdkF[] shoupai, TCardInfoPdkF[] maxShouPai, bool aaaIsZhaDan = false, bool isOne = false) { if (shoupai == null || shoupai.Length <= 0) return null; List> result = new List>(); if (outCard.GameNum <= 0) { //如果是自己先出的话, 就从尾部一张一张提示过去 for (int i = shoupai.Length - 1; i >= 0; i--) { List chu = new List(); chu.Add(shoupai[i]); result.Add(chu); } return result; } switch (outCard.Type) { //飞机带翅膀、炸弹,四带三、四带二 case CardType1.DanZhang: var danzhangs = shoupai.Where(x => x.GameNum > outCard.GameNum); if (danzhangs.Count() > 0) { foreach (var item in danzhangs) { List chu = new List(); chu.Add(item); result.Add(chu); } } break; case CardType1.DuiZi: result = PokerLogic.GetCountCard(outCard, shoupai, 2, true); break; case CardType1.SanDai2: result = PokerLogic.GetCountCard(outCard, shoupai, 3, true); break; case CardType1.ShunZi: result = PokerLogic.GetShunZi(outCard, shoupai); break; case CardType1.LianDui: result = PokerLogic.GetLianCount(outCard, shoupai, 2, null); break; case CardType1.FeiJi: result = PokerLogic.GetLianCount(outCard, shoupai, 3, maxShouPai); break; case CardType1.ZhaDan: PokerLogic.GetPlayZhaDan(shoupai, out var cards); if (cards != null && cards.Count > 0 && cards[0].GameNum > outCard.GameNum) { result.Add(cards); } break; } if (result == null) result = new List>(); if (isOne && result != null && result.Count > 0) { //只要一种提示 } else { if (aaaIsZhaDan) { var aaa = GetAAAZhaDan(shoupai); if (aaa != null && aaa.Count >= 3) { result.Add(aaa); } } if (outCard.Type != CardType1.ZhaDan) { PokerLogic.GetPlayZhaDan(shoupai, out var cards); if (cards != null && cards.Count > 0) { result.Add(cards); } } } return result; } /// /// 判断是否是炸弹 /// /// /// /// /// public static bool IsZhaDan(TCardInfoPdkF[] cards, bool aaaIsZhaDan, bool isCheckPaiCount = true) { if (cards == null || cards.Length < 3 || cards.Length > 4) return false; if (aaaIsZhaDan && cards.Length == 3) { return Is3A(cards); } if (cards.Length == 4) { return IsZhaDan(cards, isCheckPaiCount); } return false; } /// /// 检查玩家是否有比出的牌更大的牌 /// /// 玩家出的牌 /// 自己的手牌-在手里的牌,并且是排序过的。 /// 出牌人的手牌 /// 3A是不是炸弹,默认不是 /// true有比玩家大的牌 false没有 public static bool CheckHaveBigger(PlayOutCardPdkF outCard, TCardInfoPdkF[] shouPai, TCardInfoPdkF[] maxShouPai, bool aaaIsZhaDan = false) { if (shouPai == null || shouPai.Length <= 0) return false; List> cs = null; List cards = null; switch (outCard.Type) { case CardType1.DanZhang: if (shouPai.Where(x => x.GameNum > outCard.GameNum).Count() > 0) { return true; } break; case CardType1.DuiZi: cs = PokerLogic.GetCountCard(outCard, shouPai, 2, true); if (cs != null && cs.Count > 0) { return true; } break; case CardType1.SanDai2: cs = PokerLogic.GetCountCard(outCard, shouPai, 3, true); if (cs != null && cs.Count > 0) { return true; } break; case CardType1.ShunZi: cs = PokerLogic.GetShunZi(outCard, shouPai); if (cs != null && cs.Count > 0) { return true; } break; case CardType1.LianDui: cs = PokerLogic.GetLianCount(outCard, shouPai, 2, null); if (cs != null && cs.Count > 0) { return true; } break; case CardType1.FeiJi: cs = PokerLogic.GetLianCount(outCard, shouPai, 3, maxShouPai); if (cs != null && cs.Count > 0) { return true; } break; case CardType1.ZhaDan: var b = PokerLogic.GetPlayZhaDan(shouPai, out cards); if (!b) return false; foreach (var item in cards) { if (item.GameNum > outCard.GameNum) return true; } break; } if (aaaIsZhaDan) { var aaa = GetAAAZhaDan(shouPai); if (aaa != null && aaa.Count >= 3) { return true; } } if (outCard.Type != CardType1.ZhaDan) { return PokerLogic.GetPlayZhaDan(shouPai, out cards); } return false; } /// /// 通过选中的牌返回出下去牌的类型 否则选中的牌就不能出下去 /// 一般客户端用 /// /// 选中的牌 /// 玩家手牌,不包含已经出下去的牌 /// 规则玩法 /// 返回出牌内容 /// true可以出牌 false不能出牌 public static bool GetOutCard(TCardInfoPdkF[] selectCards, TCardInfoPdkF[] shouPai, PdkRule wangfa, out PlayOutCardPdkF paycard) { paycard = new PlayOutCardPdkF(); if (selectCards == null || selectCards.Length <= 0 || shouPai == null || shouPai.Length <= 0) return false; var chaCard = shouPai.Except(selectCards); //获取差集,如果个数大于0说明牌的张数是够的,如果是0,说明牌不够 PokerLogic.SortCardByGameNum(ref selectCards); var bugou = chaCard.Count() <= 0; byte gameNum = 0; if (selectCards.Length == 1) { //单张可以出 paycard.Ids = new byte[] { selectCards[0].ID }; paycard.GameNum = selectCards[0].GameNum; paycard.Type = CardType1.DanZhang; return true; } else if (selectCards.Length == 2) { //对子 if (PokerLogic.IsDuiZi(selectCards)) { paycard.Ids = selectCards.Select(x => x.ID).ToArray(); paycard.GameNum = selectCards[0].GameNum; paycard.Type = CardType1.DuiZi; return true; } } else if (selectCards.Length == 3) { if (wangfa.AAAIsZhaDan && Is3A(selectCards)) //3A是炸弹 { paycard.Ids = selectCards.Select(x => x.ID).ToArray(); paycard.GameNum = selectCards[0].GameNum; paycard.Type = CardType1.ZhaDan; return true; } else { bool xt = selectCards[0].GameNum == selectCards[1].GameNum && selectCards[2].GameNum == selectCards[1].GameNum; if (xt && bugou) { paycard.GameNum = selectCards[0].GameNum; paycard.Type = CardType1.SanDai2; paycard.Ids = selectCards.Select(x => x.ID).ToArray(); return true; } } } else { if (IsZhaDan(selectCards)) //炸弹 { paycard.GameNum = selectCards[0].GameNum; //因为该值会根据大小排序 paycard.Type = CardType1.ZhaDan; paycard.Ids = selectCards.Select(x => x.ID).ToArray(); return true; } if (wangfa.SiDai2 && IsSiDai2(selectCards, !bugou, out gameNum)) { //四带二 paycard.GameNum = gameNum; paycard.Type = CardType1.SiDai2; paycard.Ids = selectCards.Select(x => x.ID).ToArray(); return true; } if (wangfa.SiDai3 && IsSiDai3(selectCards, !bugou, out gameNum)) { //四带二 paycard.GameNum = gameNum; paycard.Type = CardType1.SiDai3; paycard.Ids = selectCards.Select(x => x.ID).ToArray(); return true; } if (PokerLogic.IsShunzi(selectCards)) { //顺子 paycard.GameNum = selectCards[0].GameNum; paycard.Type = CardType1.ShunZi; paycard.Ids = selectCards.Select(x => x.ID).ToArray(); return true; } if (PokerLogic.IsLianDui(selectCards)) //连对 { paycard.GameNum = selectCards[0].GameNum; paycard.Type = CardType1.LianDui; paycard.Ids = selectCards.Select(x => x.ID).ToArray(); return true; } if (PokerLogic.IsSanDaiEr(selectCards, bugou, out gameNum)) //三带二、 { paycard.GameNum = gameNum; paycard.Type = CardType1.SanDai2; paycard.Ids = selectCards.Select(x => x.ID).ToArray(); return true; } if (PokerLogic.IsFeiJi(selectCards, bugou, true, out gameNum)) //飞机带翅膀 { paycard.GameNum = gameNum; paycard.Type = CardType1.FeiJi; paycard.Ids = selectCards.Select(x => x.ID).ToArray(); return true; } } return false; } /// /// 是否是3张A /// /// /// true是 false不是 static bool Is3A(TCardInfoPdkF[] cards) { if (cards == null || cards.Length != 3) return false; return cards[0].GameNum == 14 && cards[1].GameNum == 14 && cards[2].GameNum == 14; } /// /// 获取3A炸弹 /// /// 玩家手里没有打下去的牌 /// static List GetAAAZhaDan(TCardInfoPdkF[] cards) { if (cards == null || cards.Length < 3) return null; List result = new List(); for (int i = 0; i < cards.Length; i++) { if (cards[i].GameNum == 14) { result.Add(cards[i]); } } if (result.Count >= 3) { return result; } return null; } static bool IsSiDai3(TCardInfoPdkF[] selectCards, bool isPaiBuGou, out byte gameNum) { gameNum = 0; if (selectCards == null || selectCards.Length < 5 || selectCards.Length > 7) return false; if (isPaiBuGou && selectCards.Length != 7) return false; var b = PokerLogic.GetPlayZhaDan(selectCards, out var cards); if (!b) return b; gameNum = cards[0].GameNum; return true; } /// /// 是否是四带二 /// /// /// true牌够,false牌不够 /// true是 false不是 #pragma warning disable CS1573 // 参数在 XML 注释中没有匹配的 param 标记(但其他参数有) static bool IsSiDai2(TCardInfoPdkF[] selectCards, bool isPaiBuGou, out byte gameNum) #pragma warning restore CS1573 // 参数在 XML 注释中没有匹配的 param 标记(但其他参数有) { gameNum = 0; if (selectCards == null || selectCards.Length < 5 || selectCards.Length > 6) return false; if (isPaiBuGou && selectCards.Length != 6) return false; var b = PokerLogic.GetPlayZhaDan(selectCards, out var cards); if (!b) return b; gameNum = cards[0].GameNum; return true; } /// /// 判断是否是炸弹 /// /// /// 是否要校验牌的张数对不对 /// static bool IsZhaDan(TCardInfoPdkF[] selectCards, bool isCheckPaiCount = true) { if (selectCards == null || selectCards.Length < 4) return false; int gameNum = 0; foreach (var item in selectCards) { if (gameNum == 0) { gameNum = item.GameNum; continue; } if (gameNum != item.GameNum) { //炸弹的牌不是一样的牌 return false; } } var b = PokerLogic.GetPlayZhaDan(selectCards, out var cards); if (!b) return b; if (isCheckPaiCount) { //校验返回的炸弹牌数量和传入的牌数量是不是一样多 return selectCards.Length == cards.Count; } return true; } /// /// 判断是否有炸弹 /// /// /// AAA是否是炸弹 true是 false不是 /// public static bool IsHaveBomb(TCardInfoPdkF[] selectCards, bool aaaIsBomb) { if (selectCards == null || selectCards.Length < 3) return false; if (!aaaIsBomb && selectCards.Length < 4) return false; Dictionary dic = new Dictionary(); for (int i = 0; i < selectCards.Length; i++) { if (dic.ContainsKey(selectCards[i].GameNum)) { dic[selectCards[i].GameNum]++; } else { dic[selectCards[i].GameNum] = 1; } } foreach (var item in dic) { if (aaaIsBomb && item.Key == 14 && item.Value == 3) return true; if (item.Value >= 4) return true; } return false; } } }