简单的麻将ai算法

简单的麻将ai算法

写一个麻将的小游戏,需要自动出牌的ai算法,自己动手写了一个,虽然不是很聪明,但惊讶于它的简单,就记录一下。用python来实现的。

  1. 先归纳麻将的规则。看似很复杂的麻将规则,可以用一个公式来表示。胡牌 = AA and (AAA or AAAA or ABC)
    AA:是麻将
    AAA:是碰牌
    AAAA:是杠牌
    ABC:是连牌
  2. 牌的表示。用数字来表示麻将牌,如11-19表示一万到九万,31-39表示一条到九条,51-59表示一筒到九筒。为什么条子和筒子之间要隔着10个数字呢,是为了算法的实现。
  3. 判断胡牌。用一个递归函数来判断胡牌。牌cardList要求按牌面的数字大小,从小到大排列。
    # cardList: 是手上的牌,需要从小到大排列
    def match(cardList, majiang=False):
        if len(cardList) == 0 and majiang:
            return True

        rst = False
        # AA
        if not majiang and len(cardList) >= 2 and cardList[0] == cardList[1]:
            list1 = [] + cardList
            list1.pop(0)
            list1.pop(0)
            rst = match(list1, True)

        # AAA
        if not rst and len(cardList) >= 3 and cardList[0] == cardList[1] == cardList[2]:
            list1 = [] + cardList
            list1.pop(0)
            list1.pop(0)
            list1.pop(0)
            rst = match(list1, majiang)

        # AAAA
        if not rst and len(cardList) >= 4 and cardList[0] == cardList[1] == cardList[2] == cardList[3]:
            list1 = [] + cardList
            list1.pop(0)
            list1.pop(0)
            list1.pop(0)
            list1.pop(0)
            rst = match(list1, majiang)

        # ABC
        if not rst and len(cardList) >= 3:
            list1 = []
            a = cardList[0]
            b = False
            c = False
            for i in range(1, len(cardList)):
                if not b and cardList[i] == a + 1:
                    b = True
                elif not c and cardList[i] == a + 2:
                    c = True
                else:
                    list1.append(cardList[i])

            if(b and c):
                rst = match(list1, majiang)

        return rst
  1. 判断出牌。出牌就是要把手上最没用的一张牌打出去。先给手上所有的牌都计算一个分值,得分最低的牌就是最没用的牌。怎么给每张牌计算分值呢?
    如下图,牌面x的分值计算方法。如AAAA这样的牌,得分最高,不会被打掉;如AC这样差一些的牌,得分比较低,被打掉的可能性就增大。
    输入图片说明 不但要计算手上的牌,还要考虑未出现的牌。如手上有AC这样的牌,但未出现的牌中还有比较多的A,B牌。那么凑出AAA或ABC牌的几率加大了,得分也高一些,被打出去的概率也小一些。但是,未出现的牌再多,也比不上手里已经有ABC这样成型的牌来的实际,所以未出现的牌的分值要低一些。比如,手上的牌计100分,那未出现的牌只能计5分。
    para = [10, 2, 1]
    scale = 50
    # cards:手上的牌
    # dark:未出现过的牌
    def cardsScore(cards, dark):
        scores = []
        
        for c in cards:
            score = 0
            for cc in cards:
                gap = abs(cc - c)
                if gap < 3:
                    score += para[gap] * scale
                    
            for cc in dark:
                gap = abs(cc - c)
                if gap < 3:
                    score += para[gap]
                    
            scores.append(score)
            
        return scores
  1. 测试。通过测试,简单几行代码实现的ai算法,还是很容易胡牌的。四个这样的ai对局,95%可以胡牌,有5%会黄,没ai胡牌。可以调整para和scale的值,来提高ai的智力。

猜你喜欢

转载自my.oschina.net/kyle960/blog/1803351
今日推荐