【算法】通用麻將胡牌算法

聲明

算法並非原創 , 但是來源已經忘記了 , 當時考慮算法的時候看了比較多的麻將胡牌算法 , 想尋找自己比較容易理解的 , 找了幾篇,所以算法的出處已然忘記,不過還是感謝下原創吧 .

算法

1.將麻將抽象爲數字

數字 {01 ~ 09} 表示 {1 ~ 9} 筒
數字 {11 ~ 19} 表示 {1 ~ 9} 條
數字 {21 ~ 29} 表示 {1 ~ 9} 萬
數字 {31 33 35 37 } 表示 { 東 南 西 北 }
數字 {41 43 45} 表示 {中 發 白}

數字10 20 30 32 34 36 40 42 44 46 空出來不代表任何麻將牌
這樣設計的好處就是
使得能夠形成順子的牌在用數字表示出來的時候剛好也是連着的
而不能夠形成順子的牌,在用數字表示的時候並不是順子
便於以後使用代碼進行判斷

2.算法的核心流程

玩過麻將的都知道麻將玩家手上一般有兩種牌 一種是手牌 一種是已經碰牌或者吃牌或者槓牌之後已經明瞭的牌 . 現在以玩家A爲例 , 把牌分的細一點

a. 玩家A的手牌 (數量1 + 3n n < N , n < 4 )
b. 其他玩家打出來的牌 (數量 1)
c. 玩家A從牌面上取出來的牌 (數量 1)
d. 玩家A吃碰槓的牌 (3
n + 4*m)
  
能否胡牌主要是看手牌a 和b/c 的組合能否形成一對加n條順子和m條克子 . 能則能胡 反則不能.

在這裏插入圖片描述
代碼如下:

public static bool IsCanHU(List<int> mah, int ID)
{
    List<int> pais = new List<int>(mah);
 
    pais.Add(ID);
    //只有兩張牌
    if (pais.Count == 2)
    {
        return pais[0] == pais[1];
    }
 
    //先排序
    pais.Sort();
 
    //依據牌的順序從左到右依次分出將牌
    for (int i = 0; i < pais.Count; i++)
    {
        List<int> paiT = new List<int>(pais);
        List<int> ds = pais.FindAll(delegate (int d)
        {
            return pais[i] == d;
        });
 
        //判斷是否能做將牌
        if (ds.Count >= 2)
        {
            //移除兩張將牌
            paiT.Remove(pais[i]);
            paiT.Remove(pais[i]);
 
            //避免重複運算 將光標移到其他牌上
            i += ds.Count;
 
            if (HuPaiPanDin(paiT))
            {
                return true;
            }
        }
    }
    return false;
}
 
private static bool HuPaiPanDin(List<int> mahs)
{
    if (mahs.Count == 0)
    {
        return true;
    }
 
    List<int> fs = mahs.FindAll(delegate (int a)
    {
        return mahs[0] == a;
    });
 
    //組成克子
    if (fs.Count == 3)
    {
        mahs.Remove(mahs[0]);
        mahs.Remove(mahs[0]);
        mahs.Remove(mahs[0]);
 
        return HuPaiPanDin(mahs);
    }
    else
    { //組成順子
        if (mahs.Contains(mahs[0] + 1) && mahs.Contains(mahs[0] + 2))
        {
            mahs.Remove(mahs[0] + 2);
            mahs.Remove(mahs[0] + 1);
            mahs.Remove(mahs[0]);
 
            return HuPaiPanDin(mahs);
        }
        return false;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章