胡牌高手
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了胡牌高手相关的知识,希望对你有一定的参考价值。
玩过麻将 龙虎榜的人应该很熟悉这个画面,一般三连庄之后,会有个小游戏。这个游戏叫胡牌高手,就是给你十三张牌,都是清一色的万子,筒子或者条子,找出胡的那几张牌。
我的电玩生涯中,有几个游戏一直陪伴着我,街霸,双截龙,拳皇,快打三和龙虎榜,也叫搓牌高手。其他的游戏起起落落,一段时间过去,都从各大游戏室里面消失,当然搓牌高手最后也不能幸免,但是它的时间跨度是其他游戏所不能比的。最早玩的游戏应该数名将,那个瘦的像芦材棒的选手是大家的最爱,那一招死的玩法是永远的经典,也是早期街机的著名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]--; } }