胡牌高手

来源:互联网 发布:哈尔滨飞扬软件怎么样 编辑:程序博客网 时间:2024/04/28 08:19


   玩过麻将 龙虎榜的人应该很熟悉这个画面,一般三连庄之后,会有个小游戏。这个游戏叫胡牌高手,就是给你十三张牌,都是清一色的万子,筒子或者条子,找出胡的那几张牌。

   我的电玩生涯中,有几个游戏一直陪伴着我,街霸,双截龙,拳皇,快打三和龙虎榜,也叫搓牌高手。其他的游戏起起落落,一段时间过去,都从各大游戏室里面消失,当然搓牌高手最后也不能幸免,但是它的时间跨度是其他游戏所不能比的。最早玩的游戏应该数名将,那个瘦的像芦材棒的选手是大家的最爱,那一招死的玩法是永远的经典,也是早期街机的著名bug。当时,格斗技能不行,和电脑玩玩还凑和,和人玩,心理素质极不过关,后来混久了,慢慢习惯了,成了菜鸟专杀。至今记得在烟雾缭绕的游戏室里面,一叠铜币,偶尔叼根同学给的烟,全神贯注的操作着方向杆,狠狠的按下游戏键,那是有钱的时候,没钱的时候,只能在旁欣赏着别人的表演,一面揣摩着如果是自己在操作会如何如何。那是我人生最堕落的时光,也是我人生最快乐的时候。小学五年,初中三年,快乐的背后,也为我的未来生活留下不少问题,但是年少怎能不轻狂呢,过去要省视,重要的是活在当前

   麻将的规则挺多,除去特殊的牌型如十三幺,七对子等等,n*AAA+m*ABC+DD 是万变不离其宗的胡牌牌型。这里不研究通用的麻将胡牌算法,它比较啰嗦, 只考虑游戏里的这种情形。清一色的牌型。

  选出一张备选的牌型进入牌局,凑成14张牌 ,对十四张牌进行分解,12张牌和对子2张对子。

  对12张牌进行分解,将其分解为n*AAA+m*ABC的形式,如果分解成功,那么即为胡牌,否则失败。对于这十二张牌,每次从最左边的牌入手,该牌无非为顺子(ABC)或者刻(AAA),分别进行枚举,若匹配成功,将剩余的九张牌进行递归分解,方法同上。若失败则返回。

#include <stdio.h>

#define INPUT_SIZE 13

int input[INPUT_SIZE] = {2,3,4,4,4,4,5,6,7,7,8,8,9};    
//int input[INPUT_SIZE] = {1,2,2,4,4,5,5,6,6,7,7,8,8};    
//int input[INPUT_SIZE] = {1,1,1,2,3,4,5,6,7,8,9,9,9}; //九莲宝灯    
int data[9] = {0};

void getdata(int *in,int *out)// 将输入数据转换为累加数据    
{    
   int i;    
   for(i=0;i<INPUT_SIZE;i++)  out[in[i]-1]++;    
}    
int markshunzi(int *dt,int i,int d)//顺子匹配,d=-1表示选择操作,1表示回滚    
{    
    if(i>=7) return -1;

    if(d==-1)    
    {    
        if(dt[i]==0||dt[i+1]==0||dt[i+2]==0) return -1;

    }   
    dt[i]+=d;    
    dt[i+1]+=d;    
    dt[i+2]+=d;    
    return 0;    
}    
int markke(int *dt,int i,int d)//d的意义同上    
{

    dt[i] += 3*d;    
    if(dt[i]>=0&&dt[i]<=4)  return 0;    
    dt[i] -= 3*d;    
    return -1;

}    
int check3pattern(int *dt,int total) //进行顺子或者刻的搜索过程    
{    
    int i,j ;    
    if(total==12) return 0;    
    for(i=0;i<9;i++)    
    {    
        if(dt[i]==0) continue; 
        if(markke(dt,i,-1)==0)    
        {    
            total+=3;    
            j = check3pattern(dt,total);   
            total-=3;    
            markke(dt,i,1);    
            if(j==0)    
            {    
                printf("%d,%d,%d \n",i+1,i+1,i+1);    
                return 0;    
            };

        }    
        if(markshunzi(dt,i,-1)==0)    
        {    
            total+=3;    
            j =check3pattern(dt,total);           
            total-=3;    
            markshunzi(dt,i,1);    
            if(j==0)    
            {    
                printf("%d,%d,%d \n",i+1,i+2,i+3);    
                return 0;    
            }

        }    
        if(j!=0) return -1;    
    }    
    return -1;    
}    
int is_hupai(int *dt)    
{    
     int i,left = 0,rst; //对子的左边张数,对子的右边张数    
      for(i=0;i<9;i++)   //是否为7对子    
     {    
         if(dt[i]%2!=0)  
         {    
             break;    
         }    
     }    
     if(i==9)    
     {    
         printf("七对子 \n");    
         return 0;  //符合7对子牌型    
     }    
     for(i=0;i<9;i++)    
     {            
         if((dt[i]==2&&left%3==0)||dt[i]>2) //做一些剪枝    
         {    
             dt[i]-=2;    
             rst = check3pattern(dt,0);    
             dt[i]+=2;    
             if(rst==0)    
             {    
                 printf("门对:%d,%d \n",i+1,i+1);    
                 return 0;    
             }    
         }            
         left+=dt[i];    
     }    
     return -1;    
}

void main()    
{    
   int i;    
   getdata(input,data);    
   for(i=0;i<9;i++)    
   {    
        if(data[i]>=4)    
        {    
            printf("%d萬已经超过4张牌,不能加入%d 萬\n",i+1,i+1);    
            continue;    
        }    
        data[i]++;     
       if(is_hupai(data)==0)    
       {    
           printf("胡 %d 萬 \n",i+1);    
       }    
       else    
       {    
           printf("不胡 %d 萬 \n",i+1);    
       }

        data[i]--;    
   }

}

程序清单

输入

2,3,4,4,4,4,5,6,7,7,8,8,9


1,2,2,4,4,5,5,6,6,7,7,8,8


1,1,1,2,3,4,5,6,7,8,9,9,9 //九莲宝灯


0 0
原创粉丝点击