浪子的胡牌函数写出来了,就是方法好象很笨, 思路是这样子,每一手可胡的牌都可以看作是五组牌组成的,五组牌的可能形式是对子,顺子和刻子, 意思就是:看手中的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;
思路是这样子,每一手可胡的牌都可以看作是五组牌组成的,五组牌的可能形式是对子,顺子和刻子,
意思就是:看手中的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;
http://soft.66169.com/soft.php?id=1000717
可以用闪客精灵一类的软件得到swf中的代码自己分析地。这是delphi的初初学者(打算学还没学:))