/// <summary> /// 摊牌检测 /// 1. 有王没炸弹 /// 2. 达到炸弹封顶 /// </summary> /// <param name="self"></param> /// <returns></returns> private static bool CheckTanCard(this GameController self) { Room room = self.GetParent <Room>(); var gameInfo = room.GetComponent <GameInfo>(); foreach (Player player in room.Players) { var cards = player.GetComponent <HandCardsComponent>().Cards; List <AnalyseResult> analyseResults = AnalyseResult.Analyse(cards); int jokerCount = analyseResults.GetJokerCount(); if (jokerCount == 4) { return(true); } // 炸弹 analyseResults = analyseResults.GetBooms(); // 有王没有炸弹 if (jokerCount > 0 && analyseResults.Count == 0) { return(true); } // 炸弹封顶 if (analyseResults.Any(result => result.Count + jokerCount >= gameInfo.BoomTop)) { return(true); } } return(false); }
/// <summary> /// 王罚分 /// </summary> /// <param name="self"></param> private static void JokerScore(this GameController self) { var room = self.GetParent <Room>(); foreach (Player player in room.Players) { var cards = player.GetComponent <HandCardsComponent>().Cards; if (cards.Count == 0) { continue; } List <AnalyseResult> analyseResults = AnalyseResult.Analyse(cards); // 一旦存在炸弹,就不需要罚王了。 if (analyseResults.Any(f => f.Count >= 4 && !CardsHelper.IsJoker(f.Weight))) { continue; } int jokerCount = analyseResults.GetJokerCount(); // joker数量为4不需要罚王,算做9炸分. if (jokerCount == 4) { continue; } // 罚分 self.SetScore(player, -(jokerCount * 3)); } }
/// <summary> /// 炸弹排序 /// 玩家手牌视图的两种排序(普通排序、炸弹排序) /// 炸弹提出来最后 /// </summary> /// <param name="cards"></param> /// <param name="jokerBefore"></param> public static void BoomSort(List <Card> cards, bool jokerBefore = true) { Sort(cards); // 分析牌的数量 List <AnalyseResult> analyseResults = AnalyseResult.Analyse(cards); // 王的数量 int jokerCount = analyseResults.Count(f => f.Weight == CardWeight.SJoker || f.Weight == CardWeight.LJoker); // 数量>=4的牌就是炸弹 analyseResults = analyseResults.Where(analyseResult => analyseResult.Count >= 4).ToList(); // 没有一个炸弹 if (analyseResults.Count == 0) { return; } // 如果joker数量有4个,就归为炸弹. if (jokerCount != 4) { if (!jokerBefore) { jokerCount = 0; } } // 先把炸弹按照数量进行,再把炸弹插入到所有joker的前面。 analyseResults.Sort((a, b) => { int x = a.Count * 100 + (int)a.Weight; int y = b.Count * 100 + (int)b.Weight; if (x > y) { return(1); } if (x < y) { return(-1); } return(0); }); // 移除炸弹牌,如果需要插入到王前面就放到前面,不需要就插入到尾巴上. foreach (AnalyseResult result in analyseResults) { foreach (Card card in result.Cards) { cards.Remove(card); cards.Insert(cards.Count - jokerCount, card); } } }
/// <summary> /// 配王算分 /// </summary> /// <param name="self"></param> private static void FetchJokerBoomScore(this GameController self) { var room = self.GetParent <Room>(); var gameInfo = self.Parent.GetComponent <GameInfo>(); foreach (Player player in room.Players) { List <Card> cards = player.GetComponent <HandCardsComponent>().Cards; if (cards.Count == 0) { continue; } List <AnalyseResult> analyseResults = AnalyseResult.Analyse(cards); int jokerCount = analyseResults.GetJokerCount(); if (jokerCount == 4) { self.BoomScore(player, gameInfo.BoomTop); jokerCount = 0; } analyseResults = analyseResults.GetBooms(); // 按照数量降序 analyseResults.Sort(); // 配王 foreach (AnalyseResult analyseResult in analyseResults) { // 最多8张牌 int boomCount = analyseResult.Count; if (jokerCount > 0) { // 需要多少张王 int a = gameInfo.BoomTop - boomCount; // 取小(jokerCount,a) a = a > jokerCount? jokerCount : a; // 减去用了的 jokerCount -= a; // 配上的 boomCount += a; } self.BoomScore(player, boomCount); } } }
/// <summary> /// 炸弹:四个(含四个)以上相同点的牌叫炸弹,可以炸任何类型的牌,炸弹的大小 按数量及2>A>K>Q>J>10>9……..3排序,相同数目的炸按先出顺序比大小(如:四个3先出,则后出的四个3不能压)。 /// </summary> /// <param name="cards"></param> /// <returns></returns> public static bool IsBoom(List <Card> cards) { // 炸弹最少4张牌, 最多12张 if (cards.Count < 4 || cards.Count > 12) { return(false); } List <AnalyseResult> analyseResults = AnalyseResult.Analyse(cards); // 结果不能大于3种,因为不算花色,加上大小王最多3种牌。 if (analyseResults.Count > 3) { return(false); } // 只有一种牌,并且大于等于4张 if (analyseResults.Count == 1 && analyseResults[0].Count >= 4) { return(true); } // 把王排除掉,后有且只能有一种牌。 int jokerCount = analyseResults.Count(f => f.Weight == CardWeight.LJoker || f.Weight == CardWeight.SJoker); if (analyseResults.Count - jokerCount != 1) { return(false); } // 并且剩下的那种牌的数量必须>=4 foreach (AnalyseResult analyseResult in analyseResults) { // 跳过王 if (analyseResult.Weight == CardWeight.LJoker || analyseResult.Weight == CardWeight.SJoker) { continue; } if (analyseResult.Count < 4) { return(false); } } return(true); }
/// <summary> /// 特殊牌型,4张王,最大的8炸。 /// </summary> /// <param name="cards"></param> /// <returns></returns> public static bool IsJokerBoom(List <Card> cards) { if (cards.Count != 4) { return(false); } List <AnalyseResult> analyseResults = AnalyseResult.Analyse(cards); if (analyseResults.Count != 2) { return(false); } // 4张王 return(analyseResults[0].Count == 2 && analyseResults[1].Count == 2 && IsJoker(analyseResults[0].Weight) && IsJoker(analyseResults[1].Weight)); }
/// <summary> /// 数量权重排序 /// 一些牌型验证需要使用 /// 比如出三带二、连三带二时、炸弹时。多的牌在前面 /// </summary> /// <param name="cards"></param> public static void WeightSort(List <Card> cards) { Sort(cards); // 分析每张牌的数量 List <AnalyseResult> analyseResults = AnalyseResult.Analyse(cards); // 按照数量以及权重进行牌型,数量>权重 analyseResults.Sort(); // 从排序结果中 cards.Clear(); foreach (AnalyseResult result in analyseResults) { if (result.Count > 0) { cards.AddRange(result.Cards); } } }
/// <summary> /// 连三带二:牌点连续的两个(含两个)以上的三张+随意4张(6张、8张、、、,2不出现连三中) /// </summary> /// <returns></returns> public static bool IsTripleStraight(List <Card> cards) { // 牌数不对 if (cards.Count < 10 || cards.Count % 5 != 0) { return(false); } List <AnalyseResult> analyseResults = AnalyseResult.Analyse(cards); // 3张的牌有几个 analyseResults = analyseResults.Where(f => f.Count >= 3).ToList(); // 匹配成功目标个数 int targetNum = cards.Count / 5; int matchNum = 0; // 3张的牌的权重依次递增: 3334443456需要给通过,但视图现在显示为:3333444456 // 3335556668 // 反向判定,按出牌最大的权重算. 3334445556 : 444555 for (int i = analyseResults.Count - 1; i > 0; i++) { // 排除2 if (analyseResults[i].Weight - analyseResults[i - 1].Weight == 1 && analyseResults[i].Weight != CardWeight._2 && analyseResults[i - 1].Weight != CardWeight._2) { matchNum += 2; if (matchNum == targetNum) { return(true); } } } return(false); }
/// <summary> /// 获取牌组权重 /// 已经按照数量权重排序 /// </summary> /// <param name="cards"></param> /// <param name="type"></param> /// <returns></returns> public static int GetWeight(this IReadOnlyList <Card> cards, CardType type) { int w = 0; switch (type) { case CardType.None: break; case CardType.ThreeAndTwo: { w += (int)cards[0].Weight * 3; break; } case CardType.TripleStraight: { // 需要进行分析,因为特殊牌型:3333344444 3333444456 再排序上是挨着一起的。 List <AnalyseResult> analyseResults = AnalyseResult.Analyse(cards); // 需要计算的次数 int targetNum = cards.Count / 5; int matchNum = 0; analyseResults = analyseResults.Where(f => f.Count >= 3).ToList(); // 反向求权重,按出牌最大的权重算. 3334445556 : 444555 for (int i = analyseResults.Count - 1; i > 0; i++) { // 排除2 if (analyseResults[i].Weight - analyseResults[i - 1].Weight == 1 && analyseResults[i].Weight != CardWeight._2 && analyseResults[i - 1].Weight != CardWeight._2) { w += (int)analyseResults[i].Weight * 3; w += (int)analyseResults[i - 1].Weight * 3; matchNum += 2; if (matchNum == targetNum) { break; } } } break; } case CardType.Boom: // 数量占大头 + 除王的权重值 w = int.MaxValue / 2 + cards.Count * 100 + cards.Where(card => !IsJoker(card)).Sum(card => (int)card.Weight); break; case CardType.JokerBoom: w = int.MaxValue; break; // 直接求和的 case CardType.Single: case CardType.Double: case CardType.OnlyThree: case CardType.DoubleStraight: case CardType.Straight: default: w = cards.Sum(c => (int)c.Weight); break; } return(w); }