/* *
*这是一个控制台下的麻将游戏 *
*/
#include<iostream.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#include<process.h>
//#include<windows.h>
//#include<conio.h>
template<class T>void swap(T & x,T & y){T temp=x;x=y;y=temp;}
template<class T> T max(T x,T y){ return (((x)>(y))?(x):(y));}
#define TOTALCARDS 136
#define CARDKINDS 34 /*所有的牌的数目 东西南北中发板 (万+条+饼)*9 */
#define MAN 0
#define PENG 1 /*碰牌*/
#define LCHI 2 /*左将吃*/
#define MCHI 4 /*中将吃*/
#define RCHI 8 /*右将吃*/
#define TING 16 /*停牌*/
#define HU 32 /*和牌*/
char joke[CARDKINDS][5]={
"大饼","二饼","三饼","四饼","五饼","六饼","七饼","八饼","九饼"
,"一万","两万","三万","四万","五万","六万","七万","八万","九万"
,"夭鸡","二条","三条","四条","五条","六条","七条","八条","九条"
,"东风","西风","南风","北风","红中","发财","白板"};
char playerName[4][5]={"本家","下家","对家","上家"};
struct hotCard
{
int Id;
int val;
};
class majiang
{
private:
int host; /*庄家的代号 人:0 ; 机器:1,2,3*/
hotCard onHand; //刚刚摸到的牌
hotCard justThrowed; //上家扔出来的牌
int p[TOTALCARDS]; /*存储洗好的牌*/
int pInHand[4][CARDKINDS]; /*数字标记 标志每个人所拿到的牌 如果你手中有3个大饼 那么pInHand[0][0]=3 */
int pThrowed[4][CARDKINDS]; /*标记你打出去的牌*/
int explode[4][CARDKINDS]; /*记录碰了的或者是吃了的牌*/
int trigger; /*抓牌点*/
int possess; /*轮到谁*/
bool running; /*游戏运行标志*/
public :
majiang(); //构造函数
void initial(); /*洗牌*/
void pitch();
void nextTrigger();
void nextPossess();
void startPlay();
void showDesk();
void machineDo(int mth);
void manDo();
void throwAndWrite(int Id,int th); /*打牌并且记录*/
bool isWin(int Id);
bool manNeedThrowedCard(int peng,int chi);
int calValue(int mechId,int i);
bool ignitionForHu(); //打出去的牌检测是否有别人和
bool ignitionForChi();//打出去的牌检测是否被吃
bool ignitionForPeng();//打出去的牌检测是否被别人碰
void ignitionForOther(); /*刚刚被打出去的牌其他三个人可以吃,碰,胡*/
bool ignitionForPengOrChi(int Id,bool couldChi);
void putGettedCardIn();
void putOnhandCardIn();
void putThrowedCardIn(int Id); /*进行常识*/
void putThrowedCardOut(int Id); /*放弃常识*/
void oneGetACardOnHand();
void calTotalValue(int Id,int & valueSum,int & num); /*把Id的所有活牌的优先数 数目统计出来 */
int calAverageValueWhenChi(int Id,int tt,int tt1,int tt2);
void chiPai(int Id,int val1,int val2,int val3);//吃牌 后刷新手中的活牌
void pengPai(int Id,int justThrowedVal);
void afterGraspShowCards(int th);
void beforePengChiShowCards(int th);
void showCards(int th); /*把th手中的牌打印出来*/
void throwCard(int Id);
void manThrow();
void machineThrow(int Id);
int queryPengChi(int Id,int choicePeng,int choiceChi);
int queryMan(int peng,int chi);//询问人 是否要碰或者是吃 返回值是选择的命令
int queryMachine(int Id,int choicePeng,int choiceChi);//询问机器是否碰或者是吃
bool pipei3(int *p,int len);
};
majiang::majiang()
{
running=true;
for(int i=0;i<TOTALCARDS;i++)
{
p[i]=i/4;
}
for(int j=0;j<4;j++)
{
for(int k=0;k<CARDKINDS;k++)
{
pInHand[j][k]=0;
pThrowed[j][k]=0;
explode[j][k]=0;
//states[j][k]=0;
}
}
}
void majiang::initial()
{
time_t t; //随机种子
srand((unsigned)time(&t));
for(int j=1;j<TOTALCARDS;j++) /*随机洗牌*/
{
int index=rand()%(j+1);
swap(p[j],p[index]);
}
}
void majiang::pitch() /*电脑随机选庄家 并且掷色子开牌*/
{
int i;
time_t t; //随机种子
srand((unsigned)time(&t));
host=rand()%4; //选庄家
cout<<"-----庄家是:"<<playerName[host]<<"----------"<<endl;
cout<<"---------------------------------------------------"<<endl;
possess=host;
trigger=rand()%TOTALCARDS;
for(i=0; i<4*13; i++) /*模拟抓牌 每人13张牌*/
{
pInHand[possess][p[trigger]]++;
nextTrigger();
nextPossess();
}
}
void majiang::nextTrigger()
{
trigger++;
trigger%=TOTALCARDS;
}
void majiang::nextPossess()
{
possess++;
possess%=4;
}
bool majiang::ignitionForHu()
{
for(int i=1;i<4;i++)//先扫一遍 看是否有人胡
{
int temp=(i+justThrowed.Id)%4;
putThrowedCardIn(temp); //假想将刚刚别人打出来的牌抓进来 看和不和
if(isWin(temp)) /*看刚刚打出去的牌是否为别人点炮*/
{
cout<<playerName[justThrowed.Id]<<"打出["<<joke[justThrowed.val]<<"]给"<<playerName[temp]<<"点炮!"<<endl;
running=false; //结束游戏
return true;
}
putThrowedCardOut(temp); //不和则打出去
}
return false;
}
void majiang::pengPai(int Id,int justThrowedVal)
{
explode[Id][justThrowedVal]+=3;
pInHand[Id][justThrowedVal]-=2;
}
bool majiang::ignitionForPengOrChi(int Id,bool couldChi)
{
int tt=justThrowed.val;
int choiceChi=0,choicePeng=0;
if(couldChi==true&&tt<27)//如果可以吃(只对下家)看是否能吃上家打出的牌
{
int g=tt%9;
if(g<7)
{
if(pInHand[Id][tt+1]>0 && pInHand[Id][tt+2]>0)
choiceChi+=LCHI;
}
if(g>1)
{
if(pInHand[Id][tt-1]>0&&pInHand[Id][tt-2]>0)
choiceChi+=RCHI;
}
if(g>=1&&g<=7)
{
if(pInHand[Id][tt+1]>0&& pInHand[Id][tt-1]>0)
choiceChi+=MCHI;
}
}
if(pInHand[Id][tt]>=2)
choicePeng+=PENG;
if(choiceChi>0||choicePeng>0)//具有吃的条件 然后询问玩家是否选择吃
{
bool dealed=true;
int intention=queryPengChi(Id,choicePeng,choiceChi);
switch(intention) {
case LCHI:
chiPai(Id,tt,tt+1,tt+2);
cout<<playerName[justThrowed.Id]<<"-->"<<joke[justThrowed.val]<<" 被吃牌 ==>"<<playerName[Id]<<endl;
break;
case RCHI:
chiPai(Id,tt-2,tt-1,tt);
cout<<playerName[justThrowed.Id]<<"-->"<<joke[justThrowed.val]<<" 被吃牌 ==>"<<playerName[Id]<<endl;
break;
case MCHI:chiPai(Id,tt-1,tt,tt+1);
cout<<playerName[justThrowed.Id]<<"-->"<<joke[justThrowed.val]<<" 被吃牌 ==>"<<playerName[Id]<<endl;
break;
case PENG:pengPai(Id,tt);
cout<<playerName[justThrowed.Id]<<"-->"<<joke[justThrowed.val]<<" 被碰牌 ==>"<<playerName[Id]<<endl;
break;
default:
dealed=false;
}
if(dealed)
{
possess=Id;
throwCard(Id);
cout<<"***************吃[碰]牌后情况**************"<<endl;
showCards(Id);
cout<<"*******************************************"<<endl;
return true;
}
else return false;
}
else
return false;
}
int majiang::queryPengChi(int Id,int choicePeng,int choiceChi)
{
if(Id==MAN)
{
return queryMan(choicePeng,choiceChi);
}
else
{
return queryMachine(Id,choicePeng,choiceChi);
}
}
void majiang::ignitionForOther()
{
if(ignitionForHu())//先看有没有人和
{
cout<<"和牌了"<<endl;
running=false;
return;
}
for(int j=1;j<=3;j++)
{
if(j==1)
{
if(ignitionForPengOrChi((possess+j)%4,true))
{
cout<<playerName[justThrowed.Id]<<"打出的牌:"<<joke[justThrowed.val]<<" 被";
cout<<playerName[(possess+j)%4]<<"利用"<<endl;
break;//如果对于下家来说 (可以碰) 可以吃
}
}
else
{
if(ignitionForPengOrChi((possess+j)%4,false))
{
cout<<playerName[justThrowed.Id]<<"打出的牌:"<<joke[justThrowed.val]<<" 被";
cout<<playerName[(possess+j)%4]<<"利用"<<endl;
break;//对于另外两家来说 (可以碰) 不可以吃
}
}
}
return;
}
int majiang::calAverageValueWhenChi(int Id,int tt,int tt1,int tt2)
{
int sumValue,n;
// putThrowedCardIn(Id);
pInHand[Id][tt]--;
pInHand[Id][tt1]--;
pInHand[Id][tt2]--;
calTotalValue(Id,sumValue,n);
int average=sumValue/n;
pInHand[Id][tt]++;
pInHand[Id][tt1]++;
pInHand[Id][tt2]++;
// putThrowedCardOut(Id);
return average;
}
int majiang::queryMachine(int Id,int choicePeng,int choiceChi)
{
int tt=justThrowed.val;
int sumValue,n;
double original,average_peng=0,aver