lua 实现四川麻将胡牌算法(附源代码讲解)

房卡棋牌游戏正如火如荼的遍地开花,迫使我也加入开发中的一员,最近完成了一套麻将棋牌游戏!今天给大家分享一下其中的算法部分!转载请说明出处,有更好的算法可以加扫描微信交流!

                                                  

                                            lua 实现四川麻将胡牌算法(附源代码讲解)_第1张图片


LUA源代码下载

一副麻将是否能否牌就必须满足以下公式(特殊牌型出外,7对,龙七对)
N*AAA+N*ABC+1*AA
看懂了吗?如果一副牌由N个刻子,N个连牌,有且只有一对组成那么我们就可以认为这副牌胡了!
如果还没有搞懂没关系,下面我们依次讲解什么意思!
AAA ABC AA
AAA:刻子  3张花色一样,点数一样的牌,俗称一砍牌
ABC:连牌 3张花色一样,点数彼此相差一点 如:123 345 678 俗称一搭牌
AA:对子  2张花色一样,点数一样的牌,俗称麻将


可以回忆一下我们平时打麻将胡牌之后牌型是否都满足这样的公式。
现在我们知道了胡牌的公式,那么在程序语言中我们是怎么来计算的呢????
工欲善其事,必先利其器!!!首先我们来定义一个麻将的数据结构
我们知道一副麻将里面有3种花色(万,筒,条),9个点数(1----9),我们就可以定义一个三维数组来存储我们手牌

Local handCard=
{
{0,0,0,0,0,0,0,0,0}, --表示万
{0,0,0,0,0,0,0,0,0}, --表示筒
{0,0,0,0,0,0,0,0,0}  --表示条
}
如图:

这副牌在数组里面就可以这样来定义
Local handCard=
{
{1,2,1,0,1,0,2,0,0}, --表示万
{0,0,1,1,1,0,2,0,1}, --表示筒
{0,0,0,0,0,0,0,0,0}  --表示条
}
看懂了嚒,每一个值代表每一张牌出现了几次,我们还可以在handCard里面再多定义一个数组用来表示每一张牌的属性,方便我们后面来计算连牌
 handCard[4]={}
    for i=1,3 do
      for j=1,9 do
         for h=1,card[i][j]  do
            local cardData ={}
             cardData.color = i
             cardData.point = j
             card[4][#card[4]+1]=  cardData
         end
       end
   end

这样我们手牌牌如何用数据来表示就完成了,接下来我们就可以开始拆牌了。定义几个数组分别用来储存 同一张牌出现了4次的牌,3次的牌,2次的牌。

 local cardData={}
   self.twoCardAry={}
   self.threeCardAry={}
   self.fourCardAry={}
   self.cloneCardList = {}

   for i=1, 3 do
     for j=1,9  do
        cardData={}
        if tempCardList[i][j] == 2 then
        cardData.color = i
        cardData.point = j
        self.twoCardAry[#self.twoCardAry+1] = cardData
        elseif tempCardList[i][j] == 3 then
        cardData.color = i
        cardData.point = j
        self.threeCardAry[#self.threeCardAry+1] = cardData
        elseif tempCardList[i][j] == 4 then
        cardData.color = i
        cardData.point = j
        self.fourCardAry[#self.fourCardAry+1] = cardData
        end 
     end
   end
   
最后依次把每张牌能组成的牌型都遍历一次,看最后能否满足我们之前定义的胡牌公式。

---是否能胡牌 参数 1牌的列表  2 打的那张牌  3自己缺的花色
function Algorithm:PlayerIs_Hu(cardList,nSendCardValue,nQueSe)
   
    local tempCardList = {}
    tempCardList[4]={}
   for i=1,3 do
     tempCardList[i]={}
     for j=1,9 do
         tempCardList[i][j] = cardList[i][j]
     end
   end
   tempCardList[nSendCardValue.color][nSendCardValue.point]  = tempCardList[nSendCardValue.color][nSendCardValue.point] + 1
   self:SortPlayerCards(tempCardList)
   
   --判断自己缺的花色打完没有
   for i=1,9 do
     if  tempCardList[nQueSe][i]>0 then return false end
   end
   
   local cardData={}
   self.twoCardAry={}
   self.threeCardAry={}
   self.fourCardAry={}
   self.cloneCardList = {}

   for i=1, 3 do
     for j=1,9  do
        cardData={}
        if tempCardList[i][j] == 2 then
        cardData.color = i
        cardData.point = j
        self.twoCardAry[#self.twoCardAry+1] = cardData
        elseif tempCardList[i][j] == 3 then
        cardData.color = i
        cardData.point = j
        self.threeCardAry[#self.threeCardAry+1] = cardData
        elseif tempCardList[i][j] == 4 then
        cardData.color = i
        cardData.point = j
        self.fourCardAry[#self.fourCardAry+1] = cardData
        end 
     end
   end
   
   if #self.twoCardAry == 7 then return true end   --7对
   if #self.twoCardAry == 5 and #self.fourCardAry ==1 then  return true end --龙七对

   local tempFour = 0
   local tempThree = 0
   local tempTwo = 0

   if next(self.twoCardAry)~=nil then  tempTwo = #self.twoCardAry  end
   if next(self.threeCardAry)~=nil then  tempThree = #self.threeCardAry end
   if next(self.fourCardAry)~=nil then  tempFour = #self.fourCardAry end

   
   --要胡牌 必须满足  AAA ABC AA  必须要有一对将牌
   local isHuCard = false
   for i=0,tempFour do
      for j=0,tempThree do
         for k=0,tempTwo do
          self.cloneCardList ={}
           
          for g=1,#tempCardList[4]  do
            self.cloneCardList[g] = tempCardList[4][g]    
          end
          
          isHuCard = self:CalcIsHuCard(i,j,k)
          if isHuCard == true then return true end
         end
      end   
   end
  
  return false
end


  function Algorithm:CalcIsHuCard(nFourIndex,nThreeIndex,nTwoIndex)

       local FourCardData =  nil
       local ThreeCardData =  nil
       local TwoCardData =  nil

       if nFourIndex>0   then FourCardData  =  self.fourCardAry[nFourIndex] end
       if nThreeIndex>0  then ThreeCardData =  self.threeCardAry[nThreeIndex] end
       if nTwoIndex>0    then TwoCardData   =  self.twoCardAry[nTwoIndex] end

       self:DelCardOfCardList(self.cloneCardList,FourCardData,4)
       self:DelCardOfCardList(self.cloneCardList,ThreeCardData,3)
       self:DelCardOfCardList(self.cloneCardList,TwoCardData,2)

       --剔除所有的连牌
       local nCntIndex = #self.cloneCardList
      
       local i=1
       local j=1
       local h=1
       while i<=nCntIndex do
            j=i+1
           while j<=nCntIndex do
               h=j+1
               while h<=nCntIndex do
                   if self.cloneCardList[i].color == self.cloneCardList[j].color and self.cloneCardList[i].color == self.cloneCardList[h].color  
                          and self.cloneCardList[i].point+1 == self.cloneCardList[j].point and self.cloneCardList[j].point+1 == self.cloneCardList[h].point  then
                        local card1 = self.cloneCardList[i]
                        local card2 = self.cloneCardList[j]
                        local card3 = self.cloneCardList[h]
                               
                        self:DelCardOfCardList(self.cloneCardList,card1,1)
                        self:DelCardOfCardList(self.cloneCardList,card2,1)
                        self:DelCardOfCardList(self.cloneCardList,card3,1)

                        nCntIndex = #self.cloneCardList
                        i=1 j=2 h=3
                    else
                        h=h+1      
                    end 
               end
               j=j+1
           end
            i=i+1
       end

       if nTwoIndex>0 then  --如果有一对  剩余的牌必须为0 才能胡牌
          if  nCntIndex == 0  then
                return true
          end
       else   ---如果没有一对  最后必须没有单牌 和有且只有一对
            local twoAry={}
            local OneAry={}
            local cardAry={}
            for i=1,3 do
                cardAry[i]={}
               for j=1,9 do
                  cardAry[i][j]=0
               end
            end
            
            for i=1,nCntIndex do
                local data = self.cloneCardList[i]
                cardAry[data.color][data.point] = cardAry[data.color][data.point] + 1 
            end
            
           
            local nIndex = 1
            for i=1,3 do
               for j=1,9 do
                   if cardAry[i][j]==1 then
                        return false
                   elseif cardAry[i][j]==2 then
                        nIndex = nIndex +1
                        if nIndex == 3 then
                          return false
                        end
                   end
               end
            end


            return true

       end
       

       return false
   end



你可能感兴趣的:(lua 实现四川麻将胡牌算法(附源代码讲解))