歪胡子牌胡法
湖南岳阳一带流行一种纸牌玩法,“歪胡子”,也叫“鬼胡子”是由一,二,三....十;及壹,贰,参.....拾,组成,共80支牌。手上牌打牌时牌数是3的倍数多一张牌,不超过19张,胡牌时是3的倍数多2张牌,不超过20张。有玩法与麻将有点类似,由三个连续的数或三个相同的数组合,但多了一个二,七,十的组合,大字与小字之间不能相混组合。胡牌时也和麻将有点不同,二个门子都可胡牌。如以下都可胡牌:(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; }