麻将听牌的算法(java)

本文介绍了一种用于判断麻将游戏中玩家是否处于听牌状态的算法。该算法通过尝试移除玩家手中的每一张牌并检查剩余的牌是否能够组成胡牌组合来实现。文章详细展示了算法的实现过程及核心代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

   近来正在做麻将游戏,写了个判断听牌的算法(暂且称其为算法),和大家分享一下,
算法还没通过全面的验证,可能会遗漏某些情况。(我不太会打麻将阿)
其中判断和牌算法的程序代码是网上找的,是听牌算法的基石。在这感谢这位仁兄了。
1、在介绍算法之前,先说说我的牌值顺序:
 0-8  : 1-9万
 9-17 : 1-9筒
 18-26: 1-9条
 27-30: 东南西北风
 31-33: 中发白
 无花
2、MaJiang3.java 是判断可否听牌的程序
 (1)、判断点:当玩家抓进一张牌后(14张),系统判断出这时候打出某些牌后就听牌了
 (2)、思想:检查将某个牌替换成另一个牌后能不能和(不考虑番种),能和就表示能听
3、MaJiang2.java 是判断某一手牌是否能和的程序

还是看代码吧,我在程序里加了些注释: 

 

import java.util.*;
public class MaJiang3
{
    
/*
    先拿掉一个,然后再检测缺少什么,补上,这里不行,就补别的地方
    
*/

    
public ArrayList entryList = new ArrayList();   //替换对子
    
    
private int fmaj = -1;        //可以打掉的牌
    private int tmaj = -1;        //可以补上的牌
    
    
int[] w={3,1,1,1,2,1,1,1,3};  //1-9万各个牌的个数
    int[] to={0,0,0,0,0,0,0,0,0};
    
int[] ti={0,0,0,0,0,0,0,0,0};
    
int[] z={0,0,0,0,0,0,0};
    
    
public MaJiang3(int[] w, int[] to, int[] ti, int[] z)
    
{
        
this.w = w;
        
this.to = to;
        
this.ti = ti;
        
this.z = z;
    }

    
private void ting()
    
{        
        
for(int i = 0; i < 34; i++)
        
{
            
boolean exeIT = false;
            
if((i < 9 && w[i] >0) )
            
{
                w[i]
--;
                fmaj 
= i;
                
if(!check())
                
{ w[i]++;continue;}
                w[i]
++;
            }

            
else if(i >=9 && i < 18 && to[i-9>0)
            
{
                to[i
-9]--;
                fmaj 
= i;
                
if(!check())
                
{ to[i-9]++;continue;}
                to[i
-9]++;
            }
 
            
else if(i >=18 && i <27 && ti[i-18>0)
            
{
                ti[i
-18]--;
                fmaj 
= i;
                
if(!check())
                
{ ti[i-18]++;continue;}
                ti[i
-18]++;
            }

            
else if((i >= 27 && z[i-27>0))
            
{
                z[i
-27= z[i-27-1;
                fmaj 
= i;
                
if(!check())
                
{ z[i-27]++;continue;}
                z[i
-27]++;
            }

        }

    }


    
private boolean check()
    
{
        
boolean res = true;
        res 
= checkZi(z, 27);  //如果字牌不符合条件,就不用检查序数牌了
        checkNum(w, 0);
        checkNum(to, 
9);
        checkNum(ti, 
18);
        
return res;
    }

    
//检查字:因为字和序数牌不同,单独拿出来
    private boolean checkZi(int[] hua, int beginLoc)
    
{
        
//判断字
        boolean checkjiang = false;
        
for(int i = 0; i < hua.length; i++)
        
{
            
if(beginLoc + i == fmaj) continue;
            
if(hua[i] == 2)
            
{
                hua[i]
++;
                
if(hu(w,to,ti,z))
                
{
                    tmaj 
= beginLoc+i;
                    
                        print();
                    entryList.add(
new Entry(fmaj, tmaj));
                }

                
else
                
{
                    
if(!checkjiang)
                    
{
                        checkjiang 
= true;
                    }

                    
else
                    
{
                        hua[i]
--;
                        
return false;//不用往下匹对了,
                    }

                }

                hua[i]
--;
            }

            
else if(hua[i] == 1)
            
{
                hua[i]
++;
                
if(hu(w,to,ti,z))
                
{
                    tmaj 
= beginLoc+i;
                    print();
                    entryList.add(
new Entry(fmaj, tmaj));
                }

                
else 
                
{
                    hua[i]
--;
                    
return false;//不用往下匹对了
                }

                hua[i]
--;
            }

        }

        
return true;
    }

    
private void checkNum(int[] hua, int beginLoc)
    
{
        
boolean[] hasreplace = new boolean[9];  //检查是否已经替换过
        for (int i=0;i<hua.length ;i++ )
        
{
               
if(beginLoc + i == fmaj) continue;
              
if((i == 0 || hua[i] >0&& !hasreplace[i])
               
{
                   hua[i]
++;
                   hasreplace[i] 
= true;
                   
if(hu(w,to,ti,z))
                   
{
                       tmaj 
= beginLoc+i;
                    entryList.add(
new Entry(fmaj, tmaj));
                   }

                   hua[i]
--;
                   
//替换成i前面的那张牌
                   if(i > 0 && i < 9 && !hasreplace[i-1])
                   
{
                       hua[i
-1]++;
                       hasreplace[i
-1= true;
                       
if(hu(w,to,ti,z))
                       
{
                           tmaj 
= beginLoc + i - 1;
                        entryList.add(
new Entry(fmaj, tmaj));
                       }

                       hua[i
-1]--;
                   }

                   
//替换成i前面的那张牌
                   if(i > 0 && i < 8 && !hasreplace[i+1])
                   
{
                       hua[i
+1]++;
                       hasreplace[i
+1= true;
                       
if(hu(w,to,ti,z))
                       
{
                           tmaj 
= beginLoc + i + 1;
                        entryList.add(
new Entry(fmaj, tmaj));
                       }

                       hua[i
+1]--;
                   }

               }

        }

    }

    
public boolean hu(int[] aWan,int[] aTong,int[] aTiao,int[] aZi)
    
{
        
int[] tempWang = new int[aWan.length];
        
int[] tempTong = new int[aTong.length];
        
int[] tempTiao = new int[aTiao.length];
        
int[] tempZi = new int[aZi.length];
        System.arraycopy(aWan, 
0, tempWang, 0, aWan.length);
        System.arraycopy(aTong, 
0, tempTong, 0, aTong.length);
        System.arraycopy(aTiao, 
0, tempTiao, 0, aTiao.length);
        System.arraycopy(aZi, 
0, tempZi, 0, aZi.length);
        
boolean res = new MaJiang2().Hu(tempWang, tempTong, tempTiao, tempZi);
        
return res;
        
    }

    
private void print()
    
{
        System.out.print(
"w = ");
        
for(int i = 0; i < w.length; i++)
        
{
            System.out.print(w[i] 
+ "");
        }

        System.out.println();
        System.out.print(
"to = ");
        
for(int i = 0; i < to.length; i++)
        
{
            System.out.print(to[i] 
+ "");
        }

        System.out.println();
        System.out.print(
"ti = ");
        
for(int i = 0; i < ti.length; i++)
        
{
            System.out.print(ti[i] 
+ "");
        }

        System.out.println();
        System.out.print(
"z = ");
        
for(int i = 0; i < z.length; i++)
        
{
            System.out.print(z[i] 
+ "");
        }

        System.out.println();                        
    }

    
public static void main(String[] args) 
    
{
        
         
int[] w={0,0,0,0,0,0,0,1,1};
        
int[] to={0,0,0,0,1,1,1,0,0};
        
int[] ti={0,1,0,2,0,0,0,0,0};
        
int[] z={0,0,0,0,0,0,0};
        MaJiang3 mj
=new MaJiang3(w,to,ti,z);
        mj.ting();
        System.out.println(mj.entryList);
    }

    
    
    
class Entry
    
{
        
        
public int fmaj;
        
public int tmaj;
        
        
public Entry(int fmaj, int tmaj)
        
{
            
this.fmaj = fmaj;
            
this.tmaj = tmaj;
        }

        
public void setFmaj(int fmaj)
        
{
            
this.fmaj = fmaj;
        }

        
public void setTmaj(int tmaj)
        
{
            
this.tmaj = tmaj;
        }

        
public String toString()
        
{
            
return "(" + fmaj + "" + tmaj + ")";
        }

    }
 
}

 

这个是判断和牌的算法, 来自网络.

 

public class MaJiang2
{
    
private boolean jiang=false;//是否找到将
    
    
public MaJiang2(){}

    
//花色,判断这个花色是否被减完了(如果没有减完自然没有和)

    
private int huase(int[] hua)
    
{
        
if (hua.length==7)
        
{
            
//判断字,自比较特殊,没有顺
            for (int i=0;i<hua.length ;i++ )
            
{
                
if (hua[i]==3||hua[i]==4)
                
{
                    hua[i]
=0;
                    huase(hua);
                }

                
//如果字有两个,肯定是将
                if (hua[i]==2&&!jiang)
                
{
                    hua[i]
=0;
                    jiang
=true;
                    huase(hua);
                }

            }

        }

        
else
        
{
            
for (int i=0;i<hua.length ;i++ )
            
{
                
//如果没有将,先把将减出去
                if (!jiang&&hua[i]>=2)
                
{
                    hua[i]
=hua[i]-2;
                    jiang
=true;
                    
int fanhui=huase(hua);
                    
//如果递归回来依旧没有减完,则把将加回去
                    if (fanhui!=0)
                    
{
                        hua[i]
=hua[i]+2;
                        jiang
=false;
                    }

                }
 
                
if (hua[i]!=0&&i<7&&hua[i+1]!=0&&hua[i+2]!=0)
                
{
                    hua[i]
--;
                    hua[i
+1]--;
                    hua[i
+2]--;
                    huase(hua);
                    
int fanhui=huase(hua);
                    
//如果递归回来依旧没有减完,减去的加回去
                    if (fanhui!=0)
                    
{
                        hua[i]
++;
                        hua[i
+1]++;
                        hua[i
+2]++;
                    }

                }

                
if (hua[i]==3||hua[i]==4)
                
{
                    
int temp=hua[i];
                    hua[i]
=0;
                    huase(hua);
                    
int fanhui=huase(hua);
                    
//如果递归回来依旧没有减完,减去的加回去
                    if (fanhui!=0)
                    
{
                        hua[i]
++;
                        hua[i]
=temp;
                    }

                }

            }

        }

        
int re=0;
        
//最后判断减没减完
        for (int i=0;i<hua.length ;i++ )
        
{
            re
=re+hua[i];
        }

        
return re;
    }



    
public boolean Hu(int[] aWan,int[] aTong,int[] aTiao,int[] aZi)//aTiao
    {
        
        
if(huase(aZi) == 0 && huase(aWan) == 0 
            
&& huase(aTong) == 0 && huase(aTiao) == 0 && jiang)
        
{
            
return true;
        }

        
else
        
{
            
return false;
        }

    }

    
public static void main(String[] args) 
   
{
        MaJiang2 mj
=new MaJiang2();
         
int[] w={0,0,0,0,0,0,1,1,1};
        
int[] to={0,0,0,0,1,1,1,0,0};
        
int[] ti={0,0,0,2,0,0,0,0,0};
        
int[] z={0,0,0,0,0,0,0};
        
long beginTime = System.currentTimeMillis();
             mj.Hu(w,to,ti,z);
        
long endTime = System.currentTimeMillis();
        System.out.println(
"耗时:" + (endTime - beginTime));
    }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值