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;
}
}
}