#2
wp2319572013-04-07 10:57
|
如以下都可胡牌:(1,2,3...代表: 一,二,三...; 11,12,13...代表:壹,贰,参)
1 2 3 2 7 10 15 16
1 2 3 2 7 15 16 17
1 2 3 2 7 10 15 17
1 2 3 2 7 10 15 15
以下完成了是否胡牌的程序,暂时没考虑“息”的情况,主要思路是,如果胡牌,则一定可以加张牌,使最后剩下的二张牌完成一句话或三个相同或二七十的组合,此思路多了很多重复的计算,主要是为了回避二七十组合的干扰。欢迎朋友们讨论。
程序代码:
#include<iostream>
using namespace std;
int _del(int* a) //處理函數21支牌(增加了1支)
{
int i;
for( i=0; i<20; i++)
{
if(a[i]>=3)
{
a[i]-=3;
}
if(a[i]==1 && i<8) //處理連續的小字
{
if(a[i+1]>0 && a[i+2]>0)
{ a[i]--; a[i+1]--; a[i+2]--;}
}
if(a[i]==2 && i<8 ) //處理連續的小字
{
if(a[i+1]>1 && a[i+2]>1)
{ a[i]-=2; a[i+1]-=2; a[i+2]-=2;}
}
if(a[i]==1 && i>=10 && i<18) //處理連續的大字
{
if(a[i+1]>0 && a[i+2]>0)
{ a[i]--; a[i+1]--; a[i+2]--;}
}
if(a[i]==2 && i>=10 && i<18 ) //處理連續的大字
{
if(a[i+1]>1 && a[i+2]>1)
{ a[i]-=2; a[i+1]-=2; a[i+2]-=2;}
}
}
int sum=0;
for(i=0; i<20 ; i++)
sum+=a[i];
return sum;//sum==0,胡牌
}
int main()
{
int min, MIN,b[20]={0}, a[20], i,j,flat2=0;
bool endw;
int pai_source[20]={1,2,3,2,7,10,11,12,13,12,12,20,17,17,20,17,15};//手上的原牌(牌数%3==2)
for( i=0 ; i<20; i++)//統計每張牌的個數
b[pai_source[i]-1]++;
for(i=0 ; i<20; i++)
cout<<b[i]<<" /";
cout<<endl;
for( j=0; j<20; j++) //試探增加每張牌,看否能和其他組合成一句話
//或三個相同的數,或2,7,10的组合。
{
for(i=0;i<20; i++)//更新牌
a[i]=b[i];
a[j]++;
min=a[1]<a[6]? a[1]:a[6];
min=min<a[9]? min:a[9];//求小字中二,七,十中最小的那個數
MIN=a[11]<a[16]? a[11]:a[16];
MIN=MIN<a[19]?MIN:a[19]; //求大字中二,七,十中最小的那個數
int a1[20]={0};
for(i=0; i<20; i++)//保存增加的牌的某种情况。
a1[i]=a[i];
for(int l=0; l<=min ; l++)// 以便處理考慮小字2 7 10 的情況。
{
for(i=0; i<20; i++)
a[i]=a1[i];
switch(l)
{
case 1 : a[1]--; a[6]--; a[9]--;break;//2,7,10减一
case 2 : a[1]-=2; a[6]-=2; a[9]-=2;break;
default :break;
}
int a2[20]={0};
for(i=0; i<20; i++)
a2[i]=a[i];
for(int t=0; t<=MIN ; t++)
{
for(i=0; i<20; i++)
a[i]=a2[i];
switch(t)
{
case 1 : a[11]--; a[16]--; a[19]--;break;//大字2,7,10减一
case 2 : a[11]-=2; a[16]-=2; a[19]-=2;break;
default :break;
}
if( _del(a)==0 )
{flat2=1;goto endw;}
}
}
}
endw:
if(flat2) cout<<"ok!"<<endl;
else cout<<"no!"<<endl;
return 0;
}
using namespace std;
int _del(int* a) //處理函數21支牌(增加了1支)
{
int i;
for( i=0; i<20; i++)
{
if(a[i]>=3)
{
a[i]-=3;
}
if(a[i]==1 && i<8) //處理連續的小字
{
if(a[i+1]>0 && a[i+2]>0)
{ a[i]--; a[i+1]--; a[i+2]--;}
}
if(a[i]==2 && i<8 ) //處理連續的小字
{
if(a[i+1]>1 && a[i+2]>1)
{ a[i]-=2; a[i+1]-=2; a[i+2]-=2;}
}
if(a[i]==1 && i>=10 && i<18) //處理連續的大字
{
if(a[i+1]>0 && a[i+2]>0)
{ a[i]--; a[i+1]--; a[i+2]--;}
}
if(a[i]==2 && i>=10 && i<18 ) //處理連續的大字
{
if(a[i+1]>1 && a[i+2]>1)
{ a[i]-=2; a[i+1]-=2; a[i+2]-=2;}
}
}
int sum=0;
for(i=0; i<20 ; i++)
sum+=a[i];
return sum;//sum==0,胡牌
}
int main()
{
int min, MIN,b[20]={0}, a[20], i,j,flat2=0;
bool endw;
int pai_source[20]={1,2,3,2,7,10,11,12,13,12,12,20,17,17,20,17,15};//手上的原牌(牌数%3==2)
for( i=0 ; i<20; i++)//統計每張牌的個數
b[pai_source[i]-1]++;
for(i=0 ; i<20; i++)
cout<<b[i]<<" /";
cout<<endl;
for( j=0; j<20; j++) //試探增加每張牌,看否能和其他組合成一句話
//或三個相同的數,或2,7,10的组合。
{
for(i=0;i<20; i++)//更新牌
a[i]=b[i];
a[j]++;
min=a[1]<a[6]? a[1]:a[6];
min=min<a[9]? min:a[9];//求小字中二,七,十中最小的那個數
MIN=a[11]<a[16]? a[11]:a[16];
MIN=MIN<a[19]?MIN:a[19]; //求大字中二,七,十中最小的那個數
int a1[20]={0};
for(i=0; i<20; i++)//保存增加的牌的某种情况。
a1[i]=a[i];
for(int l=0; l<=min ; l++)// 以便處理考慮小字2 7 10 的情況。
{
for(i=0; i<20; i++)
a[i]=a1[i];
switch(l)
{
case 1 : a[1]--; a[6]--; a[9]--;break;//2,7,10减一
case 2 : a[1]-=2; a[6]-=2; a[9]-=2;break;
default :break;
}
int a2[20]={0};
for(i=0; i<20; i++)
a2[i]=a[i];
for(int t=0; t<=MIN ; t++)
{
for(i=0; i<20; i++)
a[i]=a2[i];
switch(t)
{
case 1 : a[11]--; a[16]--; a[19]--;break;//大字2,7,10减一
case 2 : a[11]-=2; a[16]-=2; a[19]-=2;break;
default :break;
}
if( _del(a)==0 )
{flat2=1;goto endw;}
}
}
}
endw:
if(flat2) cout<<"ok!"<<endl;
else cout<<"no!"<<endl;
return 0;
}