/// <summary> /// 能够鸣牌计算 /// </summary> private List <FuruAble> isCanFuru() { // 获得刚刚打牌的玩家的牌河和打出的牌 List <MahjongCard> played_cards = GetPlayerCardPlayed(Playing); MahjongCard last_played = played_cards.Last(); // 最后一张 // 比对其他三家的手牌 List <FuruAble> furuAbles = new List <FuruAble>(); // 记录是否有玩家可以碰或者杠以减少不必要的计算 bool hasPongKong = false; // 遍历所有其它玩家 for (int player = 0; player < 4; player++) { if (player == Playing) { continue; // 跳过自己 } // 获得手牌 List <MahjongCard> player_hand = GetPlayerCardOnHand(player); // 记录可副露牌组 FuruAble furuAble = new FuruAble(player); // 如果已经有别的玩家可以碰杠,则不可能再有玩家可以碰杠 if (hasPongKong == false) { // 优先找出杠子和刻子 IEnumerable <MahjongCard> PongKong = from card in player_hand where card == last_played select card; if (PongKong.Count() >= 2) { hasPongKong = true; // 可以碰 furuAble.FuruableList.Add(new MahjongCardFuru() { cards = Enumerable.Repeat(last_played, 2).ToList(), target = Playing, type = FuruType.Pong, }); if (PongKong.Count() == 3) { // 可以杠 furuAble.FuruableList.Add(new MahjongCardFuru() { cards = Enumerable.Repeat(last_played, 3).ToList(), target = Playing, type = FuruType.Kong, }); hasPongKong = true; } } } if (last_played.type == MahjongCardType.Char) { // 年级和小组顺子(吃) // 年级顺子 MahjongCardName name = last_played.name; MahjongCardGradeType grade = last_played.grade; MahjongCardGroupType group = last_played.group; IEnumerable <IGrouping <MahjongCardName, MahjongCard> > grade_chi = from card in player_hand where (card.grade == grade) && (card.name != name) && (card.type == MahjongCardType.Char) && (card.@group == @group) group card by card.name into g select g; if (grade_chi.Count() == 2) { // 至少要有两种同年级的牌才可以吃 // 获得要吃的牌 List <MahjongCard> chi = new List <MahjongCard>(); foreach (IGrouping <MahjongCardName, MahjongCard> cards in grade_chi) { chi.Add(cards.First()); } // 加入可副露列表 furuAble.FuruableList.Add(new MahjongCardFuru() { cards = chi, target = Playing, type = FuruType.ChiGrade, }); } // 小组顺子 MahjongCardSquadType squad = last_played.squad; IEnumerable <IGrouping <MahjongCardName, MahjongCard> > squad_chi = from card in player_hand where (card.squad == squad) && (card.name != name) && (card.type == MahjongCardType.Char) group card by card.name into g select g; if (squad_chi.Count() == 2) { // 至少要有两种同小组的牌才可以吃 // 获得要吃的牌 List <MahjongCard> chi = new List <MahjongCard>(); foreach (IGrouping <MahjongCardName, MahjongCard> cards in squad_chi) { chi.Add(cards.First()); } // 加入可副露列表 furuAble.FuruableList.Add(new MahjongCardFuru() { cards = chi, target = Playing, type = FuruType.ChiSquad, }); } } furuAbles.Add(furuAble); } return(furuAbles); }
/// <summary> /// 和牌判定(除去雀头和副露) /// </summary> /// <param name="cards">手牌</param> /// <param name="start">从第几张手牌开始找刻子</param> /// <returns>是否和牌</returns> private bool isHu(List <MahjongCard> cards, int start, ref List <HuCard> huCard) { if (cards.Count == 0) { return(true); // 空牌和 } if (cards.Count < 3) { return(false); // 剩牌不和 } // 针对第一张牌开始寻找刻子和顺子 IEnumerable <MahjongCard> u = from card in cards where card.name == cards[start].name select card; int count = u.Count(); if (count >= 3) { // 将刻子加入牌组 HuCard hucard = new HuCard() { type = HuCardType.PongKong, furu = false, cards = new List <MahjongCard>() { cards[start], cards[start + 1], cards[start + 2] }, }; huCard.Add(hucard); // 删除这个刻子 for (int m = 0; m < 3; m++) { cards.RemoveAt(start); } // 递归判和 return(isHu(cards, ref huCard)); } else { if (start + 1 < cards.Count) { return(isHu(cards, start + 1, ref huCard)); } else { // 寻找顺子(年级和小组顺子) MahjongCard cur_card = u.First(); // 获得牌种 MahjongCardType type = cur_card.type; // 只有角色牌才可以凑成年级或小组顺子 if (type == MahjongCardType.Char) { // 获得团体、年级和小组信息 MahjongCardGroupType group = cur_card.group; MahjongCardGradeType grade = cur_card.grade; MahjongCardSquadType squad = cur_card.squad; // 确认同团体的牌有至少三张 IEnumerable <MahjongCard> same_group = from card in cards where (card.name != cur_card.name) && (card.@group == @group) && (card.type == MahjongCardType.Char) select card; if (same_group.Count() >= 2) { // 判断同年级/同小组 IEnumerable <MahjongCard> same_grade = from card in same_group where card.grade == grade select card; IEnumerable <MahjongCard> same_squad = from card in same_group where card.squad == squad select card; IEnumerable <MahjongCard> determine; bool GradeOrSquad = false; if (same_grade.Count() >= 2) { GradeOrSquad = false; determine = same_grade; // 判断同年级 } else if (same_squad.Count() >= 2) { GradeOrSquad = true; determine = same_squad; // 判断同小队 } else { return(false); } // 每种牌只找出一张 IEnumerable <MahjongCard> not_same = from card in determine group card by card.name into g select g.First(); if (not_same.Count() >= 2) { MahjongCard[] not_same_cards = not_same.ToArray(); // 将顺子加入牌组 HuCard hucard = new HuCard() { type = (GradeOrSquad) ? HuCardType.SquadChi : HuCardType.GradeChi, furu = false, cards = new List <MahjongCard>() { cur_card, not_same_cards[0], not_same_cards[1] }, }; huCard.Add(hucard); // 从手牌中删除 bool p = true, q = true, r = true; // 防止重复删除 for (int i = 0; i < cards.Count; i++) { if ((cards[i].name == cur_card.name) && p) { p = false; cards.RemoveAt(i); i--; continue; } if ((cards[i].name == not_same_cards[0].name) && q) { q = false; cards.RemoveAt(i); i--; continue; } if ((cards[i].name == not_same_cards[1].name) && r) { r = false; cards.RemoveAt(i); i--; continue; } if (!(p || q || r)) { break; } } // 递归判和 return(isHu(cards, ref huCard)); } } } } return(false); } }