判断麻将和牌的算法(转载) 2007年05月22日 星期二 下午 05:59
#include <stdio.h> int Hu(int PAI[38]); int Remain(int PAI[38]); int main() { // 把一副牌放在下面的数组里,可以任意填入数字来测试函数正确与否。 // 为了方便,PAI[0],PAI[10],PAI[20],PAI[30]都弃之不用,并且必须 // 置为0,千万注意! int PAI[38] = { 0, 1,1,1,0,1,1,1,0,0, // PAI[ 1- 9] 壹万~玖万的个数 0, 0,0,0,0,0,3,0,0,0, // PAI[11-19] 壹铜~玖铜的个数 0, 0,0,0,0,0,0,0,0,0, // PAI[21-29] 壹条~玖条的个数 0, 0,1,1,1,0,0,0 // PAI[31-37] 东南西北中发白的个数 }; // 请务必先排除“七对” 和“十三幺”,由于简单,所以不提供了 // if( QIDUI(PAI) )... // if( SHISANYAO(PAI) )... if( Hu(PAI) ) printf("哈!我和啦!/n"); else printf("哎,和不成!/n"); return 1; } // 判断和牌的递归函数,不考虑“七对” 和“十三幺”。因为如果 // 把“七对” 和“十三幺”的判断放在递归函数里,将得不偿失。 int Hu(int PAI[38]) { static int JIANG = 0; // 将牌标志,即牌型“三三三三二”中的“二” if( !Remain(PAI) ) return 1; // 递归退出条件:如果没有剩牌,则和牌返回。 for(int i=1;!PAI[i]&&i<38;i++); // 找到有牌的地方,i就是当前牌, PAI[i]是个数 printf("i = %d/n",i); // 跟踪信息 // 4张组合(杠子) if ( PAI[i] == 4 ) // 如果当前牌数等于4张 { PAI[i] = 0; // 除开全部4张牌 if( Hu(PAI) ) return 1; // 如果剩余的牌组合成功,和牌 PAI[i] = 4; // 否则,取消4张组合 } // 3张组合(大对) if ( PAI[i] >= 3 ) // 如果当前牌不少于3张 { PAI[i] -= 3; // 减去3张牌 if( Hu(PAI) ) return 1; // 如果剩余的牌组合成功,和牌 PAI[i] += 3; // 取消3张组合 } // 2张组合(将牌) if ( !JIANG && PAI[i] >= 2 ) // 如果之前没有将牌,且当前牌不少于2张 { JIANG = 1; // 设置将牌标志 PAI[i] -= 2; // 减去2张牌 if( Hu(PAI) ) return 1; // 如果剩余的牌组合成功,和牌 PAI[i] += 2; // 取消2张组合 JIANG = 0; // 清除将牌标志 } if ( i > 30 ) return 0; // “东南西北中发白”没有顺牌组合,不和 // 顺牌组合,注意是从前往后组合! if( i%10 != 8 && i%10 != 9 && // 排除数值为8和9的牌 PAI[i+1] && PAI[i+2] ) // 如果后面有连续两张牌 { PAI[i]--; PAI[i+1]--; PAI[i+2]--; // 各牌数减1 if( Hu(PAI) ) return 1; // 如果剩余的牌组合成功,和牌 PAI[i]++; PAI[i+1]++; PAI[i+2]++; // 恢复各牌数 } // 无法全部组合,不和! return 0; } // 检查剩余牌数 int Remain(int PAI[38]) { int sum = 0; for(int i=1;i<38;i++) sum += PAI[i]; return sum; } |