判断麻将和牌的算法(转载)

判断麻将和牌的算法(转载)
2007年05月22日 星期二 下午 05:59
 
/***************************************************************
* 文件名:hu.cpp                                               *
*                                                              *
* 功   能:演示一个简洁明了的递归函数——判断[麻将]的和牌。     *
*                                                              *
* 说   明:1.   此函数不判断七对和十三幺,读者不难自行判断;     *
*     同时由于麻将的规则各不相同,也请读者自己添加和修改。*
*                                                              *
*     2.   其他与麻将类似的游戏,如[字牌](又称跑胡子、     *
*     二七十)等牌类游戏,也可采用类似的判断函数。         *
*                                                              *
* 环   境: VC 6.0,   但符合ANSI C标准,随便移植 ^_^              *
*                                                              *
* 作   者:shyworm(怕怕虫)                                      *
* E_Mail: shyworm@sina.com                                     *
***************************************************************/
#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;
}
 
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值