斗地主机器人算法(个人思路整理)

借鉴网上一些参数设置,最后结果和正常人输赢差不多!!!不喜勿喷

 

一、参数设置

1、大小:3、4、5、6、7、8、9、10、J、Q、K、A、2、小王、大王

2、牌基础值:以10为中间值0。向左依次递减,3为-7。向右依次递增,大王为7

4、一轮牌的价值是7

3、牌型值:(非负+7)(一个轮次的值+7)

单张,对,三条(三不带、带1、带2):牌基础值。
单连,对连为最大牌值加1:连牌中最大一张牌的基础值+1。
飞机均为无负价值,最大6:(最大牌的基础值+ 7 + 1)/ 2
四带均为无负价值,最大6:(基础值 + 7) /2
炸弹为基础价值+一个轮次的值:基础值 + 7 + 7
王炸(最大炸弹+1):20

(借鉴的这里)https://blog.csdn.net/sm9sun/article/details/70804909

二、计算当前分值最高的牌型组合

1、找到当前用于计算的手牌coreCard(指哪一种牌,比如黑桃7或者梅花3)。先找四张重复的牌,其次是三张重复的牌,最后是由大到小查找(都是是4张情况下,也是优先大的牌。先找4张和3张是想先把可以带牌的组合放在前面计算,避免出现333没法带A的情况)

2、遍历牌型组合(这里我是用的枚举单张~王炸)。找到以coreCard为最大牌的所有组合类型allCardType。

3、allCardType中计算带牌思路:移除当前已选择好的牌,剩余牌用动态规划查找带牌。

例如:3带1单张,num = 1,waitData  里面的List 每个就是1张单牌

            3带1对子,num = 1,waitData  里面的List 每个就是组对子

    /**
     * 动态规划,实现组合查找
     * @param num  带牌数量
     * @param waitData  可以选择的带牌
     */
    public static List combination(int num, List> waitData) {
        if(waitData != null && waitData.size() >= num){
            List returnData = new LinkedList();
            combination(0,num,new LinkedList(),waitData,returnData);
            return returnData;
        }
        return new LinkedList();
    }

4、比较allCardType里面的每一种选择,选择后剩余手牌价值最大

比较方式:一种选择的价值 + 选择后剩余手牌的价值 - 总共需要的轮次数 * 7

计算剩余价值使用的是回溯法:

        for (DdzRobotCardType cardType : allCardType) {
            String key = cardInfo.getContainsType(cardType);
            //这里是保持了一个副本,用于去除重复计算
            RecursionCardInfo lastInfo = cardInfo.haveChoseType.get(key);
            if(lastInfo == null){
                //剩余牌的价值
                RecursionCardInfo copyCardInfo = cardInfo.clone();
                removeCards(cardType, copyCardInfo);
                //这里是递归调用本方法
                lastInfo = recursionCard(copyCardInfo);
                setMaxValue(lastInfo);
                cardInfo.haveChoseType.put(key,lastInfo);
            }
            //当前牌型,加上剩余牌的牌型
            if (mostCardInfo == null || (lastInfo.getCoompareValue(1) + cardType.cardsValue > mostCardInfo.getCoompareValue(0))) {
                mostCardInfo = lastInfo.choseCardTypes;
            }
        }

https://blog.csdn.net/sm9sun/article/details/70821106

 

三、主动出牌

1、把之前计算好的牌型组合,按照组合类型遍历,找到最优的价值打出去(比较方式:一种选择的价值 + 选择后剩余手牌的价值 - 总共需要的轮次数 * 7)

2、地方一手出完(剩余2张牌或一张牌):优先打其他牌型,只有相同牌型情况下由大打到小。

3、队友报单或报对子:手牌小于10的单张或对子优先打出去。

4、手牌是打牌类型+1其他牌型:优先打大牌类型(由小到大),最后打小牌类型。(大牌类型:价值>= 2的基础价值)

5、下家是庄家:出单张和对子,优先出10基础价值以上价值的牌(只是添加了牌的价值,并不是一定会打出)

 

 

你可能感兴趣的:(java,算法)