http://blog.csdn.net/aojiancc2/article/details/17166305五
斗地主的出牌规则不过有两点
1:自己出的牌是否符合规则
2:牌能否大过上家
所以我们需要建立一个牌的类型枚举,如果在该枚举中才允许出牌,每个类型需要对应一个tag用于标记该类型对应最大的牌
这样我们和上家去比较就非常方便了,比如牌的类型是顺子那么tag应该标记顺子中最大的,
如果是飞机应该标记三同中最大的
我们来分析一下斗地主需要的对象:玩家,牌
这里分析一下牌的对象
属性:
1:牌的类型
2:tag标记该类型牌最大的参数
3:出的牌
4:用户手中的牌
5:底牌
方法:
1:IsThan是否大过上家
2:Put出牌
3:Deal发牌
4:GetPokerType给牌归下类以便好判断牌的类型与找到标记
先建立枚举(这里可以允许连续炸弹类型):
public enum PokerGroupType : int
{
单子 = 1,//1张牌
对子 = 2,//2张牌
双王 = 3,
三不带 = 4,//3张牌
炸弹 = 5,//4张牌
三带一 = 6,
五张顺子 = 7,//5张牌
三带一对 = 8,
六张顺子 = 9,//6张牌
三连对 = 10,
四带二 = 11,
二飞机不带 = 12,
七张顺子 = 13,
四连对 = 14,//8张牌
八张顺子 = 15,
二飞机带2单 = 16,
四带2对 = 17,
九张顺子 = 18,//9张牌
三飞机不带 = 19,
五连对 = 20,//10张牌
十张顺子 = 21,
飞机带2对 = 22,
十一张顺子 = 23,
十二张顺子 = 24,//12张牌
四飞机不带 = 25,
三飞机带3张 = 26,
六连对 = 27,
两个4带2 = 28,
七连对 = 29,//14张牌
五飞机不带 = 30,//15张牌
三飞机带三对 = 31,
八连对 = 32,//16张牌
四连飞机带4单 = 33,
两个4带两对 = 34,
九连对 = 35,//18张牌
六连飞机不带 = 36,
三个四个二 = 37,
十连对 = 38,//20张牌
四飞机带4对 = 39,
五飞机带5单 = 40
}
为了更好的判断牌的类型我们用一个方法给生成的牌归下类
public int GetPokerType(int _pokertype)
{
if (_pokertype <= 3 && _pokertype >= 0) //0-3都是3
return 3;
if (_pokertype <= 7 && _pokertype >= 4) //4-7都是4
return 4;
if (_pokertype <= 11 && _pokertype >= 8)
return 5;
if (_pokertype <= 15 && _pokertype >= 12)
return 6;
if (_pokertype <= 19 && _pokertype >= 16)
return 7;
if (_pokertype <= 23 && _pokertype >= 20)
return 8;
if (_pokertype <= 27 && _pokertype >= 24)
return 9;
if (_pokertype <= 31 && _pokertype >= 28)
return 10;
if (_pokertype <= 35 && _pokertype >= 32)
return 11;
if (_pokertype <= 39 && _pokertype >= 36)
return 12;
if (_pokertype <= 43 && _pokertype >= 40)
return 13;
if (_pokertype <= 47 && _pokertype >= 44)
return 14;
if (_pokertype <= 51 && _pokertype >= 48) //都是2
return 15;
if (_pokertype == 52) //小王
return 16;
if (_pokertype == 53)//大王
return 17;
return -1;
}
出牌规则类:验证自己是否能出牌与标记相应类型tag
public class PokerRule
{
public bool IsRule(Poker_ddz _pokers) //出牌是否符合规则与类型
{
_pokers.putpokers.Sort();
int num = _pokers.putpokers.Count;
bool res = false;
switch (num)
{
case 1:
_pokers.pgt = PokerGroupType.单子;
_pokers.tagnum = _pokers.putpokers[0];
res = true;
break;
case 2:
if (Same(_pokers))
{
_pokers.pgt = PokerGroupType.对子;
res = true;
}
else if (_pokers.putpokers[0] == 16 && _pokers.putpokers[1] == 17)
{
_pokers.pgt = PokerGroupType.双王;
res = true;
}
break;
case 3:
if (Same(_pokers))
{
_pokers.pgt = PokerGroupType.三不带;
res = true;
}
break;
case 4:
if (Same(_pokers))
{
_pokers.pgt = PokerGroupType.炸弹;//先判断炸弹别把炸弹理解成3个带一个了
res = true;
}
else if (IsPlaneWithOne(_pokers))
{
_pokers.pgt = PokerGroupType.三带一;
res = true;
}
break;
case 5:
if (IsStraight(_pokers))
{
_pokers.pgt = PokerGroupType.五张顺子;
res = true;
}
else if (IsPlaneWithTwo(_pokers))
{
_pokers.pgt = PokerGroupType.三带一对;
res = true;
}
break;
case 6:
if (IsStraight(_pokers))
{
_pokers.pgt = PokerGroupType.六张顺子;
res = true;
}
else if (IsFourWithTwoSimple(_pokers))
{
_pokers.pgt = PokerGroupType.四带二;
res = true;
}
else if (IsStraightPair(_pokers))
{
_pokers.pgt = PokerGroupType.三连对;
res = true;
}
else if (IsPlaneNoWith(_pokers))
{
_pokers.pgt = PokerGroupType.二飞机不带;
res = true;
}
break;
case 7:
if (IsStraight(_pokers))
{
_pokers.pgt = PokerGroupType.七张顺子;
res = true;
}
break;
case 8:
if (IsStraight(_pokers))
{
_pokers.pgt = PokerGroupType.八张顺子;
res = true;
}
else if (IsStraightPair(_pokers))
{
_pokers.pgt = PokerGroupType.四连对;
res = true;
}
else if (IsPlaneWithOne(_pokers))
{
_pokers.pgt = PokerGroupType.二飞机带2单;
res = true;
}
else if (IsFourWithTwoPair(_pokers))
{
_pokers.pgt = PokerGroupType.四带2对;
res = true;
}
break;
case 9:
if (IsStraight(_pokers))
{
_pokers.pgt = PokerGroupType.九张顺子;
res = true;
}
else if (IsPlaneNoWith(_pokers))
{
_pokers.pgt = PokerGroupType.三飞机不带;
res = true;
}
break;
case 10:
if (IsStraight(_pokers))
{
_pokers.pgt = PokerGroupType.十张顺子;
res = true;
}
else if (IsStraightPair(_pokers))
{
_pokers.pgt = PokerGroupType.五连对;
res = true;
}
else if (IsPlaneWithTwo(_pokers))
{
_pokers.pgt = PokerGroupType.飞机带2对;
res = true;
}
break;
case 11:
if (IsStraight(_pokers))
{
_pokers.pgt = PokerGroupType.十一张顺子;
res = true;
}
break;
case 12:
if (IsStraight(_pokers))
{
_pokers.pgt = PokerGroupType.十二张顺子;
res = true;
}
else if (IsStraightPair(_pokers))
{
_pokers.pgt = PokerGroupType.六连对;
res = true;
}
else if (IsPlaneWithOne(_pokers))
{
_pokers.pgt = PokerGroupType.三飞机带3张;
res = true;
}
else if (IsPlaneNoWith(_pokers))
{
_pokers.pgt = PokerGroupType.四飞机不带;
res = true;
}
else if (IsFourWithTwoSimple(_pokers))
{
_pokers.pgt = PokerGroupType.两个4带2;
res = true;
}
break;
case 14:
if (IsStraightPair(_pokers))
{
_pokers.pgt = PokerGroupType.七连对;
res = true;
}
break;
case 15:
if (IsPlaneNoWith(_pokers))
{
_pokers.pgt = PokerGroupType.五飞机不带;
res = true;
}
else if (IsPlaneWithTwo(_pokers))
{
_pokers.pgt = PokerGroupType.三飞机带三对;
res = true;
}
break;
case 16:
if (IsPlaneWithOne(_pokers))
{
_pokers.pgt = PokerGroupType.四连飞机带4单;
res = true;
}
else if (IsStraightPair(_pokers))
{
_pokers.pgt = PokerGroupType.八连对;
res = true;
}
else if (IsFourWithTwoPair(_pokers))
{
_pokers.pgt = PokerGroupType.八连对;
res = true;
}
break;
case 18:
if (IsStraightPair(_pokers))
{
_pokers.pgt = PokerGroupType.九连对;
res = true;
}
else if (IsPlaneNoWith(_pokers))
{
_pokers.pgt = PokerGroupType.六连飞机不带;
res = true;
}
else if (IsFourWithTwoSimple(_pokers))
{
_pokers.pgt = PokerGroupType.三个四个二;
res = true;
}
break;
case 20:
if (IsStraightPair(_pokers))
{
_pokers.pgt = PokerGroupType.十连对;
res = true;
}
else if (IsPlaneWithTwo(_pokers))
{
_pokers.pgt = PokerGroupType.四飞机带4对;
res = true;
}
else if (IsPlaneWithOne(_pokers))
{
_pokers.pgt = PokerGroupType.五飞机带5单;
res = true;
}
break;
default: return false;
}
return res;
}
public bool Same(Poker_ddz _pokers)//是否手中的所有牌相同
{
for (int i = 0; i < _pokers.putpokers.Count - 1; i++)
{
if (_pokers.putpokers[0] != _pokers.putpokers[i + 1])
return false;
}
_pokers.tagnum = _pokers.putpokers[_pokers.putpokers.Count - 1];
return true;
}
public bool IsHaveFourStaright(Poker_ddz _pokers, List<int> foursame, int onesame) //验证是否有4个的,与4个的是否连续
{
if (foursame.Count == 1 && foursame.Count * 2 == onesame)//验证是否有4个的,且一个4个的能带两个单张,普通4带2
{
_pokers.tagnum = foursame[foursame.Count - 1];
return true;
}
else if (foursame.Count > 1 && foursame.Count * 2 == onesame && IsStraight(new Poker_ddz { putpokers = foursame }))//滚筒,4个的是否连续
{
_pokers.tagnum = foursame[foursame.Count - 1];
return true;
}
else
return false;
}
public bool IsFourWithTwoSimple(Poker_ddz _pokers) //是否是4带2单,与滚筒比如333344445678两个4个的带4张
{
List<int> foursame = new List<int>();//4张相同的
int onesame = 0;//所带的单个数
for (int i = 0; i < _pokers.putpokers.Count; i++)
{
int tag = _pokers.putpokers[i];
int count = _pokers.putpokers.Where(a => a == tag).Count();
if (count == 4)
{
foursame.Add(tag);
i = i + 3;
}
else
onesame++;
}
return IsHaveFourStaright(_pokers, foursame, onesame);
}
public bool IsFourWithTwoPair(Poker_ddz _pokers) //是否是4带2对,与滚筒比如333344445566两个4个的带4对
{
List<int> foursame = new List<int>();//4张相同的
int onesame = 0;//所带的对子个数
for (int i = 0; i < _pokers.putpokers.Count; i++)
{
int tag = _pokers.putpokers[i];
int count = _pokers.putpokers.Where(a => a == tag).Count();
if (count == 4)
{
foursame.Add(tag);
i = i + 3;
}
else if (count == 2)
{
i++;
onesame++;
}
else //要带两个除了4个的就必须是对子,如果不是4个的也不是对子那么必然不是4带两对
return false;
}
return IsHaveFourStaright(_pokers, foursame, onesame);
}
public bool IsStraight(Poker_ddz _pokers)//是否为顺子
{
int num = _pokers.putpokers.Where(a => a == 16 || a == 17 || a == 15).Count();//不能包涵王与2
if (num > 0)
return false;
for (int i = 0; i < _pokers.putpokers.Count - 1; i++)
{
if (_pokers.putpokers[i] + 1 != _pokers.putpokers[i + 1])
return false;
}
_pokers.tagnum = _pokers.putpokers[_pokers.putpokers.Count - 1];
return true;
}
public bool IsStraightPair(Poker_ddz _pokers)//是否为联连对
{
int num = _pokers.putpokers.Where(a => a == 16 || a == 17 || a == 15).Count();//不能包涵王与2
if (num > 0)
return false;
for (int i = 0; i < _pokers.putpokers.Count - 2; i++)
{
if (_pokers.putpokers[i] != _pokers.putpokers[i + 1])//相连两个相等
return false;
if (_pokers.putpokers[i] + 1 != _pokers.putpokers[i + 2])//对子之间必须要相隔1
return false;
i = i + 1;//两两比较就行了
}
_pokers.tagnum = _pokers.putpokers[_pokers.putpokers.Count - 1];
return true;
}
public bool IsHavePlaneStaright(List<int> _threesame, List<int> withsame) //验证不否有3个的,与3个的是否连续即是否是飞机
{
if (_threesame.Count < 1)//没有三张相同的
return false;
if (_threesame.Count != 1)//等于1是普通三带一不需要验证是否连续
{
if (!IsStraight(new Poker_ddz { putpokers = _threesame })) //检查相同的是否为连续
return false;
}
if (_threesame.Count != withsame.Count)//验证是否带牌得合理,一个三张牌只能带一张牌或一对牌,所以应该是1比1
return false;
return true;
}
public void ToPlaneTidy(Poker_ddz _pokers, List<int> threesame, List<int> twosame, int _type) //重新理下牌,因为出的飞机可能不是我们想要看到的那样比如3332244455整理成3334442255
{
List<int> pokers = new List<int>();
for (int i = 0; i < threesame.Count; i++)
{
pokers.Add(threesame[0]);
pokers.Add(threesame[0]);
pokers.Add(threesame[0]);
}
for (int j = 0; j < twosame.Count; j++)
{
if (_type == 2)//带1对,就要多添加一次因为他是对子嘛
pokers.Add(twosame[j]);
pokers.Add(twosame[j]);
}
_pokers.putpokers = pokers;
}
public bool IsPlaneNoWith(Poker_ddz _pokers)//是否是飞机不带
{
List<int> recrod = new List<int>();//记录是那几个牌有三张,关键是看是否是连续,不然不能称之为飞机
for (int i = 0; i < _pokers.putpokers.Count; i++)
{
int tag = _pokers.putpokers[i];
int count = _pokers.putpokers.Where(a => a == tag).Count();
if (count == 3) //前三个相等直接比较跳过这三个
{
recrod.Add(tag);
i = i + 2;//本身还要加个一
}
else //三不带必须要每个都是三个
return false;
}
if (recrod.Count < 1)//没有三张相同的
return false;
if (!IsStraight(new Poker_ddz { pokers = recrod })) //检查相同的是否为连续
return false;
_pokers.tagnum = _pokers.putpokers[_pokers.putpokers.Count - 1];
return true;
}
public bool IsPlaneWithOne(Poker_ddz _pokers)//是否是飞机带1
{
List<int> threesame = new List<int>();//记录是那几个牌有三张
List<int> twosame = new List<int>();//记录是单个的牌
for (int i = 0; i < _pokers.putpokers.Count; i++)
{
int tag = _pokers.putpokers[i];
int count = _pokers.putpokers.Where(a => a == tag).Count();
if (count == 3) //前三个相等直接比较跳过这三个
{
threesame.Add(tag);
i = i + 2;
}
else
twosame.Add(tag);
}
if (!IsHavePlaneStaright(threesame, twosame)) //检查相同的是否为连续
return false;
_pokers.tagnum = threesame[threesame.Count - 1];
ToPlaneTidy(_pokers, threesame, twosame, 1);
return true;
}
public bool IsPlaneWithTwo(Poker_ddz _pokers)//是否是飞机带对
{
List<int> threesame = new List<int>();//记录是那几个牌有三张
List<int> twosame = new List<int>();//记录是对子的牌
for (int i = 0; i < _pokers.putpokers.Count; i++)
{
int tag = _pokers.putpokers[i];
int count = _pokers.putpokers.Where(a => a == tag).Count();
if (count == 3) //前三个相等直接比较跳过这三个
{
threesame.Add(tag);
i = i + 2;
}
else if (count == 2)
{
twosame.Add(tag);
i = i + 1;
}
else //三带一对不可能有单张的存在
return false;
}
if (!IsHavePlaneStaright(threesame, twosame)) //检查相同的是否为连续
return false;
_pokers.tagnum = threesame[threesame.Count - 1];//记录最大的一张牌
ToPlaneTidy(_pokers, threesame, twosame, 2);
return true;
}
}