Files
hjha-server/GameFix/Common/Core/PokerLogic.cs
xiaoou e9616125ce feat: initial commit - HJHA game server full source
6 major server modules (PdkFriendServer/GlobalSever/ServerCore/GameModule/GameNetModule) +
game logic (GameFix/GameDAL/ServerData) +
network layer (NetWorkMessage) +
data layer (ObjectModel) +
utilities (MrWu/Core/Config/CloudAPI/dll) +
adapters (zyxAdapter/base)

.NET 8.0 C# solution, 16 projects, 958 source files
2026-07-07 12:02:15 +08:00

722 lines
25 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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; //次数
}
/// <summary>
/// 获取所有的单张
/// </summary>
/// <returns></returns>
public static List<T> GetDanZhang<T>(IPlayOutCardType1 outCard, T[] cards, bool chaiDan = false)
where T : ICardInfoType1
{
if (outCard.GameNum <= 0 || cards == null || cards.Length <= 0) return null;
Dictionary<byte, byte> dic = new Dictionary<byte, byte>();
List<T> result = new List<T>();
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;
}
/// <summary>
/// 获取连续的相同大小的张数
/// </summary>
/// <param name="outCard"></param>
/// <param name="cards">手里没有打下去的牌</param>
/// <param name="count">几张大小相同的个数</param>
/// <param name="shouPai">手里全部的牌</param>
/// <returns></returns>
public static List<List<T>> GetLianCount<T>(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<List<T>> result = new List<List<T>>();
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<T> temp = new List<T>();
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;
}
/// <summary>
/// 根据牌的绝对Id返回牌的详细信息
/// </summary>
/// <param name="wanshouPai">玩家手牌</param>
/// <param name="ids">牌的Id集合</param>
/// <returns></returns>
public static T[] GetCardByIds<T>(T[] wanshouPai, byte[] ids) where T : ICardInfoType1
{
if (ids == null || ids.Length <= 0) return null;
if (wanshouPai == null || wanshouPai.Length <= 0) return null;
List<T> result = new List<T>();
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();
}
/// <summary>
/// 获取飞机的连的个数,长度
/// </summary>
/// <param name="selectCards"></param>
/// <returns></returns>
public static int GetFeiJiCount<T>(T[] selectCards) where T : ICardInfoType1
{
if (selectCards == null || selectCards.Length < 6) return 0;
List<XY> list = new List<XY>();
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<int> fj = new List<int>();
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;
}
/// <summary>
/// 获取玩家手里几张相同的牌型
/// </summary>
/// <param name="outCard">玩家出的牌</param>
/// <param name="cards">玩家手里没有出下去的牌</param>
/// <param name="count">要获取相同大小的张数</param>
/// <param name="chai">是否拆牌 false不拆 true拆</param>
/// <param name="deng">是否获取跟出牌大小相等的牌 true是 false不是</param>
/// <returns></returns>
public static List<List<T>> GetCountCard<T>(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<List<T>> result = new List<List<T>>();
Dictionary<byte, byte> dic = new Dictionary<byte, byte>();
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;
}
/// <summary>
/// 是否是对子
/// 跑得快朋友房使用了
/// </summary>
/// <param name="selectCards"></param>
/// <returns></returns>
public static bool IsDuiZi<T>(T[] selectCards) where T : ICardInfoType1
{
if (selectCards == null || selectCards.Length != 2) return false;
return selectCards[0].GameNum == selectCards[1].GameNum;
}
/// <summary>
/// 获取顺子
/// </summary>
/// <param name="playCard"></param>
/// <returns></returns>
public static List<List<T>> GetShunZi<T>(T[] playCard) where T : ICardInfoType1
{
if (playCard == null || playCard.Length < 5) return null;
var cards = playCard.ToList();
List<List<T>> result = new List<List<T>>();
for (int i = 14; i > 6; i--)
{
List<T> shunzi = new List<T>();
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;
}
/// <summary>
/// 获取顺子
/// </summary>
/// <param name="outCard"></param>
/// <param name="playCard"></param>
/// <returns></returns>
public static List<List<T>> GetShunZi<T>(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<List<T>> result = new List<List<T>>();
for (int i = 14; i > outCard.GameNum; i--)
{
List<T> shunzi = new List<T>();
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;
}
/// <summary>
/// 是否是飞机 跑得快朋友房使用了
/// </summary>
/// <param name="selectCards">选中的牌</param>
/// <param name="isPaiBuGou">true不够 false 够</param>
/// <param name="canDaiPia">true可以带牌 false不可以带牌</param>
/// <param name="gameNum">返回飞机面值</param>
/// <returns></returns>
public static bool IsFeiJi<T>(T[] selectCards, bool isPaiBuGou, bool canDaiPia, out byte gameNum)
where T : ICardInfoType1
{
gameNum = 0;
if (selectCards == null || selectCards.Length < 6) return false;
List<XY> list = new List<XY>();
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<int> fj = new List<int>();
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;
}
/// <summary>
/// 判断是否是顺子,使用该函数前请先排序 跑得快朋友房使用了
/// </summary>
/// <param name="selectCards"></param>
/// <returns></returns>
public static bool IsShunzi<T>(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;
}
/// <summary>
/// 给牌排序 跑得快朋友房使用了
/// </summary>
/// <param name="cards"></param>
public static void SortCardByGameNum<T>(ref T[] cards) where T : ICardInfoType1
{
if (cards == null || cards.Length < 2) return;
Array.Sort(cards, (x, y) => y.GameNum.CompareTo(x.GameNum));
}
/// <summary>
/// 是否是连对,,使用该函数前请先排序 跑得快朋友房使用了
/// </summary>
/// <param name="selectCards"></param>
/// <returns></returns>
public static bool IsLianDui<T>(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;
}
/// <summary>
/// 获取玩家炸弹没有炸弹则out就是废王的牌
/// 需要先排序才可以运算
/// </summary>
/// <param name="playCards">玩家手牌</param>
/// <param name="cards">炸弹的牌 或者 废王的牌</param>
/// <returns>true有炸弹 false没有炸弹</returns>
public static bool GetPlayZhaDan<T>(T[] playCards, out List<T> cards) where T : ICardInfoType1
{
cards = new List<T>();
if (playCards == null || playCards.Length <= 0) return false;
List<T> result = new List<T>();
List<T> temp = new List<T>();
List<T> wang = new List<T>();
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;
}
/// <summary>
/// 获取玩家的炸弹
/// </summary>
/// <param name="playCards">玩家手牌</param>
/// <param name="cards">炸弹的牌</param>
/// <returns>true有炸弹 false没有炸弹</returns>
public static bool GetPlayZhaDans<T>(T[] playCards, out List<List<T>> cards) where T : ICardInfoType1
{
cards = new List<List<T>>();
if (playCards == null || playCards.Length <= 0) return false;
List<T> temp = new List<T>();
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;
}
/// <summary>
/// 是否是三带二 跑得快朋友房使用了
/// </summary>
/// <param name="selectCards">要判断的牌</param>
/// <param name="isPaiBuGou">玩家手牌是不是不够张数带牌true不够 false够</param>
/// <returns></returns>
#pragma warning disable CS1573 // 参数在 XML 注释中没有匹配的 param 标记(但其他参数有)
public static bool IsSanDaiEr<T>(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<byte, byte> dic = new Dictionary<byte, byte>();
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;
}
/// <summary>
/// 检测是否有相同的ID因为牌的ID是唯一的不会相同
/// </summary>
/// <param name="ids"></param>
/// <returns>true有 false没有</returns>
public static bool CheckSameId(byte[] ids)
{
if (ids == null || ids.Length <= 1) return false;
Dictionary<byte, int> did = new Dictionary<byte, int>();
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;
}
/// <summary>
/// 给牌排序,按照个数从大到小
/// </summary>
/// <param name="cards"></param>
/// <returns></returns>
public static T[] SortCardByCount<T>(T[] cards) where T : ICardInfoType1
{
if (cards == null || cards.Length <= 0) return null;
List<T> result = new List<T>();
Dictionary<int, List<T>> dics = new Dictionary<int, List<T>>();
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<T>();
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;
}
}
}