[参考]麻将和牌,吃牌,碰牌算法

自己写的上千行麻将和牌,吃牌,碰牌算法C++代码(原创)

//文件mian.cpp
#include "MJ.h"
#include "iostream.h"

int main()
{
CPlayMj Player1;
Pai * pTemp=Player1.GetPaiOwn();
Pai *pPaiRest;
pPaiRest=new Pai[14];
char control;
int iNum;
int i;
struct Pai TotalPai[34];//整副麻将牌
for(i=0;i<34;i++)
{
TotalPai[i].iNum=4;
TotalPai[i].iPaiNum=i;
}

Player1.SetPaiOwn(TotalPai);
Player1.SortPai(13,Player1.GetPaiOwn());
Player1.ShowOwn();

// cout<cout<<"Input:";
cin>>control;
while(control!='q')
{
switch(control)
{
case 'm':
cout<<"你摸的牌是:";
if(Player1.GetNewPai(TotalPai))
cout<<" ";
else
cout<<"没有牌了";
Player1.ShowNewPai();
break;
case 'h':
cout<<"你要交换的牌位:";
cin>>iNum;
Player1.ChangePai(iNum-1);
Player1.SortPai(13,Player1.GetPaiOwn());
Player1.ShowOwn();
break;
case 'f':

for(i=0;i<13;i++)
{
pPaiRest[i].iNum=pTemp[i].iNum;
pPaiRest[i].iPaiNum=pTemp[i].iPaiNum;
}
pPaiRest[13].iNum=Player1.GetNew()->iNum;
pPaiRest[13].iPaiNum=Player1.GetNew()->iPaiNum;
Player1.Hu(pPaiRest);
cout<break;
case 'c':
if(Player1.IsCi(Player1.GetPaiOwn()) && Player1.IsCi(Player1.GetPaiOwn())%2==1)
Player1.Ci(1,Player1.GetPaiOwn());
else
{
if(Player1.IsCi(Player1.GetPaiOwn()) && Player1.IsCi(Player1.GetPaiOwn())>=4)
Player1.Ci(4,Player1.GetPaiOwn());
}
Player1.SortPai(13,Player1.GetPaiOwn());
Player1.ShowOwn();

break;
case 's':
Player1.ShowOwn();
break;
case 'p':
if(Player1.IsPong(Player1.GetPaiOwn()))
Player1.Pong(Player1.GetPaiOwn());
Player1.SortPai(13,Player1.GetPaiOwn());
Player1.ShowOwn();

break;
case 'q':
break;
default:;
}
cout<<"Input:";
cin>>control;
}
delete []pPaiRest;
return 1;
}

//文件Mj.h


enum PaiHua{WANG,TONG,TIAO,ZI};


//牌样=牌花+牌号
struct Pai //单独的一个牌样,一个牌样有四张
{
int iPaiNum;// 牌号从0到33
int iNum;//剩余牌样的数目
};

struct ShowPai
{
int iPaiNum;
int iNum;
PaiHua Hua;
char *str;
};

class CPlayMj
{
public:

//主功能函数
bool IsHu(Pai *);
void Hu(Pai *);//胡牌
int IsCi(Pai* pPaiRest);
bool Ci( int iCi,Pai* pPaiRest);//吃牌
bool IsPong(Pai* pPaiRest);
bool Pong(Pai* pPaiRest);//碰牌
bool IsGang(Pai* pPaiRest);
bool Gang(Pai* pPaiRest);//杠牌
void SetPaiOwn(Pai *TotalPai);//初始化游戏者的13张牌
bool GetNewPai(Pai *TotalPal);//摸牌,返回1摸牌成功,返回0没有牌。
int ChangePai(int i);//进牌
void SortPai(int iNum,Pai *pPaiRest);//对牌按牌号排序,便于显示
void ShowOwn();//显示自己的牌
void ShowNewPai();//显示所摸的排
void Pair(Pai* pPaiRest);
bool GetMark();
void SetMark(bool);
void MyShow(Pai *);


//辅助功能函数
CPlayMj();
~CPlayMj();
Pai * PaiInPaiOwn(Pai *pPaiRest,int iPaiNum);//通过牌号判断牌是否在自己的牌中
bool NumInNum(int a,int b);
bool IsPair(Pai

* pPaiRest);
// bool FindCi(Pai* pPaiRest);
// bool FindPong(Pai* pPaiRest);
// bool FindPair(Pai* pPaiRest);
Pai* GetPaiOwn();
Pai *GetNew();


protected:

struct Pai *pPaiOwn;
struct Pai *pPaiNew;
ShowPai* pShowPai;
ShowPai *pShowNewPai;
int iPongNum;
int iGangNum;
int iPairNum;
int iCiNum;
bool iMark;
};


