胡牌判断函数

来源:互联网 发布:小班亲子美工 编辑:程序博客网 时间:2024/05/16 01:12

胡牌判断函数

胡牌判断函数
[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
                {
                  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
                    {
                       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 TWanJia::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 TWanJia::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
#include
#include
#include
#include

#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为非负值,则必须处理掉一张牌或胡牌

protected:

       int HuPai(int * arr);
        int RemainPai(int * arr);

 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);
      
};
//---------------------------------------------------------------------------
extern PACKAGE Tfrm_mainwin *frm_mainwin;
//---------------------------------------------------------------------------
#endif

[/code]

原创粉丝点击