斗地主算法(1)

来源:互联网 发布:淘宝店铺授权凭证 编辑:程序博客网 时间:2024/05/06 02:22

现在在公司实习用quick-coco2dx引擎写了斗地主,所有代码用lua脚本实现。我把算法封装成了一个lua类(CardUtils)所有代码可以直接拿来使用。

首先先弄清楚有那些牌型:

火箭or王炸:即双王(大王和小王),最大的牌。

        炸弹:四张同数值牌(如四个 7 )。

        单牌:单个牌(如红桃 5 )。

        对牌:数值相同的两张牌(如梅花 4+ 方块 4 )。

        三张牌:数值相同的三张牌(如三个 J )。

        三带一:数值相同的三张牌 + 一张单牌或一对牌。例如: 333+6 或 444+99 

        单顺:五张或更多的连续单牌(如: 45678 或 78910JQK )。不包括 2 点和双王。

        双顺:三对或更多的连续对牌(如: 334455 、 7788991010JJ )。不包括 2 点和双王。 

       三顺:二个或更多的连续三张牌(如: 333444 、 555666777888 )。不包括 2 点和双王。

        飞机带翅膀:三顺+同数量的单牌(或同数量的对牌)。 

        如: 444555+79 或 333444555+7799JJ 

        四带二:四张牌+两手牌。(注意:四带二不是炸弹)。

  如: 5555 + 3 + 8 或 4444 + 55 + 77 。

这里我按照牌型的大小定义了一些变量方便在以后代码中使用

----各种牌型的对应数字ERROR_CARDS = 0 --错误牌型SINGLE_CARD = 1 --单牌  DOUBLE_CARD = 2 --对子  THREE_CARD = 3 --3不带  THREE_ONE_CARD = 4 --3带1  THREE_TWO_CARD = 5 --3带2  BOMB_TWO_CARD = 6 --四个带2张单牌  BOMB_FOUR_CARD = 7 --四个带2对  CONNECT_CARD = 8 --连牌  COMPANY_CARD = 9 --连队  AIRCRAFT_CARD = 10 --飞机不带  AIRCRAFT_WING = 11 --飞机带单牌或对子BOMB_CARD = 12 --炸弹  KINGBOMB_CARD = 13 --王炸
先来定义数字代表扑克中的牌的规则
我用3到13代表扑克中的3到K,再用14代表A,15 代表 2 (这样在以后的牌型判断和比较的时候方便)。花色用百位来表示(如方块3就是103,黑桃2就是415),大小王是116,117。

先写两个方法得到数字代表的牌值和花色

--获得扑克牌的牌值function getValue(card)  return card % 100end--获得扑克牌的花色function getSuit(card)  return card / 100end
在写一个方法判断数字是否是牌(有时候传进来的数字可能去掉了花色)

--测试所有的牌是否都是扑克牌function isCards(cards)  for k,c in pairs(cards) do    if c < 100 then      if  3 > c or  17 < c then        return false      end    else       if getValue(c) > 17 or getValue(c) < 3 then        return false      end    end  end  return trueend

接下来就是牌型判断了先判断几个容易的牌型(牌数小于5的)

把所有的代表牌的数字放在一个table中传进去得到一个牌值的table

function getCardsTabValue(cards)  local tmp = {}  for k, v in pairs(cards or {}) do        if type(v) ~= "table" then            tmp[k] = v % 100        else            tmp[k] = CardUtils.getCardsTabValue(v)        end    end  return tmp end

注意下面所有的判断都是先将数字去掉花色之后的判断

-- 单牌function isSingle(cards)  if not CardUtils.isCards(cards)then       return false  end  if 1 == #cards then    return true  end  return falseend--对子function isDouble(cards)  if not CardUtils.isCards(cards) then       return false  end  if 2 == #cards then    if cards[1] == cards[2] then        return true     end  end  return falseend--王炸function isKingBomb(cards)  if not CardUtils.isCards(cards) or 2 ~= #cards then       return false  end  table.sort(cards)  if cards[1] == 16 and cards[2] == 17 then    return true  end  return falseend--3不带 只要判断三个牌值相等function isThree(cards)  if not CardUtils.isCards(cards) or 3 ~= #cards then       return false  end  if cards[1] == cards[2] and cards[1] == cards[3] then      return true   end  return falseend--3带1 先对数字排序 再判断带的牌是在那个位置 (4446,3444)再将带的牌移除判断剩下的三个牌是不是 3不带function isThreeOne(cards)  if not CardUtils.isCards(cards) or 4 ~= #cards then       return false  end  table.sort(cards)  if cards[1] ~=cards[2] then    table.remove(cards, 1)  else     table.remove(cards, 4)  end  if isThree(cards)  then    return true  end  return falseend--3带对子  先排序 头尾都是对子而且中间的牌等于头或者尾的值(55577,44555)function isThreeTwo( cards )  if not CardUtils.isCards(cards) or 5 ~= #cards then       return false  end  table.sort(cards)  if cards[1] == cards[2] and cards[4] == cards[5] then    if cards[3] == cards[2] or cards[3] == cards[4] then      return true    end  end  return falseend--炸弹function isBomb( cards )  if not CardUtils.isCards(cards) or 4 ~= #cards then       return false  end  if cards[1] == cards[2] and cards[2] == cards[3] and cards[3] == cards[4] then    return true  end  return falseend




0 0