~~~~~~~~~以下与上面合用:

// Mj.cpp 注意iNum=1时,牌不能再用于吃 碰 胡 换牌
#include "mj.h"
#include "stdlib.h"
#include "time.h"
#include "iostream.h"

//辅助函数编写
CPlayMj::CPlayMj()
{
pPaiOwn=new Pai[13];
pPaiNew=new Pai;
pShowPai=new ShowPai[13];
pShowNewPai=new ShowPai;
iCiNum=0;
iPongNum=0;
iGangNum=0;
iPairNum=0;
iMark=0;
};

CPlayMj::~CPlayMj()
{
delete []pPaiOwn;
delete pPaiNew;
delete []pShowPai;
delete pShowNewPai;
};

Pai * CPlayMj::PaiInPaiOwn(Pai *pPaiRest,int iPaiNum)
{
for(int i=0;i<13;i++)
{
if(pPaiRest[i].iNum==1)//对未被吃,碰,杠
{
if(pPaiRest[i].iPaiNum==iPaiNum)
return pPaiRest+i;
}
}
return NULL;
}

bool CPlayMj::NumInNum(int a,int b)
{
if(a>26 || b>26)
return 0;
if(a>=0 && a<=8 && b>=0 && b<=8)
return 1;
if(a>=9 && a<=17 && b>=9 && b<=17)
return 1;
if(a>=18 && a<=26 && b>=18 && b<=26)
return 1;
return 0;
}

bool CPlayMj::IsPair(Pai* pPaiRest)
{
for(int i=0;i<13;i++)
{
if(pPaiRest[i].iPaiNum==pPaiNew->iPaiNum && pPaiRest[i].iNum==1)
return 1;
}
return 0;
}

void CPlayMj::Pair(Pai* pPaiRest)
{
for(int i=0;i<13;i++)
{
if(pPaiRest[i].iPaiNum==pPaiNew->iPaiNum && pPaiRest[i].iNum==1)
{
pPaiRest[i].iNum=0;
pPaiNew->iNum=0;
}
}
}
Pai* CPlayMj::GetPaiOwn()
{
return pPaiOwn;
}

Pai* CPlayMj::GetNew()
{
return pPaiNew;
}

bool CPlayMj::GetMark()
{
return iMark;
}

void CPlayMj::SetMark(bool i)
{
iMark=i;
}

void CPlayMj::MyShow(Pai *pTemp)
{
int iTemp;
ShowPai pShowPai[14];
for(int i=0;i<14;i++)
{
iTemp=pTemp[i].iPaiNum;
switch(iTemp/9)
{
case 0:pShowPai[i].Hua=WANG;//判断是那个牌花:万,条,铜
pShowPai[i].str="万";
pShowPai[i].iPaiNum=iTemp+1;//从1到9,下标转换为牌号
break;
case 1:pShowPai[i].Hua=TONG;
pShowPai[i].str="铜";
pShowPai[i].iPaiNum=iTemp-9+1;
break;
case 2:pShowPai[i].Hua=TIAO;
pShowPai[i].str="条";
pShowPai[i].iPaiNum=iTemp-18+1;
break;
default:
pShowPai[i].Hua=ZI;
switch(iTemp)
{
case 27:
pShowPai[i].str="东";break;
case 28:
pShowPai[i].str="南";break;
case 29:
pShowPai[i].str="西";break;
case 30:
pShowPai[i].str="北";break;
case 31:
pShowPai[i].str="中";break;
case 32:
pShowPai[i].str="发";break;
case 33:
pShowPai[i].str="白";break;
default:;
};
pShowPai[i].iPaiNum=iTemp;//字的只有7种,东南西北,中发白
};
pShowPai[i].iNum=pTemp[i].iNum;

if(pShowPai[i].iPaiNum>26)
cout<else
cout<}
}


