浪子最近在编一麻将游戏(惠州庄,广东一地区的规则),目前界面已经编出来了,现在做算法,开始觉得很简单,但是写起来觉得蛮复杂的,而且算法相当弱智,十分没有可取之处,不知有没有相同爱好的“同志(呵呵)能给我点头绪,谢谢。
刚来不久,分不多,大家见笑了。

解决方案 »

  1.   

    网上的单机麻将很多,我遇到过一个flash写的北京麻将,感觉暴强,flash 都能做,说明算法的效率挺高的。
      

  2.   

    浪子的胡牌函数写出来了,就是方法好象很笨,
    思路是这样子,每一手可胡的牌都可以看作是五组牌组成的,五组牌的可能形式是对子,顺子和刻子,
    意思就是:看手中的14张牌能不能胡,看它能不能组成状如(顺,刻,顺,刻,对)组合形式。
    这段程序仅考虑胡牌的可能,对番数未作考虑。
    表达能力较差,可能大家看不懂,还是看源码吧。
    function ZiMo(VInput:array of integer):bool;     //自摸
    var
      TmpZimo:bool; 
      Test:array[0..4] of integer;       // 胡牌组合检测参数
      Tmp34Card:array[0..33] of integer; // 14张牌的位置数组
      i,j,k,m,Sn,TestSuccess:integer;    // Sn用来存首张牌的位置beginTmpZimo := false; // 赋予初值
    j:=0;
    MySort(VInput,14); // 排序// 每一手可胡的麻将可拆分为五组牌,这五组牌分别由顺子,刻子和
    // 有且唯一的将牌(即对子)组成,
    // 所以每一手可胡的麻将牌理论上可能的胡牌组合=3的5次方=243种.
    // 实际上胡牌的可能组合为112种(因为将牌的特殊原因)// 设置循环方式,将112种胡牌组合依次代入,组合成功时退出.
    // 先计算出本次循环要代入的胡牌组合代数// ==把待检测的14张牌转换成位置数组for i :=0 to 33 do // 初始化,置零值
    Tmp34Card[i]:=0;for i :=0 to 13 do // 将麻将牌号换算为位置
    inc(Tmp34Card[(VInput[i]-1) div 4],1); //(本句已通过验证)// ==转换完成
    // 经过上循环,得出状如下列的数组
    // Tmp34Card=(0,0,1,1,1,0,3,0,0, 1,2,2,1,0,2,0,0,0, 0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0)// 七对在此程序里未作检测,因为我地的规则里没有七对
    // 十三么检测开始if (Tmp34Card[0]>0) and (Tmp34Card[8]>0) and (Tmp34Card[9]>0) and
    (Tmp34Card[17]>0) and (Tmp34Card[18]>0) and (Tmp34Card[26]>0) and
    (Tmp34Card[27]>0) and (Tmp34Card[28]>0) and (Tmp34Card[29]>0) and
    (Tmp34Card[30]>0) and (Tmp34Card[31]>0) and (Tmp34Card[32]>0) and
    (Tmp34Card[33]>0) and
    (
    (Tmp34Card[0]=2) or (Tmp34Card[8]=2) or (Tmp34Card[9]=2) or
    (Tmp34Card[17]=2) or (Tmp34Card[18]=2) or (Tmp34Card[26]=2) or
    (Tmp34Card[27]=2) or (Tmp34Card[28]=2) or (Tmp34Card[29]=2) or
    (Tmp34Card[30]=2) or (Tmp34Card[31]=2) or (Tmp34Card[32]=2) or
    (Tmp34Card[33]=2)
    ) then
    begin
    TmpZimo := true;
    j:=243;
    end;// 十三么检测结束while j<=242 do // 242次循环开始(3进制转换算法)
    beginm:=0;// 将113/243种胡牌组合中取一种组合赋予给Test[i]Test[0] := j div 81; // 第一组的组合形式(将,刻,顺)
    if Test[0]=0 then inc(m,1); // 每发现一组将牌,则参数m+1;Test[1]:= (j-(Test[0]*81)) div 27; // 第二组的组合形式
    if Test[1]=0 then inc(m,1); // 每发现一组将牌,则参数m+1;Test[2]:= (j-(Test[0]*81)-(Test[1]*27)) div 9; //第3组
    if Test[2]=0 then inc(m,1); // 每发现一组将牌,则参数m+1;Test[3]:= (j-(Test[0]*81)-(Test[1]*27)-(Test[2]*9)) div 3; //第4组
    if Test[3]=0 then inc(m,1); // 每发现一组将牌,则参数m+1;Test[4]:= j-(Test[0]*81)-(Test[1]*27)-(Test[2]*9)-(Test[3]*3); //第5组
    if Test[4]=0 then inc(m,1); // 每发现一组将牌,则参数m+1;// 上面段是从所有胡牌组合中取出一种可能组合并赋予Test[i]if m>1 then // 将牌不能超过一组,否则舍去此种组合,并重新循环
    begin
    inc(j,1);
    continue;
    end;// ==把待检测的14张牌转换成位置数组for i :=0 to 33 do // 初始化,全部置零值
    Tmp34Card[i]:=0;for i :=0 to 13 do // 将麻将牌号换算为位置
    inc(Tmp34Card[(VInput[i]-1) div 4],1); // ==转换完成
    // 经过上循环,得出状如下列的数组
    // Tmp34Card=(0,0,1,1,1,0,3,0,0, 1,2,2,1,0,2,0,0,0, ......){
    s:='';
    for n :=0 to 33 do
    s:=s+' '+inttostr(Tmp34Card[n]);
    ShowMessage(s);
    }Sn:=0; // 首张牌的位置号.置零
    i:=0; // 胡牌组合的第几组// 将113种胡牌组合中取一种组合代入待检牌
    // 可胡性检测开始while i<=4 do // 每一手可胡的麻将可拆分为五组牌
    begink:=0; // 找到(剩下牌中)首张牌的位置
    while k <= 33 do // 每一轮检测后都要在数组中减去已成功组合
    begin            // 的牌,所以要重新测定首张牌的位置
    if Tmp34Card[k]<>0 then
    begin
    Sn:=k; // 检测到后打上标志
    break; // 首张牌的位置号 eg: 0是一同,1是二同,8是九同,9是一索,10是二索,27是东风
    end;
    inc(k,1);
    end;// TestSuccess含义: 假设的组合是否与实际组合相符
    TestSuccess:=0; // 检测参数// 对子 2
    if Test[i]=0 then // 待检参数为将牌(对子)=>进入此段检测
    begin
    if Tmp34Card[Sn]>1 then // 可以配成对子
    begin
    Dec(Tmp34Card[Sn],2); // 在检测序列中减去两张牌
    TestSuccess:=1; // 本轮检测是否通过参数
    end;
    end;// 刻子 3
    if Test[i]=1 then // 待检参数为刻子=>进入此段检测
    begin
    if Tmp34Card[Sn]>2 then // 可以配成刻子
    begin
    Dec(Tmp34Card[Sn],3); // 在检测序列中减去三张牌
    TestSuccess:=1; // 本轮检测是否通过参数
    end;
    end;// 顺子 123
    if Test[i]=2 then // 待检参数为顺子=>进入此段检测
    begin
    if (Tmp34Card[Sn+1]<>0) and (Tmp34Card[Sn+2]<>0) and (sn<25)
    and ((sn mod 9)<>7) and ((sn mod 9)<>8) then // 可以配成顺子,标志牌不是八同九同八索
                                                 //九索八万九万和字牌
    begin
    Dec(Tmp34Card[Sn],1); // 在检测序列中减去
    Dec(Tmp34Card[Sn+1],1); // 在检测序列中减去
    Dec(Tmp34Card[Sn+2],1); // 在检测序列中减去
    TestSuccess:=1; // 本轮检测是否通过参数
    end; 
    end;if TestSuccess=0 then // 本轮无法组合,退出,换下一种组合
    break;if (i=4) and (TestSuccess=1) then // 如果第五组组合通过检测
    begin
    TmpZimo := true; // 则胡牌成功
    break; // 退出
    end;
    // 在三种牌型检测完毕后开始第2/5组检测
    inc(i,1); // 下一轮循环将检测 Test[i+1]end; // 可胡性检测结束if TmpZimo then break;inc(j,1);end; // 242次循环结束(3进制转换算法)ZiMo := TmpZimo;end;
      

  3.   

    我也想写个麻将游戏,等有时间的时候再想楼主这个问题..http://community.csdn.net/Expert/topic/4061/4061309.xml?temp=.9403498
      

  4.   

    楼主可以先看看flash版怎么写的。
    http://soft.66169.com/soft.php?id=1000717
    可以用闪客精灵一类的软件得到swf中的代码自己分析地。这是delphi的初初学者(打算学还没学:))