開源一個不過百行代碼而又強悍與效率的麻將賴子算法!!

如題:  
          博主17年開始從事棋牌遊戲開發,開始接觸賴子算法時,當時互聯網找不到任何資料,於是自己琢磨了三天開始寫出第一個算法,到目前爲止已經自己寫過三款不同的賴子算法,分別爲:

  1. 遞歸法        (<1ms級 , 複雜度爲:最好O(n),最差O(n^3) )
  2.優化型遞歸法代入法   ( us級 , 複雜度爲:最好O(n),最差O(n^2) )
  3 查表法          (us級 , 複雜度爲:O(1) )

      以上所有版本均支持多賴子,哪怕手牌是23張,全是賴子,均不影響複雜度,差異甚小

在徵得源項目老闆的同意下,分享第一種算法給遊戲愛好者們學習與進步,廢話少說,直接上代碼如下:

-----------------------------------------------------------------------------------------------------------------------
//會牌核心算法遞歸版本, 由原胡牌算法演進而來,檢測更全面    by    iori  2017/1/10
bool laizi_hupai_base(int *pi_mj, int i_num, int *pi_select,int laizi_val)
{
    //pi_select[]用於在遞歸調用時記錄已經訪問過的牌
    int i,j,k;
    int i_max,i_min,i_mid;
    int i_mark1,i_mark2;
    int i_have3=0 ,laizi_num = 0;
    
    for(i=0; i<i_num; i++)
    {
        if( pi_select[i] )
            continue;
        else
            i_mark1 = i;
        
        for( j=i+1; j<i_num; j++)
        {
            if( i == j )
                continue;
            if(pi_select[j])
                continue;
            else
                i_mark2 = j;
            
            for( k=j+1; k<i_num; k++)
            {
                if( i==k || j==k )
                    continue;
                if( pi_select[k] )
                    continue;
                
                i_have3 = 1;
                laizi_num = 0;
                i_max = std::max(pi_mj[i], std::max(pi_mj[j], pi_mj[k]));
                i_min = std::min(pi_mj[i], std::min(pi_mj[j], pi_mj[k]));
                i_mid = (i_max + i_min) / 2;
                
		//判斷選中的是否爲賴子,這裏傳入多個val,可以支持多賴
                if (pi_mj[i] == laizi_val) laizi_num++;
                if (pi_mj[j] == laizi_val) laizi_num++;
                if (pi_mj[k] == laizi_val) laizi_num++;
                
                if (laizi_num >= 2) //能成有會刻或者順,默認刻
                {
                        // do something  根據你的項目需求可以保存數據
                }
                else
                if( (pi_mj[i] == pi_mj[j] && pi_mj[i] == pi_mj[k]) || (laizi_num == 1 && (pi_mj[i]  ==  pi_mj[j] ||  pi_mj[j] == pi_mj[k] || pi_mj[i]  == pi_mj[k]))  )  //表示能組成刻子
                {
                        // do something
                }
                else  if (laizi_num == 1)//判斷是否能成有會順
                {
                    if(pi_mj[i] == laizi_val)
                    {
                        if(pi_mj[j] - pi_mj[k] != -1 && pi_mj[j] - pi_mj[k] != -2 && pi_mj[j] - pi_mj[k] != 1 && pi_mj[j] - pi_mj[k] != 2 )
                            continue;
			//這裏根據項目不同的牌值區分 中發白與風牌過濾掉,博主這個項目沒有,就不補上了
                    }else if(pi_mj[j] == laizi_val)
                    {
                        if(pi_mj[i] - pi_mj[k] != -1 && pi_mj[i] - pi_mj[k] != -2 && pi_mj[i] - pi_mj[k] != 1 && pi_mj[i] - pi_mj[k] != 2 )
                            continue;
                    }else if(pi_mj[k] == laizi_val)
                    {
                        if(pi_mj[i] - pi_mj[j] != -1 && pi_mj[i] - pi_mj[j] != -2 && pi_mj[i] - pi_mj[j] != 1 && pi_mj[i] - pi_mj[j] != 2 )
                            continue;
                    }
                        
                }else
                if( i_max-i_min == 2 && ( pi_mj[i] == i_mid || pi_mj[j] == i_mid || pi_mj[k] == i_mid)) //表示能組成順子
                {
                        // do something
                }else
                    continue;
                
                //記錄下來 下面遞歸
                pi_select[i] = pi_select[j] = pi_select[k] = 1;
                
                if( !laizi_hupai_base(pi_mj, i_num, pi_select,laizi_val) )
                {
                    pi_select[i] = pi_select[j] = pi_select[k] = 0; //遞歸一次結束,返回
                    continue;
                }
                
                //選擇的3張成刻、順,而剩下的和了
                return true;
            }
            
            //只剩兩張牌, 相等 或者 其中一張爲癩子時,滿足牌型
            if( (i_have3 == 0) &&( pi_mj[i_mark1] == pi_mj[i_mark2] || pi_mj[i_mark1] == laizi_val ||  pi_mj[i_mark2] == laizi_val  ))
            {
                return true; //這裏不退出,可以保存下來計算出所有能胡的牌型
            }
        }
    }
    return false;
}			

------------------------------------------------------------------ end by Iori

    算法好不好,跑一跑就知道,打上time log就明瞭,如有疑問,歡迎留言,支持原創,支持開源,如有轉載,請與博主聯繫授權 !

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章