//主函数编写

bool CPlayMj::

IsHu(Pai *pOwn)
{
return 0;
}
void CPlayMj::Hu(Pai *pOwn)
{
// char a;
int i;
int j=0;
int iTemp;
int iTag=0;

//
if(iPairNum+iGangNum+iPongNum+iCiNum>4)
{
if(iPairNum==7)
{
cout<<"七对子";
iMark=1;
}

if((iPongNum+iGangNum)==4 && (iPairNum==1))
{
cout<<"碰碰胡";
iMark=1;
}

if((iCiNum>=1) && ((iPongNum+iGangNum+iCiNum)==4) && (iPairNum==1))
{
cout<<"平胡";
iMark=1;
}

}
if(iMark==1)
return;

SortPai(14,pOwn);

// MyShow(pOwn);
// cin>>a;
while(pOwn[j].iNum!=1 && j<14)
j++;
if(j==14 || iMark==1)
return;

//假如情况是吃的
if( iMark==0
&&((pOwn[j].iPaiNum<=24 && pOwn[j].iPaiNum>=18)
||(pOwn[j].iPaiNum<=15 && pOwn[j].iPaiNum>=9)
||(pOwn[j].iPaiNum<=6 && pOwn[j].iPaiNum>=0) ) )
{
if(pOwn[j].iPaiNum+1==pOwn[j+1].iPaiNum)
{
for(i=j+2;i<14;i++)
{
if(pOwn[i].iPaiNum==pOwn[j].iPaiNum+2)
iTag=i;
}/////////////////等换牌
if(iTag!=0)
{//可以吃,执行吃的操作
pOwn[j].iNum=0;
pOwn[j+1].iNum=0;

iTemp=pOwn[j+2].iPaiNum;
pOwn[j+2].iPaiNum=pOwn[iTag].iPaiNum;
pOwn[iTag].iPaiNum=iTemp;
pOwn[j+2].iNum=0;
iCiNum++;//吃的次数加一次

Hu(pOwn);

iTemp=pOwn[j+2].iPaiNum;
pOwn[j+2].iPaiNum=pOwn[iTag].iPaiNum;
pOwn[iTag].iPaiNum=iTemp;
pOwn[j].iNum=1;
pOwn[j+1].iNum=1;
pOwn[j+2].iNum=1;
iCiNum--;
}
}
}
//假如情况是可以碰
if(iMark==0 && pOwn[j].iPaiNum==pOwn[j+1].iPaiNum)
{
for(i=j+2;i<14;i++)
{
if(pOwn[i].iPaiNum==pOwn[j].iPaiNum)
iTag=i;
}
if(iTag!=0)
{//可以碰,执行碰操作

pOwn[j].iNum=0;
pOwn[j+1].iNum=0;
iTemp=pOwn[j+2].iPaiNum;
pOwn[j+2].iPaiNum=pOwn[iTag].iPaiNum;
pOwn[iTag].iPaiNum=iTemp;
pOwn[j+2].iNum=0;
iPongNum++;//碰的次数加一次
Hu(pOwn);
iTemp=pOwn[j+2].iPaiNum;
pOwn[j+2].iPaiNum=pOwn[iTag].iPaiNum;
pOwn[iTag].iPaiNum=iTemp;
pOwn[j].iNum=1;
pOwn[j+1].iNum=1;
pOwn[j+2].iNum=1;
iPongNum--;
//有可能碰胡不了,对而可以胡,如55 567,555 67。
pOwn[j].iNum=0;
pOwn[j+1].iNum=0;
iPairNum++;
Hu(pOwn);
pOwn[j].iNum=1;
pOwn[j+1].iNum=1;
iPairNum--;

}
else
{//是对的情况
pOwn[j].iNum=0;
pOwn[j+1].iNum=0;
iPairNum++;
Hu(pOwn);
pOwn[j].iNum=1;
pOwn[j+1].iNum=1;
iPairNum--;
}

}
return ;
}


