using System; using System.Collections.Generic; using System.Linq; using GameMessage; namespace GameFix.Poker { public static class PokerLogic { public class XY { public int x; //牌面大小 public int y; //次数 } /// /// 获取所有的单张 /// /// public static List GetDanZhang(IPlayOutCardType1 outCard, T[] cards, bool chaiDan = false) where T : ICardInfoType1 { if (outCard.GameNum <= 0 || cards == null || cards.Length <= 0) return null; Dictionary dic = new Dictionary(); List result = new List(); foreach (var item in cards) { if (item.GameNum <= outCard.GameNum) continue; if (dic.ContainsKey(item.GameNum)) { if (dic[item.GameNum] == 1) { dic[item.GameNum]++; if (!chaiDan || (chaiDan && dic[item.GameNum] >= 4)) result.RemoveAll(x => x.GameNum == item.GameNum); } } else { dic[item.GameNum] = 1; result.Add(item); } } return result; } /// /// 获取连续的相同大小的张数 /// /// /// 手里没有打下去的牌 /// 几张大小相同的个数 /// 手里全部的牌 /// public static List> GetLianCount(IPlayOutCardType1 outCard, T[] cards, int count, T[] shouPai) where T : ICardInfoType1 { if (outCard.GameNum <= 0 || cards == null || cards.Length <= 3) return null; int lian = 0; //连了几下 if (outCard.Type == CardType1.LianDui) { lian = outCard.Ids.Length / 2; //是几连对 } if (outCard.Type == CardType1.FeiJi) { lian = GetFeiJiCount(GetCardByIds(shouPai, outCard.Ids)); //是几连飞机 } List> result = new List>(); var countCard = GetCountCard(outCard, cards, count, true, true, lian - 2); if (countCard.Count < lian) return result; for (int i = 0; i < countCard.Count - 1; i++) { List temp = new List(); int c = 1; int num = countCard[i][0].GameNum; temp.AddRange(countCard[i]); for (int j = i + 1; j < countCard.Count; j++) { if (countCard[j][0].GameNum + 1 == num) { temp.AddRange(countCard[j]); c++; num = countCard[j][0].GameNum; } if (c == lian) break; } if (c == lian) { result.Add(temp); } } return result; } /// /// 根据牌的绝对Id返回牌的详细信息 /// /// 玩家手牌 /// 牌的Id集合 /// public static T[] GetCardByIds(T[] wanshouPai, byte[] ids) where T : ICardInfoType1 { if (ids == null || ids.Length <= 0) return null; if (wanshouPai == null || wanshouPai.Length <= 0) return null; List result = new List(); foreach (var id in ids) { foreach (var item in wanshouPai) { if (item.ID == id) { result.Add(item); break; } } } if (ids.Length != result.Count) { throw new Exception($"获取玩家的牌张数不对 idslen:{ids.Length} result len:{result.Count} "); } return result.ToArray(); } /// /// 获取飞机的连的个数,长度 /// /// /// public static int GetFeiJiCount(T[] selectCards) where T : ICardInfoType1 { if (selectCards == null || selectCards.Length < 6) return 0; List list = new List(); foreach (var item in selectCards) { var t = list.Find(x => x.x == item.GameNum); if (t != null) { t.y++; } else { list.Add(new XY { x = item.GameNum, y = 1 }); } } int num = list.Count(x => x.y >= 3); if (num < 2) return 0; list = list.Where(x => x.y >= 3).ToList(); List fj = new List(); for (int i = 0; i < list.Count - 1; i++) { if (list[i].x - 1 == list[i + 1].x) { if (!fj.Contains(list[i].x)) { fj.Add(list[i].x); } if (!fj.Contains(list[i + 1].x)) { fj.Add(list[i + 1].x); } } } return fj.Count; } /// /// 获取玩家手里几张相同的牌型 /// /// 玩家出的牌 /// 玩家手里没有出下去的牌 /// 要获取相同大小的张数 /// 是否拆牌 false不拆 true拆 /// 是否获取跟出牌大小相等的牌 true是 false不是 /// public static List> GetCountCard(IPlayOutCardType1 outCard, T[] cards, int count, bool chai = false, bool deng = false, int cha = 0) where T : ICardInfoType1 { if (count <= 0 || outCard.GameNum <= 0 || cards == null || cards.Length < count) return null; List> result = new List>(); Dictionary dic = new Dictionary(); foreach (var item in cards) { if (deng) { if (item.GameNum < outCard.GameNum - cha) continue; } else { if (item.GameNum <= outCard.GameNum - cha) continue; } if (dic.ContainsKey(item.GameNum)) { dic[item.GameNum]++; } else { dic[item.GameNum] = 1; } } foreach (var item in dic) { if (item.Value >= 4 && count < 4 && chai) continue; //炸弹就不拆 if (!chai) { if (item.Value != count) continue; result.Add(cards.Where(x => x.GameNum == item.Key).ToList()); } else { if (item.Value < count) continue; result.Add(cards.Where(x => x.GameNum == item.Key).Take(count).ToList()); } } return result; } /// /// 是否是对子 /// 跑得快朋友房使用了 /// /// /// public static bool IsDuiZi(T[] selectCards) where T : ICardInfoType1 { if (selectCards == null || selectCards.Length != 2) return false; return selectCards[0].GameNum == selectCards[1].GameNum; } /// /// 获取顺子 /// /// /// public static List> GetShunZi(T[] playCard) where T : ICardInfoType1 { if (playCard == null || playCard.Length < 5) return null; var cards = playCard.ToList(); List> result = new List>(); for (int i = 14; i > 6; i--) { List shunzi = new List(); for (int j = 0; j < playCard.Length; j++) { T temp = cards.FirstOrDefault(x => x.GameNum == (i - j)); if (temp.ID > 0) { shunzi.Add(temp); } else { break; } } if (shunzi.Count >= 5) { result.Add(shunzi); } } return result; } /// /// 获取顺子 /// /// /// /// public static List> GetShunZi(IPlayOutCardType1 outCard, T[] playCard) where T : ICardInfoType1 { if (outCard.GameNum <= 0 || outCard.Type != CardType1.ShunZi) return null; if (playCard == null || playCard.Length < outCard.Ids.Length) return null; var cards = playCard.ToList(); List> result = new List>(); for (int i = 14; i > outCard.GameNum; i--) { List shunzi = new List(); for (int j = 0; j < outCard.Ids.Length; j++) { T temp = cards.FirstOrDefault(x => x.GameNum == (i - j)); if (temp.ID > 0) { shunzi.Add(temp); } else { break; } } if (shunzi.Count == outCard.Ids.Length) { result.Add(shunzi); } } return result; } /// /// 是否是飞机 跑得快朋友房使用了 /// /// 选中的牌 /// true不够 false 够 /// true可以带牌 false不可以带牌 /// 返回飞机面值 /// public static bool IsFeiJi(T[] selectCards, bool isPaiBuGou, bool canDaiPia, out byte gameNum) where T : ICardInfoType1 { gameNum = 0; if (selectCards == null || selectCards.Length < 6) return false; List list = new List(); foreach (var item in selectCards) { var t = list.Find(x => x.x == item.GameNum); if (t != null) { t.y++; if (t.y >= 3) { if (gameNum == 0) gameNum = item.GameNum; } } else { list.Add(new XY { x = item.GameNum, y = 1 }); } } int num = list.Count(x => x.y >= 3); if (num < 2) return false; //if (canDaiPia && isPaiBuGou && selectCards.Length < num * 3) return false; //功能相同 list = list.Where(x => x.y >= 3).ToList(); List fj = new List(); for (int i = 0; i < list.Count - 1; i++) { if (list[i].x - 1 == list[i + 1].x) { if (!fj.Contains(list[i].x)) { fj.Add(list[i].x); } if (!fj.Contains(list[i + 1].x)) { fj.Add(list[i + 1].x); } } } num = fj.Count; if (num < 2) return false; gameNum = (byte)fj[0]; if (!canDaiPia && num * 3 != selectCards.Length) return false; //如果不能带牌 if (selectCards.Length > num * 3 + num * 2) return false; //带多了 if (canDaiPia && !isPaiBuGou && num * 3 + num * 2 != selectCards.Length) return false; num--; for (int i = 0; i < fj.Count; i++) { if (num == 1) { //2连的飞机 return fj[i] - num == fj[i + num]; } else if (num == 2) { //3连的飞机 return fj[i] == fj[i + 1] + 1 && fj[i + 1] == fj[i + 2] + 1; } else if (num == 3) { //4连的飞机 return fj[i] == fj[i + 1] + 1 && fj[i + 1] == fj[i + 2] + 1 && fj[i + 2] == fj[i + 3] + 1; } else { if (fj[i] - num != fj[i + num]) { return false; } } } return true; } /// /// 判断是否是顺子,使用该函数前请先排序 跑得快朋友房使用了 /// /// /// public static bool IsShunzi(T[] selectCards) where T : ICardInfoType1 { if (selectCards == null || selectCards.Length < 5) return false; T temp = selectCards[0]; for (int i = 1; i < selectCards.Length; i++) { if (selectCards[i].GameNum != temp.GameNum - 1) return false; //不是连续的 temp = selectCards[i]; } return true; } /// /// 给牌排序 跑得快朋友房使用了 /// /// public static void SortCardByGameNum(ref T[] cards) where T : ICardInfoType1 { if (cards == null || cards.Length < 2) return; Array.Sort(cards, (x, y) => y.GameNum.CompareTo(x.GameNum)); } /// /// 是否是连对,,使用该函数前请先排序 跑得快朋友房使用了 /// /// /// public static bool IsLianDui(T[] selectCards) where T : ICardInfoType1 { if (selectCards == null || selectCards.Length < 4 || selectCards.Length % 2 != 0) return false; T temp = selectCards[0]; for (int i = 0; i < selectCards.Length; i += 2) { if (selectCards[i].GameNum != selectCards[i + 1].GameNum) return false; //不是一对的牌 if (i + 2 <= selectCards.Length - 1) { if (temp.GameNum != selectCards[i + 2].GameNum + 1) return false; //不是顺子 temp = selectCards[i + 2]; } } return true; } /// /// 获取玩家炸弹,没有炸弹则out就是废王的牌 /// 需要先排序才可以运算 /// /// 玩家手牌 /// 炸弹的牌 或者 废王的牌 /// true有炸弹 false没有炸弹 public static bool GetPlayZhaDan(T[] playCards, out List cards) where T : ICardInfoType1 { cards = new List(); if (playCards == null || playCards.Length <= 0) return false; List result = new List(); List temp = new List(); List wang = new List(); byte count = 0; byte num = 0; foreach (var item in playCards) { if (item.GameNum == 98 || item.GameNum == 100) { wang.Add(item); continue; } if (num == 0 && count == 0) { num = item.GameNum; count++; temp.Add(item); } else { if (num == item.GameNum) { count++; temp.Add(item); } else { num = item.GameNum; count = 1; if (temp.Count >= 4) { result.AddRange(temp); } temp.Clear(); temp.Add(item); } } } if (temp.Count >= 4) //防止最后一张牌遗漏 { result.AddRange(temp); } temp.Clear(); if (result.Count >= 4) { result.AddRange(wang); cards.AddRange(result); return true; } cards = wang; if (wang.Count >= 4) { return true; } return false; } /// /// 获取玩家的炸弹 /// /// 玩家手牌 /// 炸弹的牌 /// true有炸弹 false没有炸弹 public static bool GetPlayZhaDans(T[] playCards, out List> cards) where T : ICardInfoType1 { cards = new List>(); if (playCards == null || playCards.Length <= 0) return false; List temp = new List(); byte count = 0; byte num = 0; foreach (var item in playCards) { if (num == 0 && count == 0) { num = item.GameNum; count++; temp.Add(item); } else { if (num == item.GameNum) { count++; temp.Add(item); } else { num = item.GameNum; count = 1; if (temp.Count >= 4) { cards.Add(temp.ToList()); } temp.Clear(); temp.Add(item); } } } if (temp.Count >= 4) //防止最后一张牌遗漏 { cards.Add(temp.ToList()); } return cards.Count > 0; } /// /// 是否是三带二 跑得快朋友房使用了 /// /// 要判断的牌 /// 玩家手牌是不是不够张数带牌true不够 false够 /// #pragma warning disable CS1573 // 参数在 XML 注释中没有匹配的 param 标记(但其他参数有) public static bool IsSanDaiEr(T[] selectCards, bool isPaiBuGou, out byte gameNum) where T : ICardInfoType1 #pragma warning restore CS1573 // 参数在 XML 注释中没有匹配的 param 标记(但其他参数有) { gameNum = 0; if (selectCards == null || selectCards.Length < 4 || selectCards.Length > 5) return false; if (!isPaiBuGou && selectCards.Length != 5) return false; Dictionary dic = new Dictionary(); foreach (var item in selectCards) { if (dic.ContainsKey(item.GameNum)) { dic[item.GameNum]++; } else { dic[item.GameNum] = 1; } } if (dic.Count > 3 || dic.Count < 2) return false; var b = false; foreach (var item in dic) { if (item.Value >= 3 && item.Key < 90) //大王不能当成3个一起出 { gameNum = item.Key; b = true; break; } } return b; } /// /// 检测是否有相同的ID,因为牌的ID是唯一的,不会相同 /// /// /// true有 false没有 public static bool CheckSameId(byte[] ids) { if (ids == null || ids.Length <= 1) return false; Dictionary did = new Dictionary(); for (int i = 0; i < ids.Length; i++) { if (did.ContainsKey(ids[i])) { did[ids[i]]++; } else { did[ids[i]] = 1; } } foreach (var id in did) { if (id.Value > 1) { return true; } } return false; } /// /// 给牌排序,按照个数从大到小 /// /// /// public static T[] SortCardByCount(T[] cards) where T : ICardInfoType1 { if (cards == null || cards.Length <= 0) return null; List result = new List(); Dictionary> dics = new Dictionary>(); for (int i = 0; i < cards.Length; i++) { if (cards[i].GameNum > 20) { result.Add(cards[i]); continue; } if (dics.ContainsKey(cards[i].GameNum)) { dics[cards[i].GameNum].Add(cards[i]); } else { var temp = new List(); temp.Add(cards[i]); dics.Add(cards[i].GameNum, temp); } } var newdics = dics.OrderByDescending(x => x.Value.Count); foreach (var item in newdics) { result.AddRange(item.Value); } return result.ToArray(); } public static string GetGameNumToString(byte gameNum) { string result = ""; if (gameNum <= 0) return result; if (gameNum >= 3 && gameNum <= 10) { result = gameNum.ToString(); } else { switch (gameNum) { case 11: result = "J"; break; case 12: result = "Q"; break; case 13: result = "K"; break; case 14: result = "A"; break; case 16: result = "2"; break; //叫牌中不会有大小王 } } return result; } } }