public static int CompareHandPoker(HandPokerInfo poker1, HandPokerInfo poker2) { switch (poker2.result.type) { case HandPokerType.个: case HandPokerType.对: case HandPokerType.条: case HandPokerType.条带一个: case HandPokerType.条带一对: if (poker1.result.type == poker2.result.type) { return(poker1.result.compareValue.CompareTo(poker2.result.compareValue)); } if (poker1.result.type == HandPokerType.四条炸 || poker1.result.type == HandPokerType.王炸) { return(1); } return(-1); case HandPokerType.顺子: case HandPokerType.连对: case HandPokerType.飞机: case HandPokerType.飞机带个: case HandPokerType.飞机带队: if (poker1.result.type == poker2.result.type && poker1.result.value.Length == poker1.result.value.Length) { return(poker1.result.compareValue.CompareTo(poker2.result.compareValue)); } if (poker1.result.type == HandPokerType.四条炸 || poker1.result.type == HandPokerType.王炸) { return(1); } return(-1); case HandPokerType.炸带二个: case HandPokerType.炸带二对: if (poker1.result.type == poker2.result.type) { return(poker1.result.compareValue.CompareTo(poker2.result.compareValue)); } if (poker1.result.type == HandPokerType.四条炸 || poker1.result.type == HandPokerType.王炸) { return(1); } return(-1); case HandPokerType.四条炸: case HandPokerType.王炸: if (poker1.result.type == poker2.result.type) { return(poker1.result.compareValue.CompareTo(poker2.result.compareValue)); } if (poker1.result.type == HandPokerType.四条炸 || poker1.result.type == HandPokerType.王炸) { return(1); } return(-1); } return(-1); }
/// <summary> /// 出牌 /// </summary> /// <param name="playerId"></param> /// <param name="poker"></param> public void Play(string playerId, int[] poker) { if (this.Data.stage != GameStage.斗地主) throw new ArgumentException($"游戏阶段错误,当前阶段:{this.Data.stage}"); var playerIndex = this.Data.players.FindIndex(a => a.id == playerId); if (playerIndex == -1) throw new ArgumentException($"{playerId} 不在本局游戏"); if (playerIndex != this.Data.playerIndex) throw new ArgumentException($"还没有轮到 {playerId} 出牌"); if (poker == null || poker.Length == 0) throw new ArgumentException("poker 不能为空"); foreach (var pk in poker) if (this.Data.players[this.Data.playerIndex].poker.Contains(pk) == false) throw new ArgumentException($"{playerId} 手上没有这手牌"); var hand = new HandPokerInfo { time = DateTime.Now, playerIndex = this.Data.playerIndex, result = Utils.ComplierHandPoker(poker) }; if (hand.result == null) throw new ArgumentException("poker 不是有效的一手牌"); if (this.Data.chupai.Any() && this.Data.chupai.Last().playerIndex != this.Data.playerIndex && Utils.CompareHandPoker(hand, this.Data.chupai.Last()) <= 0) throw new ArgumentException("poker 打不过上一手牌"); this.Data.chupai.Add(hand); foreach (var pk in poker) this.Data.players[this.Data.playerIndex].poker.Remove(pk); if (hand.result.type == HandPokerType.四条炸 || hand.result.type == HandPokerType.王炸) this.Data.bong += 1; if (this.Data.players[this.Data.playerIndex].poker.Count == 0) { var wealth = this.Data.multiple * (this.Data.multipleAddition + this.Data.bong); var dizhuWinner = this.Data.players[this.Data.playerIndex].role == GamePlayerRole.地主; this.Data.stage = GameStage.游戏结束; this.EventSave(); WriteLog($"{this.Data.players[playerIndex].id} 出牌 {hand.result.text},【游戏结束】,{(dizhuWinner? GamePlayerRole.地主 : GamePlayerRole.农民)} 获得了胜利,本局炸弹 {this.Data.bong}个,结算金额 {wealth}"); this.OnGameOver?.Invoke(this.Id, this.Data); } else { if (++this.Data.playerIndex >= this.Data.players.Count) this.Data.playerIndex = 0; this.EventSave(); WriteLog($"{this.Data.players[playerIndex].id} 出牌 {hand.result.text},轮到 {this.Data.players[this.Data.playerIndex].id} 出牌"); this.OnNextPlay?.Invoke(this.Id, this.Data); } }
/// <summary> /// 出牌 /// </summary> /// <param name="playerId"></param> /// <param name="poker"></param> public void Play(string playerId, int[] poker) { if (this.Data.stage != GameStage.斗地主) throw new ArgumentException($"游戏阶段错误,当前阶段:{this.Data.stage}"); var playerIndex = this.Data.players.FindIndex(a => a.id == playerId); if (playerIndex == -1) throw new ArgumentException($"{playerId} 不在本局游戏"); if (playerIndex != this.Data.playerIndex) throw new ArgumentException($"还没有轮到 {playerId} 出牌"); if (poker == null || poker.Length == 0) throw new ArgumentException("poker 不能为空"); foreach (var pk in poker) if (this.Data.players[this.Data.playerIndex].poker.Contains(pk) == false) throw new ArgumentException($"{playerId} 手上没有这手牌"); var hand = new HandPokerInfo { time = DateTime.Now, playerIndex = this.Data.playerIndex, result = Utils.ComplierHandPoker(Utils.GroupByPoker(poker)) }; if (hand.result == null) throw new ArgumentException("poker 不是有效的一手牌"); var uphand = this.Data.chupai.LastOrDefault(); if (uphand != null && uphand.playerIndex != this.Data.playerIndex && Utils.CompareHandPoker(hand, uphand) <= 0) throw new ArgumentException("poker 打不过上一手牌"); this.Data.chupai.Add(hand); foreach (var pk in poker) this.Data.players[this.Data.playerIndex].poker.Remove(pk); if (hand.result.type == HandPokerType.四条炸 || hand.result.type == HandPokerType.王炸) this.Data.bong += 1; if (this.Data.players[this.Data.playerIndex].poker.Count == 0) { var wealth = this.Data.multiple * (this.Data.multipleAddition + this.Data.bong); var dizhuWinner = this.Data.players[this.Data.playerIndex].role == GamePlayerRole.地主; this.Data.stage = GameStage.游戏结束; foreach (var player in this.Data.players) { if (dizhuWinner) player.score = player.role == GamePlayerRole.地主 ? 2 * wealth : -wealth; else player.score = player.role == GamePlayerRole.地主 ? 2 * -wealth : wealth; } this.SaveData(); WriteLog($"{this.Data.players[playerIndex].id} 出牌 {hand.result.text},【游戏结束】,{(dizhuWinner ? GamePlayerRole.地主 : GamePlayerRole.农民)} 获得了胜利,本局炸弹 {this.Data.bong}个,结算金额 {wealth}"); } else { if (++this.Data.playerIndex >= this.Data.players.Count) this.Data.playerIndex = 0; this.Data.operationTimeout = DateTime.UtcNow.AddSeconds(30); this.SaveData(); WriteLog($"{this.Data.players[playerIndex].id} 出牌 {hand.result.text},轮到 {this.Data.players[this.Data.playerIndex].id} 出牌"); OnNextPlay?.Invoke(this); } NextAutoOperator(this); }
/// <summary> /// 从手中所有牌中,查找能压死 uphand 的打法 /// </summary> /// <param name="allpoker">所有牌</param> /// <param name="uphand">要压死的牌</param> /// <returns></returns> public static List <int[]> GetAllTips(IEnumerable <int> allpoker, HandPokerInfo uphand) { var pokers = allpoker.ToArray(); var gb = Utils.GroupByPoker(pokers); var jokers = gb.Where(a => a.count == 1 && a.key == 16 || a.key == 17).Select(a => a.poker.First()).ToArray(); var ret = new List <int[]>(); if (uphand == null) { var hand = Utils.ComplierHandPoker(gb); //尝试一手出完 if (hand != null && hand.type != HandPokerType.炸带二个 && hand.type != HandPokerType.炸带二对) { return(new List <int[]>(new[] { hand.value })); } var gb1 = gb.Where(a => a.count == 1 && (jokers.Length == 2 && a.key != 16 && a.key != 17 || jokers.Length < 2)).OrderBy(a => a.key).FirstOrDefault(); //忽略双王 var gb2 = gb.Where(a => a.count == 2).OrderBy(a => a.key).FirstOrDefault(); if (gb1 != null && (gb2 == null || gb1.key < gb2.key)) { return(new List <int[]>(new[] { gb1.poker.ToArray() })); } if (gb2 != null && (gb1 == null || gb2.key < gb1.key)) { return(new List <int[]>(new[] { gb2.poker.ToArray() })); } return(new List <int[]>(new[] { new[] { gb.Min(a => a.key) } })); } if (uphand.result.type == HandPokerType.个) { var gb1 = gb.Where(a => a.count == 1 && a.key > uphand.result.compareValue && (jokers.Length == 2 && a.key != 16 && a.key != 17 || jokers.Length < 2)).OrderBy(a => a.key); //忽略双王 if (gb1.Any()) { ret.AddRange(gb1.Select(a => a.poker.ToArray())); } if (gb1.Any() == false) { var gb2 = gb.Where(a => a.count == 2 && a.key > uphand.result.compareValue).OrderBy(a => a.key); if (gb2.Any()) { foreach (var g2 in gb2) { ret.AddRange(g2.poker.OrderBy(a => a).Select(a => new[] { a })); } } } if (gb1.Any() == false) { var gb3 = gb.Where(a => a.count == 3 && a.key > uphand.result.compareValue).OrderBy(a => a.key); if (gb3.Any()) { foreach (var g3 in gb3) { ret.AddRange(g3.poker.OrderBy(a => a).Select(a => new[] { a })); } } } if (ret.Any() == false) { var gb4 = gb.Where(a => a.count == 4).OrderByDescending(a => a.key); if (gb4.Any()) { ret.AddRange(gb4.Select(a => a.poker.OrderByDescending(z => z).ToArray())); } } if (ret.Any() == false) { if (jokers.Length == 2) { ret.Add(jokers); } } return(ret); } if (uphand.result.type == HandPokerType.对) { var gb2 = gb.Where(a => a.count == 2 && a.key > uphand.result.compareValue).OrderBy(a => a.key); if (gb2.Any()) { ret.AddRange(gb2.Select(a => a.poker.OrderByDescending(b => b).ToArray())); } if (ret.Any() == false) { var gb3 = gb.Where(a => a.count == 3 && a.key > uphand.result.compareValue).OrderBy(a => a.key); if (gb3.Any()) { ret.AddRange(gb3.Select(a => a.poker.Where((b, c) => c < 2).OrderByDescending(b => b).ToArray())); } } if (ret.Any() == false) { var gb4 = gb.Where(a => a.count == 4).OrderByDescending(a => a.key); if (gb4.Any()) { ret.AddRange(gb4.Select(a => a.poker.OrderByDescending(b => b).ToArray())); } } if (ret.Any() == false) { if (jokers.Length == 2) { ret.Add(jokers); } } return(ret); } if (uphand.result.type == HandPokerType.条) { var gb3 = gb.Where(a => a.count == 3 && a.key > uphand.result.compareValue).OrderBy(a => a.key); if (gb3.Any()) { ret.AddRange(gb3.Select(a => a.poker.OrderByDescending(b => b).ToArray())); } var gb4 = gb.Where(a => a.count == 4).OrderBy(a => a.key); if (gb4.Any()) { ret.AddRange(gb4.Select(a => a.poker.OrderByDescending(z => z).ToArray())); } if (jokers.Length == 2) { ret.Add(jokers); } return(ret); } if (uphand.result.type == HandPokerType.条带一个) { var gb3 = gb.Where(a => a.count == 3 && a.key > uphand.result.compareValue).OrderBy(a => a.key); if (gb3.Any()) { foreach (var g3 in gb3) { var gb1 = gb.Where(a => a.count == 1 && (jokers.Length == 2 && a.key != 16 && a.key != 17 || jokers.Length < 2)).OrderBy(a => a.key); //忽略双王 if (gb1.Any()) { ret.AddRange(gb1.Select(a => g3.poker.OrderByDescending(b => b).Concat(a.poker).ToArray())); } if (ret.Any() == false) { var gb2 = gb.Where(a => a.count == 2).OrderBy(a => a.key); if (gb2.Any()) { foreach (var g2 in gb2) { ret.AddRange(g2.poker.OrderBy(a => a).Select(a => g3.poker.OrderByDescending(b => b).Concat(new[] { a }).ToArray())); } } } if (ret.Any() == false) { var gb33 = gb.Where(a => a.count == 3 && a.key != g3.key).OrderBy(a => a.key); if (gb33.Any()) { foreach (var g33 in gb33) { ret.AddRange(g33.poker.OrderBy(a => a).Select(a => g3.poker.OrderByDescending(b => b).Concat(new[] { a }).ToArray())); } } } } } var gb4 = gb.Where(a => a.count == 4).OrderBy(a => a.key); if (gb4.Any()) { ret.AddRange(gb4.Select(a => a.poker.OrderByDescending(z => z).ToArray())); } if (jokers.Length == 2) { ret.Add(jokers); } return(ret); } if (uphand.result.type == HandPokerType.条带一对) { var gb3 = gb.Where(a => a.count == 3 && a.key > uphand.result.compareValue).OrderBy(a => a.key); if (gb3.Any()) { foreach (var g3 in gb3) { var gb2 = gb.Where(a => a.count == 2).OrderBy(a => a.key); if (gb2.Any()) { ret.AddRange(gb2.Select(a => g3.poker.OrderByDescending(b => b).Concat(a.poker.OrderByDescending(b => b)).ToArray())); } if (ret.Any() == false) { var gb33 = gb.Where(a => a.count == 3 && a.key != g3.key).OrderBy(a => a.key); if (gb33.Any()) { ret.AddRange(gb33.Select(a => g3.poker.OrderByDescending(b => b).Concat(a.poker.Where((b, c) => c < 2).OrderByDescending(b => b)).ToArray())); } } } } var gb4 = gb.Where(a => a.count == 4).OrderBy(a => a.key); if (gb4.Any()) { ret.AddRange(gb4.Select(a => a.poker.OrderByDescending(z => z).ToArray())); } if (jokers.Length == 2) { ret.Add(jokers); } return(ret); } if (uphand.result.type == HandPokerType.顺子) { var gbs = gb.Where(a => a.count < 4 && a.key <15 && a.key> uphand.result.compareValue - uphand.result.value.Length + 1).OrderBy(a => a.key).ToArray().AsSpan(); if (gbs.IsEmpty == false) { for (var a = 0; a < gbs.Length && gbs.Length - a >= uphand.result.value.Length; a++) { var ses = gbs.Slice(a, uphand.result.value.Length).ToArray(); if (Utils.IsSeries(ses.Select(b => b.key))) { ret.Add(ses.Select(b => b.poker.First()).ToArray()); } } } var gb4 = gb.Where(a => a.count == 4).OrderBy(a => a.key); if (gb4.Any()) { ret.AddRange(gb4.Select(a => a.poker.OrderByDescending(z => z).ToArray())); } if (jokers.Length == 2) { ret.Add(jokers); } return(ret); } if (uphand.result.type == HandPokerType.连对) { var gbs = gb.Where(a => a.count > 1 && a.count < 4 && a.key <15 && a.key> uphand.result.compareValue - uphand.result.value.Length / 2 + 1).OrderBy(a => a.key).ToArray().AsSpan(); if (gbs.IsEmpty == false) { for (var a = 0; a < gbs.Length && gbs.Length - a >= uphand.result.value.Length / 2; a++) { var ses = gbs.Slice(a, uphand.result.value.Length / 2).ToArray(); if (Utils.IsSeries(ses.Select(b => b.key))) { var tmp2 = new List <int>(); foreach (var se in ses) { tmp2.AddRange(se.poker.Where((b, c) => c < 2).OrderByDescending(b => b)); } ret.Add(tmp2.ToArray()); } } } var gb4 = gb.Where(a => a.count == 4).OrderBy(a => a.key); if (gb4.Any()) { ret.AddRange(gb4.Select(a => a.poker.OrderByDescending(z => z).ToArray())); } if (jokers.Length == 2) { ret.Add(jokers); } return(ret); } if (uphand.result.type == HandPokerType.飞机) { var gbs = gb.Where(a => a.count >= 3 && a.key <15 && a.key> uphand.result.compareValue - uphand.result.value.Length / 3 + 1).OrderBy(a => a.key).ToArray().AsSpan(); if (gbs.IsEmpty == false) { for (var a = 0; a < gbs.Length && gbs.Length - a >= uphand.result.value.Length / 3; a++) { var ses = gbs.Slice(a, uphand.result.value.Length / 3).ToArray(); if (Utils.IsSeries(ses.Select(b => b.key))) { var tmp3 = new List <int>(); foreach (var se in ses) { tmp3.AddRange(se.poker.Where((b, c) => c < 3).OrderByDescending(b => b)); } ret.Add(tmp3.ToArray()); } } } var gb4 = gb.Where(a => a.count == 4).OrderBy(a => a.key); if (gb4.Any()) { ret.AddRange(gb4.Select(a => a.poker.OrderByDescending(z => z).ToArray())); } if (jokers.Length == 2) { ret.Add(jokers); } return(ret); } if (uphand.result.type == HandPokerType.飞机带N个) { var gbs = gb.Where(a => a.count >= 3 && a.key <15 && a.key> uphand.result.compareValue - uphand.result.value.Length / 4 + 1).OrderBy(a => a.key).ToArray().AsSpan(); if (gbs.IsEmpty == false) { for (var a = 0; a < gbs.Length && gbs.Length - a >= uphand.result.value.Length / 4; a++) { var ses = gbs.Slice(a, uphand.result.value.Length / 4).ToArray(); if (Utils.IsSeries(ses.Select(b => b.key))) { var tmp3 = new List <int>(); foreach (var se in ses) { tmp3.AddRange(se.poker.Where((b, c) => c < 3).OrderByDescending(b => b)); } var gb11 = gb.Where(z => z.count == 1 && (jokers.Length == 2 && z.key != 16 && z.key != 17 || jokers.Length < 2)).OrderBy(z => z.key); //忽略双王 if (gb11.Any()) { ret.AddRange(gb11.Select(z => tmp3.Concat(z.poker).ToArray())); } if (ret.Any() == false) { var gb22 = gb.Where(z => z.count == 2).OrderBy(z => z.key); if (gb22.Any()) { foreach (var g22 in gb22) { ret.AddRange(g22.poker.OrderBy(z => z).Select(z => tmp3.Concat(new[] { a }).ToArray())); } } } if (ret.Any() == false) { var gb33 = gb.Where(z => z.count == 3 && ses.Where(y => y.key == z.key).Any() == false).OrderBy(z => z.key); if (gb33.Any()) { foreach (var g33 in gb33) { ret.AddRange(g33.poker.OrderBy(z => a).Select(z => tmp3.Concat(new[] { a }).ToArray())); } } } } } } var gb4 = gb.Where(a => a.count == 4).OrderBy(a => a.key); if (gb4.Any()) { ret.AddRange(gb4.Select(a => a.poker.OrderByDescending(z => z).ToArray())); } if (jokers.Length == 2) { ret.Add(jokers); } return(ret); } if (uphand.result.type == HandPokerType.飞机带N对) { var gbs = gb.Where(a => a.count >= 3 && a.key <15 && a.key> uphand.result.compareValue - uphand.result.value.Length / 5 + 1).OrderBy(a => a.key).ToArray().AsSpan(); if (gbs.IsEmpty == false) { for (var a = 0; a < gbs.Length && gbs.Length - a >= uphand.result.value.Length / 5; a++) { var ses = gbs.Slice(a, uphand.result.value.Length / 5).ToArray(); if (Utils.IsSeries(ses.Select(b => b.key))) { var tmp3 = new List <int>(); foreach (var se in ses) { tmp3.AddRange(se.poker.Where((b, c) => c < 3).OrderByDescending(b => b)); } var gb22 = gb.Where(z => z.count == 2).OrderBy(z => z.key); if (gb22.Any()) { ret.AddRange(gb22.Select(z => tmp3.Concat(z.poker.OrderByDescending(b => b)).ToArray())); } if (ret.Any() == false) { var gb33 = gb.Where(z => z.count == 3 && ses.Where(y => y.key == z.key).Any() == false).OrderBy(z => z.key); if (gb33.Any()) { ret.AddRange(gb33.Select(z => tmp3.Concat(z.poker.Where((b, c) => c < 2).OrderByDescending(b => b)).ToArray())); } } } } } var gb4 = gb.Where(a => a.count == 4).OrderBy(a => a.key); if (gb4.Any()) { ret.AddRange(gb4.Select(a => a.poker.OrderByDescending(z => z).ToArray())); } if (jokers.Length == 2) { ret.Add(jokers); } return(ret); } if (uphand.result.type == HandPokerType.炸带二个) { var gb4 = gb.Where(a => a.count == 4 && a.key > uphand.result.compareValue).OrderBy(a => a.key); if (gb4.Any()) { foreach (var g4 in gb4) { var gb11 = gb.Where(z => z.count == 1 && (jokers.Length == 2 && z.key != 16 && z.key != 17 || jokers.Length < 2)).OrderBy(z => z.key).ToArray(); //忽略双王 if (gb11.Length > 1) { for (var a = 0; a < gb11.Length; a++) { for (var b = a + 1; b < gb11.Length; b++) { ret.Add(g4.poker.OrderByDescending(z => z).Concat(gb11[a].poker).Concat(gb11[b].poker).ToArray()); } } } if (ret.Any() == false) { var gb22 = gb.Where(z => z.count == 2).OrderBy(z => z.key); if (gb22.Any()) { ret.AddRange(gb22.Select(y => g4.poker.OrderByDescending(z => z).Concat(y.poker.OrderByDescending(z => z)).ToArray())); } } } ret.AddRange(gb4.Select(a => a.poker.OrderByDescending(z => z).ToArray())); } if (jokers.Length == 2) { var gb11 = gb.Where(z => z.count == 1 && (jokers.Length == 2 && z.key != 16 && z.key != 17 || jokers.Length < 2)).OrderBy(z => z.key).ToArray(); //忽略双王 if (gb11.Length > 1) { for (var a = 0; a < gb11.Length; a++) { for (var b = a + 1; b < gb11.Length; b++) { ret.Add(jokers.Concat(gb11[a].poker).Concat(gb11[b].poker).ToArray()); } } } if (ret.Any() == false) { var gb22 = gb.Where(z => z.count == 2).OrderBy(z => z.key); if (gb22.Any()) { ret.AddRange(gb22.Select(y => jokers.Concat(y.poker.OrderByDescending(z => z)).ToArray())); } } ret.Add(jokers); } return(ret); } if (uphand.result.type == HandPokerType.炸带二对) { var gb4 = gb.Where(a => a.count == 4 && a.key > uphand.result.compareValue).OrderBy(a => a.key); if (gb4.Any()) { foreach (var g4 in gb4) { var gb22 = gb.Where(z => z.count == 2).OrderBy(z => z.key).ToArray(); if (gb22.Length > 1) { for (var a = 0; a < gb22.Length; a++) { for (var b = a + 1; b < gb22.Length; b++) { ret.Add(g4.poker.OrderByDescending(z => z).Concat(gb22[a].poker.OrderByDescending(z => z)).Concat(gb22[b].poker.OrderByDescending(z => z)).ToArray()); } } } } ret.AddRange(gb4.Select(a => a.poker.OrderByDescending(z => z).ToArray())); } if (jokers.Length == 2) { var gb22 = gb.Where(z => z.count == 2).OrderBy(z => z.key).ToArray(); if (gb22.Length > 1) { for (var a = 0; a < gb22.Length; a++) { for (var b = a + 1; b < gb22.Length; b++) { ret.Add(jokers.Concat(gb22[a].poker.OrderByDescending(z => z)).Concat(gb22[b].poker.OrderByDescending(z => z)).ToArray()); } } } ret.Add(jokers); } return(ret); } if (uphand.result.type == HandPokerType.四条炸) { var gb4 = gb.Where(a => a.count == 4 && a.key > uphand.result.compareValue).OrderBy(a => a.key); if (gb4.Any()) { ret.AddRange(gb4.Select(a => a.poker.OrderByDescending(z => z).ToArray())); } if (jokers.Length == 2) { ret.Add(jokers); } return(ret); } if (uphand.result.type == HandPokerType.王炸) { } return(ret); }