int CPlayMj::IsCi(Pai *pPaiRest)
{
int iCi=0;
int iTemp=pPaiNew->iPaiNum;
if(iTemp>26 && iTemp<0)
return 0;//不可以吃
if(PaiInPaiOwn(pPaiRest,iTemp-1) && PaiInPaiOwn(pPaiRest,iTemp-2)
&& NumInNum(iTemp,iTemp-1) && NumInNum(iTemp,iTemp-2))
{
iCi=iCi+1; //第1种吃法
}
if(PaiInPaiOwn(pPaiRest,iTemp-1) && PaiInPaiOwn(pPaiRest,iTemp+1)
&& NumInNum(iTemp,iTemp-1) && NumInNum(iTemp,iTemp+1))
{
iCi=iCi+2; //第2种吃法
}
if(PaiInPaiOwn(pPaiRest,iTemp+1) && PaiInPaiOwn(pPaiRest,iTemp+2)
&& NumInNum(iTemp,iTemp+1) && NumInNum(iTemp,iTemp+2))
{
iCi=iCi+4; //第3种吃法
}
return iCi;
}


bool CPlayMj::Ci(int iCi,Pai* pPaiRest)
{
Pai Temp;
Pai *pTemp;
int iTemp=pPaiNew->iPaiNum;
int iNum;
int iDrop;
iNum=(iCiNum+iGangNum+iPongNum)*3;
//下

面的三种情况就可以吃
if(iCi==1)
{
pTemp=PaiInPaiOwn(pPaiRest,iTemp-1);
pTemp->iNum=0;

Temp.iNum=pPaiOwn[iNum].iNum;
Temp.iPaiNum=pPaiOwn[iNum].iPaiNum;

pPaiOwn[iNum].iNum=pTemp->iNum;
pPaiOwn[iNum].iPaiNum=pTemp->iPaiNum;

pTemp->iNum=Temp.iNum;
pTemp->iPaiNum=Temp.iPaiNum;

/////////////////
pTemp=PaiInPaiOwn(pPaiRest,iTemp-2);
pTemp->iNum=0;

Temp.iNum=pPaiOwn[iNum+1].iNum;
Temp.iPaiNum=pPaiOwn[iNum+1].iPaiNum;

pPaiOwn[iNum+1].iNum=pTemp->iNum;
pPaiOwn[iNum+1].iPaiNum=pTemp->iPaiNum;

pTemp->iNum=Temp.iNum;
pTemp->iPaiNum=Temp.iPaiNum;

}
if(iCi==2)
{
pTemp=PaiInPaiOwn(pPaiRest,iTemp-1);
pTemp->iNum=0;

Temp.iNum=pPaiOwn[iNum].iNum;
Temp.iPaiNum=pPaiOwn[iNum].iPaiNum;

pPaiOwn[iNum].iNum=pTemp->iNum;
pPaiOwn[iNum].iPaiNum=pTemp->iPaiNum;

pTemp->iNum=Temp.iNum;
pTemp->iPaiNum=Temp.iPaiNum;

/////////////////
pTemp=PaiInPaiOwn(pPaiRest,iTemp+1);
pTemp->iNum=0;

Temp.iNum=pPaiOwn[iNum+1].iNum;
Temp.iPaiNum=pPaiOwn[iNum+1].iPaiNum;

pPaiOwn[iNum+1].iNum=pTemp->iNum;
pPaiOwn[iNum+1].iPaiNum=pTemp->iPaiNum;

pTemp->iNum=Temp.iNum;
pTemp->iPaiNum=Temp.iPaiNum;

}
if(iCi==4)
{
pTemp=PaiInPaiOwn(pPaiRest,iTemp+1);
pTemp->iNum=0;

Temp.iNum=pPaiOwn[iNum].iNum;
Temp.iPaiNum=pPaiOwn[iNum].iPaiNum;

pPaiOwn[iNum].iNum=pTemp->iNum;
pPaiOwn[iNum].iPaiNum=pTemp->iPaiNum;

pTemp->iNum=Temp.iNum;
pTemp->iPaiNum=Temp.iPaiNum;

/////////////////
pTemp=PaiInPaiOwn(pPaiRest,iTemp+2);
pTemp->iNum=0;

Temp.iNum=pPaiOwn[iNum+1].iNum;
Temp.iPaiNum=pPaiOwn[iNum+1].iPaiNum;

pPaiOwn[iNum+1].iNum=pTemp->iNum;
pPaiOwn[iNum+1].iPaiNum=pTemp->iPaiNum;

pTemp->iNum=Temp.iNum;
pTemp->iPaiNum=Temp.iPaiNum;

}
SortPai(13,GetPaiOwn());
ShowOwn();
pPaiNew->iNum=0;
cout<<"选择要去掉的牌:";
cin>>iDrop;
pPaiOwn[iDrop-1].iNum=pPaiOwn[iNum+2].iNum;
pPaiOwn[iDrop-1].iPaiNum=pPaiOwn[iNum+2].iPaiNum;
pPaiOwn[iNum+2].iNum=pPaiNew->iNum;
pPaiOwn[iNum+2].iPaiNum=pPaiNew->iPaiNum;


iCiNum++;
return 1;
}

