胡牌判断函数
胡牌判断函数 [code]//----------------unt_mainwin.cpp--------------------------------------------------------- /*----------------------------------------------------------------------------------------- *该函数判断手牌有没有胡牌,手牌的数量一定为[2,5,8,11,14] *当手牌数量为14时,判断是否有特殊牌型的胡牌[十三么,七对,全不靠] *当不存在以上牌型时,用递归算法判断是否存在一般的胡牌牌型 * *作者:yutian(于恬) *E_main:yution@126.com * *作者声明:本代码为学习时编写的代码,大家可以随意转贴及编译修改 *但不得用于商业用途和赌博,作者保留一切权力 * *鸣谢:网友 shyworm(怕怕虫) E_mail:shyworm@sina.com * CSDN ChinaUnix */ //----------------------------------------------------------------------------------------------- int TWanJia::IsWin() { int i,dblpos,dblcount; if(this->PaiCount==13) //先处理特殊牌型,七对、十三么及全不靠 { if((this->PaiInHand[0]==this->PaiInHand[1])&(this->PaiInHand[2]==this->PaiInHand[3]) &(this->PaiInHand[4]==this->PaiInHand[5])&(this->PaiInHand[6]==this->PaiInHand[7]) &(this->PaiInHand[8]==this->PaiInHand[9])&(this->PaiInHand[10]==this->PaiInHand[11]) &(this->PaiInHand[12]==this->PaiInHand[13])) return SevenDbl; //七对胡了 dblcount=0; for(i=0;i<13;i++) //以下判断手牌中对子的数量及位置 { if(this->PaiInHand[i]==this->PaiInHand[i+1]) { dblcount++; }
if(dblcount>1) break; //如果手牌中含有两个对子(或一个刻子)以上,只能胡基本牌型 } if(dblcount==1) //有一个对子的十三张手牌,可能为十三么 { /*********************************************** 十三么牌型必须是么九牌和字牌组成的十四张牌,按牌的数值定义 手牌数组PaiInHand中,只要没有1~7,10~16,19~25这些值, 则可以断定,该数组为十三么 */ int IsThirteen=1; for(i=0;i<14;i++) { if(this->PaiInHand[i]>0&&this->PaiInHand[i]<8) { IsThirteen=0; break; } else if(this->PaiInHand[i]>9&&this->PaiInHand[i]<17) { IsThirteen=0; break; } else if(this->PaiInHand[i]>18&&this->PaiInHand[i]<26) { IsThirteen=0; break; } } if(IsThirteen) return ThirteenSmall; } //end of 十三么 if(dblcount==0)//没有对子,可能是全不靠 { /*------------------------------------------- 十三不靠牌型为万筒条三个花色的147,258,369加上字牌的七张牌共16张 的任意十四张组成的胡牌,147,258,369的花色可以为任意花色,但不能有两副 出现相同的序数,如一万,四万,一条,四条是不能组成胡牌的。 判定的算法是: 先确定所以序数牌(不是字牌)的个数; 如果序数牌个数大于9,则返回错误; 如果有吃牌的序列(存在两张牌可以吃掉另外一张牌),返回错误; 对于所有的序数牌,自第一个开始,分别与其后的所有牌值mod9得 到的值比较,如果存在相等,返回错误。 如果上面判断都通过,则为十三不靠 */ int NoWordPos=14; for(i=13;i>=0;i--) { if(this->PaiInHand[i]<=26) { NoWordPos=i; break; } } if(NoWordPos<=8) //如果非字牌有9个以上,肯定不能胡全不靠 { int IsThirteenSingle=1; for(i=0;i<NoWordPos;i++) { if((this->PaiInHand[i+1]<=(this->PaiInHand[i]+2))&(this->PaiInHand[i]%9==this->PaiInHand[i+1]%9)) { IsThirteenSingle=0; break; } } if(IsThirteenSingle) { for(i=0;i<NoWordPos&IsThirteenSingle;i++) { for(int j=0;j<=NoWordPos;j++) { if(this->PaiInHand[i]==this->PaiInHand[j]%9) { IsThirteenSingle=0; break; } } } } if(IsThirteenSingle) return ThirteenSingle; } } //end of 不靠 } int TempPai[33]; for(i=0;i<34;i++) TempPai=0; for(i=0;i<14;i++) { TempPai[this->PaiInHand[i]]++; } if(HuPai(TempPai)) return GenaralWin; return 0; } //----------------------------------------------------------------------------------------------------------------- int Tfrm_mainwin::HuPai(int arr) { /* 以下代码参考了网友 shyworm(怕怕虫) E_mail:shyworm@sina.com 在csdn论坛发表的算法及源码,在此感谢 原来的算法中要对杠牌进行处理,但我设计的数据结构中,不需要对他们进行判断了, 故略去了一段代码 */ static int Jiang=0; // 将牌标志,即牌型“三三三三二”中的“二” if(!RemainPai(arr)) return 1; // 递归退出条件:如果没有剩牌,则和牌返回。 for(int i=1;!arr[i]&i<34;i++); // 找到有牌的地方,i就是当前牌, arr[i]是个数 // 3张组合(刻子) if(arr[i]>=3) // 如果当前牌不少于3张 { arr[i]-=3; // 减去3张牌 if(HuPai(arr)) return 1; // 如果剩余的牌组合成功,和牌 arr[i]+=3; // 取消3张组合 } // 2张组合(将牌) if(!Jiang&arr[i]>=2) // 如果之前没有将牌,且当前牌不少于2张 { Jiang=1; // 设置将牌标志 arr[i]-=2; // 减去2张牌 if(HuPai(arr)) return 1; // 如果剩余的牌组合成功,和牌 arr[i]+=2; // 取消2张组合 Jiang=0; // 清除将牌标志 } if(i>26) return 0; // “东南西北中发白”没有顺牌组合,不和 // 顺牌组合,注意是从前往后组合! if(i%9!=7&i%9!=8&arr[i+1]&arr[i+2])// 排除数值为8和9的牌且如果后面有连续两张牌 { arr[i]--; arr[i+1]--; arr[i+2]--; // 各牌数减1 if(HuPai(arr)) return 1; // 如果剩余的牌组合成功,和牌 arr[i]++; arr[i+1]++; arr[i+2]++; // 恢复各牌数 } // 无法全部组合,不和! return 0; } //---------------------------------------------------------------------------- // 检查剩余牌数 int Tfrm_mainwin::RemainPai(int arr) { int sum=0; for(int i=0;i<34;i++) sum+=arr[i]; return sum; } //----------------------------------------------------------------------------
[/code] 头文件 [code] //-------------------玩家类及窗体的头文件(修改中)---------------------------------------- #ifndef unt_mainwinH #define unt_mainwinH //--------------------------------------------------------------------------- #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include <Buttons.hpp> #define SevenDbl 7 //七对 #define ThirteenSmall 13 //十三么 #define ThirteenSingle 14 //十三不靠 #define GenaralWin 15 //一般胡牌 //============================================ // 0 1 2 3 4 5 6 7 8 //============================================ //一万 二万 三万 四万 五万 六万 七万 八万 九万 //============================================ // 9 10 11 12 13 14 15 16 17 //============================================ //一条 二条 三条 四条 五条 六条 七条 八条 九条 //============================================ //18 19 20 21 22 23 24 25 26 //============================================ //一筒 二筒 三筒 四筒 五筒 六筒 七筒 八筒 九筒 //============================================ //27 28 29 30 31 32 33 34 35 //============================================ //东风 南风 西风 北风 红中 发财 白板 花1 花2 //============================================ //--------------------------------------------------------------------------- struct SChiPai //吃牌的结构体,吃的牌为顺子,故记录首尾两张牌 { int MinPai; //麻将牌值,吃牌中最小的牌 int MaxPai; //麻将牌值,吃牌中最大的牌 }; //--------------------------------------------------------------------------- struct SGangPai //杠牌的结构体 { int Pai; //麻将牌值,取值范围为[0..33] int MingAn;//数值为0或1,1代表为暗杠,0代表明杠 }; //--------------------------------------------------------------------------- class TWanJia { //__published: private: AnsiString PlayerID; int FenShu; //玩家的分数,要和数据库保持一致 int MenFeng; //玩家的门风 SGangPai Gangpai[3]; //玩家手中杠的牌 SChiPai ChiPai[3]; //玩家手中吃的牌 int PengPai[3]; //玩家手中的碰牌 int HuaPai; //花牌的数量,算番时要用 int PaiInHand[13]; //玩家的手牌,除掉吃碰杠牌后手中的牌 //即其他玩家看不到的牌,最多为十四张 //其中,PaiInHand[13]在处理完成后,被赋值为-1 int PaiCount; //手牌的数量,取值为1,4,7,10,13 int NewPai; //新摸到或别人打的牌,在处理完成后,被赋值为-1 //如果NewPai为非负值,则必须处理掉一张牌或胡牌 public: TWanJia(AnsiString PlayID,int fenzhi); int SetMenFeng(int menfeng); int SetFenShu(int fenshu); int SetGangPai(int pai,int mingan); int SetChiPai(int min,int max); int SetPengPai(int pengpai); int SetPaiInHand(int * paiarr); int SetPaiCount(int count); int GetMenFeng(); int GetFenShu(); SGangPai * GetGangPai(); int * GetPengPai(); SChiPai * GetChiPai(); int * GetPaiInHand(); int GetPaiCount(); int Buhua(); int ChiPaiWithTwoPai(int min,int max); int PengPaiWithOneDbl(int pai); int IsWin(); int SendThePaiToServer(); int RequireOnePai(); }; //--------------------------------------------------------------------------- class TMJZhuo { //__published: private: int QuanFen,Header,Tail; int PaiQiang[143]; TWanJia Players[3]; public: }; //---------------------------------------------------------------------------- class Tfrm_mainwin : public TForm { __published: // IDE-managed Components TEdit *edt_paiInHand1; TLabel *Label1; TEdit *edt_GangPai1; TLabel *Label2; TLabel *Label3; TLabel *Label4; TEdit *edt_ChiPai11; TEdit *edt_ChiPai12; TEdit *edt_ChiPai21; TEdit *edt_ChiPai22; TEdit *edt_ChiPai31; TEdit *edt_ChiPai32; TEdit *edt_ChiPai41; TEdit *edt_ChiPai42; TEdit *edt_GangPai2; TEdit *edt_GangPai3; TEdit *edt_GangPai4; TEdit *edt_GangPai11; TEdit *edt_GangPai22; TEdit *edt_GangPai33; TEdit *edt_GangPai44; TEdit *edt_PengPai1; TEdit *edt_PengPai2; TEdit *edt_PengPai3; TEdit *edt_PengPai4; TEdit *edt_paiInHand2; TEdit *edt_paiInHand3; TEdit *edt_paiInHand4; TEdit *edt_paiInHand5; TEdit *edt_paiInHand6; TEdit *edt_paiInHand7; TEdit *edt_paiInHand8; TEdit *edt_paiInHand9; TEdit *edt_paiInHand10; TEdit *edt_paiInHand11; TEdit *edt_paiInHand12; TEdit *edt_paiInHand13; TEdit *edt_paiInHand14; TBitBtn *btn_IsWin; void __fastcall FormClose(TObject *Sender, TCloseAction &Action); void __fastcall btn_IsWinClick(TObject *Sender); void __fastcall FormCreate(TObject *Sender); private: // User declarations TWanJia * Player; public: // User declarations void SendDataToWanJia(); void DispWanJiaData(); __fastcall Tfrm_mainwin(TComponent* Owner); int HuPai(int arr); int RemainPai(int arr); }; //--------------------------------------------------------------------------- extern PACKAGE Tfrm_mainwin *frm_mainwin; //--------------------------------------------------------------------------- #endif [/code] 敬请斧正,谢谢 |