胡牌判断函数
*该函数判断手牌有没有胡牌,手牌的数量一定为[2,5,8,11,14]*当手牌数量为14时,判断是否有特殊牌型的胡牌[十三么,七对,全不靠]
*当不存在以上牌型时,用递归算法判断是否存在一般的胡牌牌型
*
*作者:yutian(于恬)
*E_main:[email]yution@126.com[/email]
*
*作者声明:本代码为学习时编写的代码,大家可以随意转贴及编译修改
*但不得用于商业用途和赌博,作者保留一切权力
*
*鸣谢:网友 shyworm(怕怕虫) E_mail:[email]shyworm@sina.com[/email]
* 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:[email]shyworm@sina.com[/email]
在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]
页:
[1]