bool CPlayMj::IsPong(Pai *pPaiRest)
{
int iTag=0;

//查询是否可以碰
for(int i=0;i<13;i++)
{
if(pPaiRest[i].iPaiNum==pPaiNew->iPaiNum && pPaiRest[i].iNum==1)
iTag++;
}
if(iTag>=2)
return 1;
else
return 0;
}
bool CPlayMj::Pong(Pai* pPaiRest)
{
int iTag=0;
int j=0,iDrop;
Pai Temp;
int iNum=0;
iNum=(iCiNum+iGangNum+iPongNum)*3;


//到达没有用的牌开始
while(pPaiRest[j].iNum!=1)
j++;

//把碰了的牌置0,不可以在用
for(int i=j;i<13;i++)
{
if(pPaiRest[i].iPaiNum==pPaiNew->iPaiNum && iTag!=2)
{
pPaiRest[i].iNum=0;
Temp.iNum=pPaiRest[iNum].iNum;
Temp.iPaiNum=pPaiRest[iNum].iPaiNum;

pPaiOwn[iNum].iNum=pPaiRest[i].iNum;
pPaiOwn[iNum].iPaiNum=pPaiRest[i].iPaiNum;

pPaiRest[i].iNum=Temp.iNum;
pPaiRest[i].iPaiNum=Temp.iPaiNum;
iNum++;
iTag++;
}

}
SortPai(13,GetPaiOwn());
ShowOwn();
pPaiNew->iNum=0;
cout<<"选择要去掉的牌:";
cin>>iDrop;
pPaiOwn[iDrop-1].iNum=pPaiOwn[iNum].iNum;
pPaiOwn[iDrop-1].iPaiNu

m=pPaiOwn[iNum].iPaiNum;
pPaiOwn[iNum].iNum=pPaiNew->iNum;
pPaiOwn[iNum].iPaiNum=pPaiNew->iPaiNum;
iPongNum++;
return 1;
}

void CPlayMj::SetPaiOwn(Pai* TotalPai)
{
int i=0;
int iPaiNum=0;
// struct PaiHua iPaiHua;
srand((unsigned)time(NULL));
while(i<13)
{
iPaiNum=rand()%34;
if(TotalPai[iPaiNum].iNum>0)
{
pPaiOwn[i].iPaiNum=iPaiNum;
pPaiOwn[i].iNum=1;//设置为未使用
TotalPai[iPaiNum].iNum--;
// cout<i++;
}

};
return ;

}


bool CPlayMj::GetNewPai(Pai *TotalPai)
{
int iTemp=0;
int iTimes=0;
int iTag=0;
srand((unsigned)time(NULL));
iTemp=rand()%34;
while(iTag!=1)
{

if(iTimes==33)//没有牌了,游戏结束
return 0;

if(TotalPai[iTemp].iNum==0)
{
iTemp++;
iTemp=iTemp%34;
iTimes++;
}
else
{
iTag=1;
pPaiNew->iNum=1;
pPaiNew->iPaiNum=iTemp;
(TotalPai+iTemp)->iNum--;
}
}
return 1;

}

int CPlayMj::ChangePai(int i)
{
Pai Temp;
if(pPaiOwn[i].iNum!=0)
{
Temp.iNum=pPaiOwn[i].iNum;
Temp.iPaiNum=pPaiOwn[i].iPaiNum;
pPaiOwn[i].iPaiNum=pPaiNew->iPaiNum;
pPaiOwn[i].iNum=pPaiNew->iNum;
return Temp.iPaiNum;
}
else
return 0;
}

