u3d联机斗地主(1):出牌规则

时间:2022-11-01 10:58:10


1出牌类型

enum CardType
{
None = 0,
One = 1,
Two = 2,
Three = 3,
ThreeWithOne = 4,
ThreeWithTwo = 5,
Four = 6,
FourWith2One = 7,
FourWith2Two = 8,
Rocket = 9,
}

每次出牌都是这9种类型:单张,对子,3连,3带1单,3带1对,4连,4带2个单,4带2个对,大小王

class CardRule
{
public CardType m_type;
public int m_val; //选取的最小的牌值
public int m_num = 1; //顺子的数量
}

然后根据出牌判断牌型,例如a玩家出牌:12345,牌型m_type=One,m_val=1,m_num=5。b玩家出牌:23456,牌型m_type=One,m_val=2,m_num=5。满足m_type一样,m_val更大,m_num一样,b玩家的牌就能吃掉a玩家。

例如a玩家出牌:3333444455667788,牌型m_type=FourWith2Two,m_val=3,m_num=2。

2判断一次出牌中每张的数量

static void mapCardCreate(List<int> list, ref Dictionary<int, int> dicCard)
{
for (int i = 0; i < list.Count; i++)
{
if (dicCard.ContainsKey(list[i]) == false)
{
dicCard.Add(list[i], 1);
}
else
{
dicCard[list[i]]++;
}
}
}

用一个字典保存住,键是牌的值,值是这张牌的数量。例如:444422,字典为dic[4]=4,dic [2]=2.

3只有连牌的判断

/// <summary>
/// 只有顺子处理,例如:34567,334455,333444,44445555
/// </summary>
/// <param name="list">出的牌,例如34567</param>
/// <param name="dicItem">每张牌数量的字典</param>
/// <param name="dealType">当前处理连牌类型:单连,双连,三连,4连</param>
/// <param name="val">牌型的最小值</param>
/// <param name="num">连牌数量</param>
/// <param name="cardType">牌型</param>
/// <returns></returns>
static bool shunOnlyDeal(List<int> list, Dictionary<int, int> dicItem, CardType dealType, ref int val,ref int num, ref CardType cardType)
{
int mod = 1;
int firstVal = 1;
switch (dealType)
{
case CardType.Two:
firstVal = 2;
mod = 2;
break;
case CardType.Three:
firstVal = 3;
mod = 3;
break;
case CardType.Four:
firstVal = 4;
mod = 4;
break;
}
if (list.Count % mod != 0)
{
return false;
}

int iNum = 0;
int minVal = GMaxVal;
List<int> listKey = new List<int>();
foreach (var item in dicItem)
{
if (item.Value != firstVal )
{
return false;
}
if (item.Value == firstVal)
{
iNum++;
listKey.Add(item.Key);
}
if ((item.Key < minVal) && item.Value == firstVal)
{
minVal = item.Key;
}
}

if (listKey.Count >= 2)
{
listKey.Sort((x, y) => x.CompareTo(y));
if (isInOrder(listKey) == false)
{
return false;
}
}
val = minVal;
num = iNum;
cardType = dealType;
return true;
}

例如:当出牌为334455时,双连牌时

1.出牌数量要为2的倍数

2.遍历记录每张牌数量的字典,找到最小牌值minVal =3,记录顺子数量iNum=3

3.得到每张单牌的list(3,4,5),如果它们是按顺序的,则是合法的牌型。

4连牌带牌的判断

/// <summary>
/// 连牌带牌处理,例如:3334,33344456,333345,33334455
/// </summary>
/// <param name="list">出的牌,从大到小排好顺序的</param>
/// <param name="dicItem">记录每张牌个数的字典</param>
/// <param name="dealType">处理的类型:3带1单,3带一对,4带2单,4带2对</param>
/// <param name="val">牌的最小值</param>
/// <param name="num">牌型数量</param>
/// <param name="cardType">牌型</param>
/// <returns></returns>
static bool shunWithDeal(List<int> list, Dictionary<int, int> dicItem, CardType dealType,ref int val, ref int num,ref CardType cardType)
{
int mod = 1;
int firstVal = 1;//顺子的牌要连几张,3带1,连3张
int withVal = 1;//顺子带的牌要带几张,3带1,带1张
int multiple = 1;//顺子与带牌的倍数关系,3带1,倍数为1张
switch (dealType)
{
case CardType.ThreeWithOne:
firstVal = 3;
withVal = 1;
mod = 4;
multiple = 1;
break;
case CardType.ThreeWithTwo:
firstVal = 3;
withVal = 2;
mod = 5;
multiple = 1;
break;
case CardType.FourWith2One:
firstVal = 4;
withVal = 1;
mod = 6;
multiple = 2;
break;
case CardType.FourWith2Two:
firstVal = 4;
withVal = 2;
mod = 8;
multiple = 2;
break;
}
if (list.Count%mod != 0)
{
return false;
}

int iNum = 0;//顺子的数量 例如:33334455,顺子数量为1
int iWithNum = 0;//带牌的数量 例如:33334455,带牌数量为2
int minVal = GMaxVal;
List<int> listKey = new List<int>();
foreach (var item in dicItem)
{
if (item.Value != firstVal && item.Value != withVal)
{
return false;
}
if (item.Value == withVal)
{
iWithNum++;//累积带牌数量
}
if (item.Value == firstVal)
{
iNum++;//累积顺子数量
listKey.Add(item.Key);
}
if ((item.Key < minVal) && item.Value == firstVal)
{
minVal = item.Key;
}
}
if (iWithNum != iNum * multiple)
{
return false;
}
if (listKey.Count >= 2)
{
listKey.Sort((x, y) => x.CompareTo(y));
if (isInOrder(listKey) == false)
{
return false;
}
}
val = minVal;
num = iNum;
cardType = dealType;
return true;
}

这里连牌带牌有4种:3带1单,3带1对,4带2单,4带2对。

u3d联机斗地主(1):出牌规则

例如出牌:3333444455667788,判断出牌型为4带2对,牌值为3,顺子数量为2,带牌数量为4,满足顺子与带牌的倍数:带牌数4=顺子数2*倍数2。

5运行效果

u3d联机斗地主(1):出牌规则

源码下载