1. 程式人生 > >記錄一下學習筆記和看到值得記錄的文章

記錄一下學習筆記和看到值得記錄的文章

上篇文章寫了鬥地主牌型判斷的幾個簡單的牌型的判斷,現在來寫剩下的幾個複雜的牌型

本人小菜鳥,演算法寫的不好之處請大家不吝賜教

注意下面所有的判斷都是先將數字去掉花色之後的判斷

--順子 只要判斷相鄰的數字數值是否差1就可以
function isConnect(cards)
  if not CardUtils.isCards(cards) or 5 > #cards then 
      return false
  end
  table.sort(cards)
  --2和大小王不能加入順子
  if cards[#cards] > 14 then
    return false
  end
  for i = 1, (#cards - 1) do
    if cards[i] ~= cards[i+1] -1 then
      return false
    end
  end
  return true
end

-- 連對 33445566 1和2 3和4 5和6 7和8 相等 ,2和3 4和5 6和7 相差1 
function isCompany(cards)
  if not CardUtils.isCards(cards) or 6 > #cards or (#cards % 2) ==1 then 
      return false
  end
  table.sort(cards)
  local len = #cards
  for i = 1, (len - 1) do
    if (i % 2) ==1 then
      if cards[i] ~= cards[i + 1]  then
        return false
      end 
    else
      if cards[i] ~= cards[i + 1] - 1 then
        return false
      end
    end
  end
  return true
end

-- 飛機不帶  
-- 遍歷到三個一組中的第一個的時候判斷這組的值是否都相等
-- 遍歷到三個一組中的最後一個的時候判斷和下一組的數值是不是差一
function isAircraft(cards)
  if not CardUtils.isCards(cards) or 6 > #cards or (#cards % 3) ~=0 then 
      return false
  end 
  table.sort(cards)
  local len = #cards
  for i = 1, (len - 1) do
    if (i % 3) ==1 then
      if cards[i] ~= cards[i + 1] or cards[i + 1] ~= cards[i + 2] then
        return false
      end 
    elseif (i % 3) == 0 then
      if cards[i] ~= cards[i + 1] - 1 then
        return false
      end
    end
  end
  return true 
end



-- 4帶2
function isBombTwo(cards)
  if not CardUtils.isCards(cards) or 8 < #cards or #cards < 6 or (#cards % 2) ~=0 then 
      return false
  end 

  table.sort(cards)
  local tmpTable1 = {} --存放炸彈牌
  local tmpTable2 = {}  --存放炸彈帶的牌
  local tmppos = 0
   -- 先從牌中抽出炸彈不帶的牌
  for pos = 1, (#cards - 3)  do
    if cards[pos] == cards[pos + 1] and cards[pos] == cards[pos + 2] and cards[pos + 2]  == cards[pos + 3] then
      table.insert(tmpTable1, cards[pos])
      table.insert(tmpTable1, cards[pos + 1])
      table.insert(tmpTable1, cards[pos + 2])
      table.insert(tmpTable1, cards[pos + 3])
      tmppos = pos
    end
  end
   -- 再得到帶的牌
  for k,v in pairs(cards) do
    if v ~= cards[tmppos] then
      table.insert(tmpTable2, v)
    end
  end
  if CardUtils.isBomb(tmpTable1) then
    if 2 == #tmpTable2 then
      return true
    elseif 4 == #tmpTable2 then
      table.sort(tmpTable2)
      if tmpTable2[1] == tmpTable2[2] and tmpTable2[3] == tmpTable2[4] then
        return true
      end
    end
  end

  return false
end

-- 飛機帶翅膀
function isAircraftWing(cards)
  if not CardUtils.isCards(cards) or 8 > #cards  then 
      return false
  end 
  if (#cards % 4) ~=0 and (#cards % 5) ~= 0 then
    return false
  end
  -- 先判斷有沒有炸彈插成三帶一的情況如果有那麼將其中一個替換為撲克中沒有的數(如 19)
  table.sort(cards)
  local tmp = 0 --記錄有幾個炸彈 防止有多個炸插成三帶一
  for k = 1, (#cards - 4) do
    if cards[k] == cards[k + 1] and cards[k + 1] == cards[k + 2] and cards[k + 2] == cards[k + 3] then
      cards[k + 3] = 19 + tmp
      tmp = tmp + 1
    end
  end

  local aircraftCount = math.floor(#cards / 4)
  table.sort(cards)
  local tmpTable1 = {} --存放飛機的牌
  local tmpTable2 = {}  --存放飛機帶的牌
  -- 先從牌中抽出飛機不帶
  for pos = 1, #cards - 2 do
    if cards[pos] == cards[pos + 1] and cards[pos] == cards[pos + 2] then
      table.insert(tmpTable1, cards[pos])
      table.insert(tmpTable1, cards[pos + 1])
      table.insert(tmpTable1, cards[pos + 2])
      tmppos = pos
    end
  end 
   -- 再得到帶的牌
  for k1, v1 in pairs(cards) do
    local count = 0
    for i = 1, aircraftCount do
      if v1 == tmpTable1[i * 3] then
        count = count + 1
      end
    end
    if  count == 0 then
        table.insert(tmpTable2, v1)
    end 
  end

  if not CardUtils.isAircraft(tmpTable1) then
    return false
  end
  if #tmpTable2 == aircraftCount * 2 then
    for i = 1, #tmpTable2, 2 do
      if tmpTable2[i] ~= tmpTable2[i + 1] then
        return false
      end
    end
  end

  return true
end
function getType(postcards)
  --如果傳遞進來的cards沒有去掉花色的話就先去掉花色( %100 )再判斷
  local cards = CardUtils.copyTab(postcards)
  for i = 1, #cards do
    cards[i] = CardUtils.getValue(cards[i])
  end
  local len = #cards
  if len <= 5 and len > 0 then
    if CardUtils.isSingle(cards) then 
      return SINGLE_CARD
    elseif CardUtils.isDouble(cards) then
      return DOUBLE_CARD 
    elseif CardUtils.isBomb(cards) then
      return BOMB_CARD 
    elseif CardUtils.isKingBomb(cards) then
      return KINGBOMB_CARD 
    elseif CardUtils.isThree(cards) then
      return THREE_CARD 
    elseif CardUtils.isThreeOne(cards) then
      return THREE_ONE_CARD 
    elseif CardUtils.isConnect(cards) then
      return CONNECT_CARD 
    elseif CardUtils.isThreeTwo(cards) then
      return THREE_TWO_CARD 
    end
  elseif len < 20 and len > 5 then 
    if CardUtils.isConnect(cards) then
      return CONNECT_CARD 
    elseif CardUtils.isAircraft(cards) then
      return AIRCRAFT_CARD 
    elseif CardUtils.isCompany(cards) then
      return COMPANY_CARD 
    elseif CardUtils.isBombTwo(cards) then
      return BOMB_TWO_CARD 
    elseif CardUtils.isAircraftWing(cards) then
      return AIRCRAFT_WING
    end
  end
  return ERROR_CARDS
end