bool CPlayMj::IsGang(Pai *pPaiRest)
{
int iTag=0;

//查询是否可以碰
for(int i=0;i<13;i++)
{
if(pPaiRest[i].iPaiNum==pPaiNew->iPaiNum && pPaiRest[i].iNum==1)
iTag++;
}
if(iTag==3)
return 1;
else
return 0;
}

bool CPlayMj::Gang(Pai* pPaiRest)
{

//把碰了的牌置0,不可以在用
for(int i=0;i<13;i++)
{
if(pPaiRest[i].iPaiNum==pPaiNew->iPaiNum && pPaiRest[i].iNum==1)
pPaiRest[i].iNum=0;

}
pPaiNew->iNum=0;
iGangNum++;
return 1;
}

void CPlayMj::SortPai(int iNum,Pai *pPaiRest)
{
Pai Temp;
int i=0,j=0,iTemp=0;
while(pPaiRest[iTemp].iNum!=1)
iTemp++;
for(j=iTemp;j{
for(i=iTemp;i{
if(pPaiRest[i].iPaiNum>pPaiRest[i+1].iPaiNum)
{
Temp=pPaiRest[i];
pPaiRest[i]=pPaiRest[i+1];
pPaiRest[i+1]=Temp;
}

}
}
}


//实现从0--33转换到牌花并显示
void CPlayMj::ShowOwn()
{
int iTemp;
for(int i=0;i<13;i++)
{
iTemp=pPaiOwn[i].iPaiNum;
switch(iTemp/9)
{
case 0:pShowPai[i].Hua=WANG;//判断是那个牌花:万,条,铜
pShowPai[i].str="万";
pShowPai[i].iPaiNum=iTemp+1;//从1到9,下标转换为牌号
break;
case 1:pShowPai[i].Hua=TONG;
pShowPai[i].str="铜";
pShowPai[i].iPaiNum=iTemp-9+1;
break;
case 2:pShowPai[i].Hua=TIAO;
pShowPai[i].str="条";
pShowPai[i].iPaiNum=iTemp-18+1;
break;
default:
pShowPai[i].Hua=ZI;
switch(iTemp)
{
case 27:
pShowPai[i].str="东";break;
case 28:
pShowPai[i].str="南";break;
case 29:
pShowPai[i].str="西";break;
case 30:
pShowPai[i].str="北";break;
case 31:
pShowPai[i].str="中";break;
case 32:
pShowPai[i].str="发";break;
case 33:
pShowPai[i].str="白";break;
default:;
};
pShowPai[i].iPaiNum=iTemp;//字的只有7种,东南西北,中发白
};
pShowPai[i].iNum=pPaiOwn[i].iNum;

if(pShowPai[i].iPaiNum>26)
cout<

].iNum<else
cout<}
}

void CPlayMj::ShowNewPai()
{
int iTemp;
iTemp=pPaiNew->iPaiNum;
switch(iTemp/9)
{
case 0:pShowNewPai->Hua=WANG;//判断是那个牌花:万,条,铜
pShowNewPai->str="万";
pShowNewPai->iPaiNum=iTemp+1;//从1到9,下标转换为牌号
break;
case 1:pShowNewPai->Hua=TONG;
pShowNewPai->str="铜";
pShowNewPai->iPaiNum=iTemp-9+1;
break;
case 2:pShowNewPai->Hua=TIAO;
pShowNewPai->str="条";
pShowNewPai->iPaiNum=iTemp-18+1;
break;
default:
pShowNewPai->Hua=ZI;
switch(iTemp)
{
case 27:
pShowNewPai->str="东";break;
case 28:
pShowNewPai->str="南";break;
case 29:
pShowNewPai->str="西";break;
case 30:
pShowNewPai->str="北";break;
case 31:
pShowNewPai->str="中";break;
case 32:
pShowNewPai->str="发";break;
case 33:
pShowNewPai->str="白";break;
default:;
};
pShowNewPai->iPaiNum=iTemp;//字的只有7种,东南西北,中发白
};

if(pShowNewPai->iPaiNum>26)
cout<str<else
cout<iPaiNum<str<}

===================
代码作者: ocheng

收集自: https://www.360docs.net/doc/2618457119.html,/bbs/showthread.asp?threadid=1476

相关文档
最新文档