用一千多行Java代码完整实现斗地主游戏

2 篇文章 0 订阅
1 篇文章 0 订阅

1. 前言

        之前写了一片文章Java实现斗地主?原来如此简单(页面效果版),主要是实现了斗地主游戏发牌的效果,项目比较简单,没有任何游戏逻辑上的判断和验证。这次直接完整实现了斗地主游戏,满足斗地主游戏的基本需求,包括:玩家准备、抢地主、出牌、牌规则验证、出牌验证等,核心代码一共一千多行,项目运行之后就可以正常游戏,与小伙伴们用自研的项目玩游戏,想想都不错,哈哈哈。后端使用的技术栈是Springboot+SpringCache+Websocket,项目中运用了Java基础及面向对象的各类技术,类、接口、对象、枚举、集合、Map、数组、排序、算法、缓存等都有使用…前端使用的是Thymeleaf+原生的js/jquery,接下来就一起来看一看吧!文章结尾处有项目源码地址、游戏录屏视频

2. 项目说明

1. 单牌定义

        斗地主的规则在这里就不多说了,项目中首先要准备一副扑克牌(体现在Java代码中就是一个集合,包含54个对象),每个对象(名称)的命名方式为【花色-牌面】,其中1234分别代表♠4个花色,A~K代表13个牌面,例如红桃6就是【2-6】、黑桃7就是【1-7】、大王表示为【0-L】、小王表示为【0-S】

2. 牌型定义

        牌型整理,通过枚举类来整理,一共整理了37种牌型,不知道有没有漏的,程序中目前就集成了这么多,枚举中包括两个字段,分别是牌名及牌数量,枚举类如下:

/**
 * 定义枚举用于存放各类牌型
 */
public enum PokerEnum {
    A("单牌", 1),
    AA("对子", 2),
    AAA("3不带", 3),
    AAA_B("3带1", 4),
    AAA_BB("3带2", 5),
    AAAA("炸弹", 4),
    SL("王炸",2),
    A_B_C_D_E_5("顺子5",5),
    A_B_C_D_E_6("顺子6",6),
    A_B_C_D_E_7("顺子7",7),
    A_B_C_D_E_8("顺子8",8),
    A_B_C_D_E_9("顺子9",9),
    A_B_C_D_E_10("顺子10",10),
    A_B_C_D_E_11("顺子11",11),
    A_B_C_D_E_12("顺子12",12),
    AA_BB_CC_3("3连对",6),
    AA_BB_CC_4("4连对",8),
    AA_BB_CC_5("5连对",10),
    AA_BB_CC_6("6连对",12),
    AA_BB_CC_7("7连对",14),
    AA_BB_CC_8("8连对",16),
    AA_BB_CC_9("9连对",18),
    AA_BB_CC_10("10连对",20),
    AAA_BBB_2("飞机不带",6),
    AAA_BBB_3("3连飞机不带",9),
    AAA_BBB_4("4连飞机不带",12),
    AAA_BBB_5("5连飞机不带",15),
    AAA_BBB_6("6连飞机不带",18),
    AAA_BBB_C_D_2("飞机带1",8),
    AAA_BBB_C_D_3("3连飞机带1",12),
    AAA_BBB_C_D_4("4连飞机带1",16),
    AAA_BBB_C_D_5("5连飞机带1",20),
    AAA_BBB_CC_DD_2("飞机带2",10),
    AAA_BBB_CC_DD_3("3连飞机带2",15),
    AAA_BBB_CC_DD_4("4连飞机带2",20),
    AAAA_B_C("4带2",6),
    AAAA_BB_CC("4带2对",8),
    ;

    private String name;
    private int num;
    PokerEnum(String name, int num){
        this.name = name;
        this.num = num;
    }

    public int getNum() {
        return num;
    }

    public String getName() {
        return name;
    }
}

3. 程序规则设计

        预先准备三个玩家,分别是玩家A、玩家B、玩家C,三个玩家都准备好之后,由某一个玩家抢地主,然后按序出牌、牌规则验证(验证是否为合理的牌型)、出牌验证(出牌比大小)等,优先出牌结束的玩家获胜

4. 技术栈说明

后端:Java、面向对象、Springboot、SpringCache、ConcurrentHashMap、Websocket

核心代码使用一千多行Java代码,使用Springboot作为项目框架,项目中运用了Java基础及面向对象的各类技术,类、接口、对象、枚举、集合、Map、数组、排序、算法、缓存等都有使用,各家牌、出牌记录、地主、出牌轮次等关键信息全部存储到SpringCache中,轻量级无DB交互。接入Websocket,牌型发生变化实时推送到前端页面中

前端:Thymeleaf、h5、js、jquery、css、Websocket

使用原生的h5、js、jquery实现前端页面的简单渲染,非专职前端,所以页面效果一般,哈哈哈。使用Thymeleaf作为模板引擎渲染前端,Websocket监听后端推送的地址,业务实现前端效果的各类交互

3. 核心算法

1. 牌型验证

        按照牌数量进行验证,验证的结果信息进行枚举匹配,然后返回构造的对象(包括枚举信息及最大值),这边只能介绍个大概,就不拆开说了,具体细节还需看代码逻辑一一消化了,示例代码如下:

	/**
     * 根据牌集合匹配牌对应枚举(验证牌属性)
     * @param pokerNames 牌集合
     * @return
     */
    public static PokerEnumVo findEnumByPokers(List<String> pokerNames){
        if(pokerNames == null || pokerNames.size() == 0){
            return null;
        }
        //忽略花色,提取实际的牌面,并排序
        List<String> pokerStrList = pokerNames.stream().map(i -> {
            String j = i.split("-")[1];
            return j;
        }).sorted().collect(Collectors.toList());
        Integer size = pokerStrList.size();
        PokerEnumVo vo = PokerEnumVo.builder().build();
        switch (size) {
            case 1:
                //单牌
                vo.setPokerEnum(findEnumByNum("单牌", 1));
                vo.setMaxInt(pokerValueToInt(pokerStrList.get(0)));
                return vo;
            case 2:
                if (!allEqual(pokerStrList)) {
                    //2个值不一致,如果包括大小王,则为王炸,否则为非常规牌型
                    if (pokerStrList.contains("S") && pokerStrList.contains("L")) {
                        vo.setPokerEnum(findEnumByNum("王炸", 2));
                        vo.setMaxInt(20);
                        return vo;
                    } else {
                        return null;
                    }
                }
                //对子
                vo.setPokerEnum(findEnumByNum("对子", 2));
                vo.setMaxInt(pokerValueToInt(pokerStrList.get(0)));
                return vo;
            case 3:
                if (!allEqual(pokerStrList)) {
                    //3个值不一致,为非常规牌型
                    return null;
                }
                vo.setPokerEnum(findEnumByNum("3不带", 3));
                vo.setMaxInt(pokerValueToInt(pokerStrList.get(0)));
                return vo;
            case 4:
                if (!allEqual(pokerStrList)) {
                    //4个值不一致,验证是否为3带1,否则为非常规牌型
                    List<NumValue> numValues = arrangeNumValue(pokerStrList);
                    if (numValues.size() == 2 && numValues.get(0).getNum() == 3) {
                        vo.setPokerEnum(findEnumByNum("3带1", 4));
                        vo.setMaxInt(pokerValueToInt(numValues.get(0).getValue()));
                        return vo;
                    }
                    return null;
                }
                vo.setPokerEnum(findEnumByNum("炸弹", 4));
                vo.setMaxInt(pokerValueToInt(pokerStrList.get(0)));
                return vo;
            case 5:
                List<NumValue> numValues5 = arrangeNumValue(pokerStrList);
                if (numValues5.size() == 2) {
                    if (numValues5.get(0).getNum() == 3) {
                        vo.setPokerEnum(findEnumByNum("3带2", 5));
                        vo.setMaxInt(pokerValueToInt(numValues5.get(0).getValue()));
                        return vo;
                    }
                }
                if (numValues5.size() == 5 && !pokerStrList.contains("S") && !pokerStrList.contains("L")) {
                    ChainFlag chain = isChain(pokerStrList);
                    if (chain.isFlag()) {
                        vo.setPokerEnum(findEnumByNum("顺子5", 5));
                        vo.setMaxInt(chain.getMaxInt());
                        return vo;
                    }
                }
                return null;
            case 6:
                List<NumValue> numValues6 = arrangeNumValue(pokerStrList);
                if (numValues6.size() == 6 && !pokerStrList.contains("S") && !pokerStrList.contains("L")) {
                    ChainFlag chain = isChain(pokerStrList);
                    if (chain.isFlag()) {
                        vo.setPokerEnum(findEnumByNum("顺子6", 6));
                        vo.setMaxInt(chain.getMaxInt());
                        return vo;
                    }
                }
                List<String> singleValue6 = numValues6.stream().map(i -> i.getValue()).collect(Collectors.toList());
                if (numValues6.size() == 3) {
                    if (numValues6.get(0).getNum() == 2 && numValues6.get(1).getNum() == 2) {
                        ChainFlag chain = isChain(singleValue6);
                        if (chain.isFlag()) {
                            vo.setPokerEnum(findEnumByNum("3连对", 6));
                            vo.setMaxInt(chain.getMaxInt());
                            return vo;
                        }
                    }
                }
                if (numValues6.size() == 2 && numValues6.get(0).getNum() == 3) {
                    ChainFlag chain = isChain(singleValue6);
                    if (chain.isFlag()) {
                        vo.setPokerEnum(findEnumByNum("飞机不带", 6));
                        vo.setMaxInt(chain.getMaxInt());
                        return vo;
                    }
                }
                if (numValues6.size() == 3 || numValues6.size() == 2) {
                    if (numValues6.get(0).getNum() == 4) {
                        vo.setPokerEnum(findEnumByNum("4带2", 6));
                        vo.setMaxInt(pokerValueToInt(numValues6.get(0).getValue()));
                        return vo;
                    }
                }
                return null;
            case 7:
                List<NumValue> numValues7 = arrangeNumValue(pokerStrList);
                if (numValues7.size() == 7 && !pokerStrList.contains("S") && !pokerStrList.contains("L")) {
                    ChainFlag chain = isChain(pokerStrList);
                    if (chain.isFlag()) {
                        vo.setPokerEnum(findEnumByNum("顺子7", 7));
                        vo.setMaxInt(chain.getMaxInt());
                        return vo;
                    }
                }
                return null;
            case 8:
                List<NumValue> numValues8 = arrangeNumValue(pokerStrList);
                if (numValues8.size() == 8 && !pokerStrList.contains("S") && !pokerStrList.contains("L")) {
                    ChainFlag chain = isChain(pokerStrList);
                    if (chain.isFlag()) {
                        vo.setPokerEnum(findEnumByNum("顺子8", 8));
                        vo.setMaxInt(chain.getMaxInt());
                        return vo;
                    }
                }
                List<String> singleValue8 = numValues8.stream().map(i -> i.getValue()).collect(Collectors.toList());
                if (numValues8.size() == 4) {
                    if (numValues8.get(0).getNum() == 2 && numValues8.get(1).getNum() == 2 && numValues8.get(2).getNum() == 2) {
                        ChainFlag chain = isChain(singleValue8);
                        if (chain.isFlag()) {
                            vo.setPokerEnum(findEnumByNum("4连对", 8));
                            vo.setMaxInt(chain.getMaxInt());
                            return vo;
                        }
                    }
                }
                if (numValues8.size() == 4 || numValues8.size() == 3) {
                    if (numValues8.get(0).getNum() == 3 && numValues8.get(1).getNum() == 3) {
                        List<String> strings = singleValue8.subList(0, 2);
                        ChainFlag chain = isChain(strings);
                        if (chain.isFlag()) {
                            vo.setPokerEnum(findEnumByNum("飞机带1", 8));
                            vo.setMaxInt(chain.getMaxInt());
                            return vo;
                        }
                    }
                }
                if (numValues8.size() == 3) {
                    if (numValues8.get(0).getNum() == 4 && numValues8.get(1).getNum() == 2) {
                        //AAAA_BB_CC
                        vo.setPokerEnum(findEnumByNum("4带2对", 8));
                        vo.setMaxInt(pokerValueToInt(numValues8.get(0).getValue()));
                        return vo;
                    }
                }
                if (numValues8.size() == 2) {
                    if (numValues8.get(0).getNum() == 4) {
                        //AAAA_BB_BB
                        vo.setPokerEnum(findEnumByNum("4带2对", 8));
                        vo.setMaxInt(pokerValueToInt(numValues8.get(0).getValue()));
                        return vo;
                    }
                }
                return null;
            case 9:
                List<NumValue> numValues9 = arrangeNumValue(pokerStrList);
                if (numValues9.size() == 9 && !pokerStrList.contains("S") && !pokerStrList.contains("L")) {
                    ChainFlag chain = isChain(pokerStrList);
                    if (chain.isFlag()) {
                        vo.setPokerEnum(findEnumByNum("顺子9", 9));
                        vo.setMaxInt(chain.getMaxInt());
                        return vo;
                    }
                }
                List<String> singleValue9 = numValues9.stream().map(i -> i.getValue()).collect(Collectors.toList());
                if (singleValue9.size() == 3) {
                    if (numValues9.get(0).getNum() == 3 && numValues9.get(1).getNum() == 3) {
                        ChainFlag chain = isChain(singleValue9);
                        if (chain.isFlag()) {
                            vo.setPokerEnum(findEnumByNum("3连飞机不带", 9));
                            vo.setMaxInt(chain.getMaxInt());
                            return vo;
                        }
                    }
                }
                return null;
            case 10:
                List<NumValue> numValues10 = arrangeNumValue(pokerStrList);
                if (numValues10.size() == 10 && !pokerStrList.contains("S") && !pokerStrList.contains("L")) {
                    ChainFlag chain = isChain(pokerStrList);
                    if (chain.isFlag()) {
                        vo.setPokerEnum(findEnumByNum("顺子10", 10));
                        vo.setMaxInt(chain.getMaxInt());
                        return vo;
                    }
                }
                List<String> singleValue10 = numValues10.stream().map(i -> i.getValue()).collect(Collectors.toList());
                if (numValues10.size() == 5) {
                    if (numValues10.get(0).getNum() == 2 && numValues10.get(1).getNum() == 2 && numValues10.get(2).getNum() == 2 && numValues10.get(3).getNum() == 2) {
                        ChainFlag chain = isChain(singleValue10);
                        if (chain.isFlag()) {
                            vo.setPokerEnum(findEnumByNum("5连对", 10));
                            vo.setMaxInt(chain.getMaxInt());
                            return vo;
                        }
                    }
                }
                if (singleValue10.size() == 4) {
                    if (numValues10.get(0).getNum() == 3 && numValues10.get(1).getNum() == 3 && numValues10.get(2).getNum() == 2) {
                        List<String> strings = singleValue10.subList(0, 2);
                        ChainFlag chain = isChain(strings);
                        if (chain.isFlag()) {
                            vo.setPokerEnum(findEnumByNum("飞机带2", 10));
                            vo.setMaxInt(chain.getMaxInt());
                            return vo;
                        }
                    }
                }
                return null;
            case 11:
                List<NumValue> numValues11 = arrangeNumValue(pokerStrList);
                if (numValues11.size() == 11 && !pokerStrList.contains("S") && !pokerStrList.contains("L")) {
                    ChainFlag chain = isChain(pokerStrList);
                    if (chain.isFlag()) {
                        vo.setPokerEnum(findEnumByNum("顺子11", 11));
                        vo.setMaxInt(chain.getMaxInt());
                        return vo;
                    }
                }
                return null;
            case 12:
                List<NumValue> numValues12 = arrangeNumValue(pokerStrList);
                if (numValues12.size() == 12 && !pokerStrList.contains("S") && !pokerStrList.contains("L")) {
                    ChainFlag chain = isChain(pokerStrList);
                    if (chain.isFlag()) {
                        vo.setPokerEnum(findEnumByNum("顺子12", 12));
                        vo.setMaxInt(chain.getMaxInt());
                        return vo;
                    }
                }
                List<String> singleValue12 = numValues12.stream().map(i -> i.getValue()).collect(Collectors.toList());
                if (numValues12.size() == 6) {
                    if (numValues12.get(0).getNum() == 2 && numValues12.get(1).getNum() == 2 && numValues12.get(2).getNum() == 2
                            && numValues12.get(3).getNum() == 2 && numValues12.get(4).getNum() == 2) {
                        ChainFlag chain = isChain(singleValue12);
                        if (chain.isFlag()) {
                            vo.setPokerEnum(findEnumByNum("6连对", 12));
                            vo.setMaxInt(chain.getMaxInt());
                            return vo;
                        }
                    }
                }
                if (singleValue12.size() == 4) {
                    if (numValues12.get(0).getNum() == 3 && numValues12.get(1).getNum() == 3 && numValues12.get(2).getNum() == 3) {
                        ChainFlag chain = isChain(singleValue12);
                        if (chain.isFlag()) {
                            vo.setPokerEnum(findEnumByNum("4连飞机不带", 12));
                            vo.setMaxInt(chain.getMaxInt());
                            return vo;
                        }
                        ChainFlag chainLeft = isChainLeft(singleValue12, 1);
                        if (chainLeft.isFlag()) {
                            //3连飞机+AAA
                            vo.setPokerEnum(findEnumByNum("3连飞机带1", 12));
                            vo.setMaxInt(chainLeft.getMaxInt());
                            return vo;
                        }
                        ChainFlag chainRight = isChainRight(singleValue12, 1);
                        if (chainRight.isFlag()) {
                            //AAA+3连飞机
                            vo.setPokerEnum(findEnumByNum("3连飞机带1", 12));
                            vo.setMaxInt(chainRight.getMaxInt());
                            return vo;
                        }
                    }
                }
                if (numValues12.size() == 6 || numValues12.size() == 5) {
                    if (numValues12.get(0).getNum() == 3 && numValues12.get(1).getNum() == 3 && numValues12.get(2).getNum() == 3) {
                        List<String> strings = singleValue12.subList(0, 3);
                        ChainFlag chain = isChain(strings);
                        if (chain.isFlag()) {
                            vo.setPokerEnum(findEnumByNum("3连飞机带1", 12));
                            vo.setMaxInt(chain.getMaxInt());
                            return vo;
                        }
                    }
                }
                return null;
            case 14:
                List<NumValue> numValues14 = arrangeNumValue(pokerStrList);
                if (numValues14.size() == 7) {
                    if (numValues14.get(0).getNum() == 2 && numValues14.get(1).getNum() == 2 && numValues14.get(2).getNum() == 2
                            && numValues14.get(3).getNum() == 2 && numValues14.get(4).getNum() == 2 && numValues14.get(5).getNum() == 2) {
                        List<String> singleValue14 = numValues14.stream().map(i -> i.getValue()).collect(Collectors.toList());
                        ChainFlag chain = isChain(singleValue14);
                        if (chain.isFlag()) {
                            vo.setPokerEnum(findEnumByNum("7连对", 14));
                            vo.setMaxInt(chain.getMaxInt());
                            return vo;
                        }
                    }
                }
                return null;
            case 15:
                List<NumValue> numValues15 = arrangeNumValue(pokerStrList);
                List<String> singleValue15 = numValues15.stream().map(i -> i.getValue()).collect(Collectors.toList());
                if (numValues15.size() == 5) {
                    if (numValues15.get(0).getNum() == 3 && numValues15.get(1).getNum() == 3 && numValues15.get(2).getNum() == 3 && numValues15.get(3).getNum() == 3) {
                        ChainFlag chain = isChain(singleValue15);
                        if (chain.isFlag()) {
                            vo.setPokerEnum(findEnumByNum("5连飞机不带", 15));
                            vo.setMaxInt(chain.getMaxInt());
                            return vo;
                        }
                    }
                }
                if (numValues15.size() == 6) {
                    if (numValues15.get(0).getNum() == 3 && numValues15.get(1).getNum() == 3 && numValues15.get(2).getNum() == 3
                            && numValues15.get(3).getNum() == 2 && numValues15.get(4).getNum() == 2) {
                        List<String> strings = singleValue15.subList(0, 3);
                        ChainFlag chain = isChain(strings);
                        if (chain.isFlag()) {
                            vo.setPokerEnum(findEnumByNum("3连飞机带2", 15));
                            vo.setMaxInt(chain.getMaxInt());
                            return vo;
                        }
                    }
                }
                return null;
            case 16:
                List<NumValue> numValues16 = arrangeNumValue(pokerStrList);
                List<String> singleValue16 = numValues16.stream().map(i -> i.getValue()).collect(Collectors.toList());
                if (numValues16.size() == 8) {
                    if (numValues16.get(0).getNum() == 2 && numValues16.get(1).getNum() == 2 && numValues16.get(2).getNum() == 2
                            && numValues16.get(3).getNum() == 2 && numValues16.get(4).getNum() == 2 && numValues16.get(5).getNum() == 2
                            && numValues16.get(6).getNum() == 2) {
                        ChainFlag chain = isChain(singleValue16);
                        if (chain.isFlag()) {
                            vo.setPokerEnum(findEnumByNum("8连对", 16));
                            vo.setMaxInt(chain.getMaxInt());
                            return vo;
                        }
                    }
                }
                if (numValues16.size() == 5) {
                    if (numValues16.get(0).getNum() == 4 && numValues16.get(1).getNum() == 3 && numValues16.get(2).getNum() == 3 && numValues16.get(3).getNum() == 3) {
                        List<String> strings = singleValue16.subList(1, 5);
                        ChainFlag chain = isChain(strings);
                        if (chain.isFlag()) {
                            //4连飞机+AAAA
                            vo.setPokerEnum(findEnumByNum("4连飞机带1", 16));
                            vo.setMaxInt(chain.getMaxInt());
                            return vo;
                        }
                    }
                }
                if (numValues16.size() >= 6 && numValues16.size() <= 8) {
                    if (numValues16.get(0).getNum() == 3 && numValues16.get(1).getNum() == 3 && numValues16.get(2).getNum() == 3 && numValues16.get(3).getNum() == 3) {
                        if (numValues16.size() == 8 || numValues16.size() == 7) {
                            List<String> strings = singleValue16.subList(0, 4);
                            ChainFlag chain = isChain(strings);
                            if (chain.isFlag()) {
                                //4连飞机+A+B+C+D 或 4连飞机+AA+B+C
                                vo.setPokerEnum(findEnumByNum("4连飞机带1", 16));
                                vo.setMaxInt(chain.getMaxInt());
                                return vo;
                            }
                        }
                        if (numValues16.size() == 6) {
                            if (numValues16.get(4).getNum() == 2) {
                                List<String> strings = singleValue16.subList(0, 4);
                                ChainFlag chain = isChain(strings);
                                if (chain.isFlag()) {
                                    //4连飞机+AA+BB
                                    vo.setPokerEnum(findEnumByNum("4连飞机带1", 16));
                                    vo.setMaxInt(chain.getMaxInt());
                                    return vo;
                                }
                            }
                            if (numValues16.get(4).getNum() == 3) {
                                List<String> strings = singleValue16.subList(0, 5);
                                ChainFlag chainLeft = isChainLeft(strings, 1);
                                if (chainLeft.isFlag()) {
                                    //4连飞机+AAA+B
                                    vo.setPokerEnum(findEnumByNum("4连飞机带1", 16));
                                    vo.setMaxInt(chainLeft.getMaxInt());
                                    return vo;
                                }
                                ChainFlag chainRight = isChainRight(strings, 1);
                                if (chainRight.isFlag()) {
                                    //AAA+B+4连飞机
                                    vo.setPokerEnum(findEnumByNum("4连飞机带1", 16));
                                    vo.setMaxInt(chainRight.getMaxInt());
                                    return vo;
                                }
                            }
                        }
                    }
                }
                return null;
            case 18:
                List<NumValue> numValues18 = arrangeNumValue(pokerStrList);
                List<String> singleValue18 = numValues18.stream().map(i -> i.getValue()).collect(Collectors.toList());
                if (numValues18.size() == 9) {
                    if (numValues18.get(0).getNum() == 2 && numValues18.get(1).getNum() == 2 && numValues18.get(2).getNum() == 2
                            && numValues18.get(3).getNum() == 2 && numValues18.get(4).getNum() == 2 && numValues18.get(5).getNum() == 2
                            && numValues18.get(6).getNum() == 2 && numValues18.get(7).getNum() == 2) {
                        ChainFlag chain = isChain(singleValue18);
                        if (chain.isFlag()) {
                            vo.setPokerEnum(findEnumByNum("9连对", 18));
                            vo.setMaxInt(chain.getMaxInt());
                            return vo;
                        }
                    }
                }
                if (numValues18.size() == 6) {
                    if (numValues18.get(0).getNum() == 3 && numValues18.get(1).getNum() == 3 && numValues18.get(2).getNum() == 3
                            && numValues18.get(3).getNum() == 3 && numValues18.get(4).getNum() == 3) {
                        ChainFlag chain = isChain(singleValue18);
                        if (chain.isFlag()) {
                            vo.setPokerEnum(findEnumByNum("6连飞机不带", 18));
                            vo.setMaxInt(chain.getMaxInt());
                            return vo;
                        }
                    }
                }
                return null;
            case 20:
                List<NumValue> numValues20 = arrangeNumValue(pokerStrList);
                List<String> singleValue20 = numValues20.stream().map(i -> i.getValue()).collect(Collectors.toList());
                if (numValues20.size() == 10) {
                    if (numValues20.get(0).getNum() == 2 && numValues20.get(1).getNum() == 2 && numValues20.get(2).getNum() == 2
                            && numValues20.get(3).getNum() == 2 && numValues20.get(4).getNum() == 2 && numValues20.get(5).getNum() == 2
                            && numValues20.get(6).getNum() == 2 && numValues20.get(7).getNum() == 2 && numValues20.get(8).getNum() == 2) {
                        ChainFlag chain = isChain(singleValue20);
                        if (chain.isFlag()) {
                            vo.setPokerEnum(findEnumByNum("10连对", 20));
                            vo.setMaxInt(chain.getMaxInt());
                            return vo;
                        }
                    }
                }
                if (numValues20.size() == 7) {
                    if (numValues20.get(0).getNum() == 4 && numValues20.get(1).getNum() == 3 && numValues20.get(2).getNum() == 3
                            && numValues20.get(3).getNum() == 3 && numValues20.get(4).getNum() == 3 && numValues20.get(5).getNum() == 3) {
                        List<String> strings = singleValue20.subList(1, 6);
                        ChainFlag chain = isChain(strings);
                        if (chain.isFlag()) {
                            //5连飞机+AAAA+B
                            vo.setPokerEnum(findEnumByNum("5连飞机带1", 20));
                            vo.setMaxInt(chain.getMaxInt());
                            return vo;
                        }
                    }
                }
                if (numValues20.size() >= 7 && numValues20.size() <= 10) {
                    if (numValues20.get(0).getNum() == 3 && numValues20.get(1).getNum() == 3 && numValues20.get(2).getNum() == 3
                            && numValues20.get(3).getNum() == 3 && numValues20.get(4).getNum() == 3) {
                        if (numValues20.get(5).getNum() == 3) {
                            List<String> strings = singleValue20.subList(0, 6);
                            ChainFlag chainLeft = isChainLeft(strings, 1);
                            if (chainLeft.isFlag()) {
                                //5连飞机+AAA+BB 或 5连飞机+AAA+B+C
                                vo.setPokerEnum(findEnumByNum("5连飞机带1", 20));
                                vo.setMaxInt(chainLeft.getMaxInt());
                                return vo;
                            }
                            ChainFlag chainRight = isChainRight(strings, 1);
                            if (chainRight.isFlag()) {
                                //AAA+5连飞机+BB 或 AAA+5连飞机+B+C
                                vo.setPokerEnum(findEnumByNum("5连飞机带1", 20));
                                vo.setMaxInt(chainRight.getMaxInt());
                                return vo;
                            }
                        } else {
                            List<String> strings = singleValue20.subList(0, 5);
                            ChainFlag chain = isChain(strings);
                            if (chain.isFlag()) {
                                //5连飞机 普通版
                                vo.setPokerEnum(findEnumByNum("5连飞机带1", 20));
                                vo.setMaxInt(chain.getMaxInt());
                                return vo;
                            }
                        }
                    }
                }
                if (numValues20.size() == 6) {
                    if (numValues20.get(0).getNum() == 4 && numValues20.get(1).getNum() == 4 && numValues20.get(2).getNum() == 3
                            && numValues20.get(3).getNum() == 3 && numValues20.get(4).getNum() == 3) {
                        List<String> strings = singleValue20.subList(2, 6);
                        ChainFlag chain = isChain(strings);
                        if (chain.isFlag()) {
                            //AAAA+BBBB+4连飞机
                            vo.setPokerEnum(findEnumByNum("4连飞机带2", 20));
                            vo.setMaxInt(chain.getMaxInt());
                            return vo;
                        }
                    }
                }
                if (numValues20.size() == 7) {
                    if (numValues20.get(0).getNum() == 4 && numValues20.get(1).getNum() == 3 && numValues20.get(2).getNum() == 3
                            && numValues20.get(3).getNum() == 3 && numValues20.get(4).getNum() == 3  && numValues20.get(5).getNum() == 2) {
                        List<String> strings = singleValue20.subList(1, 5);
                        ChainFlag chain = isChain(strings);
                        if (chain.isFlag()) {
                            //AAAA+4连飞机+BB+CC
                            vo.setPokerEnum(findEnumByNum("4连飞机带2", 20));
                            vo.setMaxInt(chain.getMaxInt());
                            return vo;
                        }
                    }
                }
                if (numValues20.size() == 8) {
                    if (numValues20.get(0).getNum() == 3 && numValues20.get(1).getNum() == 3 && numValues20.get(2).getNum() == 3
                            && numValues20.get(3).getNum() == 3 && numValues20.get(4).getNum() == 2  && numValues20.get(5).getNum() == 2
                            && numValues20.get(6).getNum() == 2) {
                        List<String> strings = singleValue20.subList(0, 4);
                        ChainFlag chain = isChain(strings);
                        if (chain.isFlag()) {
                            //4连飞机+AA+BB+CC+DD
                            vo.setPokerEnum(findEnumByNum("4连飞机带2", 20));
                            vo.setMaxInt(chain.getMaxInt());
                            return vo;
                        }
                    }
                }
                return null;
        }
        return null;
    }
    
	/**
     * 根据牌名称和数量匹配枚举
     * @param name 牌名称
     * @param num 数量
     * @return
     */
    public static PokerEnum findEnumByNum(String name, Integer num){
        if(StringUtils.isEmpty(name) || num == null || num == 0){
            return null;
        }
        for (PokerEnum value : PokerEnum.values()) {
            if(name.equals(value.getName()) && num == value.getNum()){
                return value;
            }
        }
        return null;
    }

	/**
     * 验证集合中的字符串是否全部一致
     * @param list
     * @return
     */
    public static boolean allEqual(List<String> list){
        boolean allEqual = true;
        for (int i = 1; i < list.size(); i++) {
            if (!list.get(i).equals(list.get(0))) { // 比较当前元素与第一个元素是否不同
                allEqual = false; // 若存在不同则将allEqual设置为false
                break; // 结束循环
            }
        }
        return allEqual;
    }

    /**
     * 整理集合中的数值规则
     * @param list 排序之后的集合
     * @return NumValue
     */
    public static List<NumValue> arrangeNumValue(List<String> list){
        List<NumValue> numList = new ArrayList<>();
        List<String> tempList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            if (i == 0) { //第一个元素
                tempList.add(list.get(i));
            } else if (i == list.size() - 1) { //最后一个元素
                if (list.get(i).equals(list.get(i-1))) { // 比较当前元素与上一个元素是否相同
                    tempList.add(list.get(i));
                    NumValue numValue = NumValue.builder().num(tempList.size()).value(list.get(i)).build();
                    numList.add(numValue);
                } else {
                    NumValue numValue = NumValue.builder().num(tempList.size()).value(list.get(i-1)).build();
                    numList.add(numValue);
                    NumValue numValueLast = NumValue.builder().num(1).value(list.get(i)).build();
                    numList.add(numValueLast);
                }
            } else {
                if (list.get(i).equals(list.get(i-1))) { // 比较当前元素与上一个元素是否相同
                    tempList.add(list.get(i));
                } else {
                    NumValue numValue = NumValue.builder().num(tempList.size()).value(list.get(i-1)).build();
                    numList.add(numValue);
                    tempList.clear();
                    tempList.add(list.get(i));
                }
            }
        }
        //按照数量降序排序返回
        List<NumValue> collect = numList.stream().sorted(Comparator.comparing(NumValue::getNum, Comparator.reverseOrder()))
                .collect(Collectors.toList());
        return collect;
    }

    /**
     * 验证集合中的字符串是否为顺子
     * @param list
     * @return
     */
    public static ChainFlag isChain(List<String> list) {
        List<Integer> integers = strToIntSort(list);
        return commonVerifyChain(integers);
    }

    /**
     * 验证集合中的字符串是否为顺子(排除左边i个)
     * @param list
     * @param i 集合左边第几个起(下标从0开始)
     * @return
     */
    public static ChainFlag isChainLeft(List<String> list, Integer i) {
        List<Integer> integers = strToIntSort(list).subList(i, list.size());
        return commonVerifyChain(integers);
    }

    /**
     * 验证集合中的字符串是否为顺子(排除右边i个)
     * @param list
     * @param i 集合右边第几个起(下标从0开始)
     * @return
     */
    public static ChainFlag isChainRight(List<String> list, Integer i) {
        List<Integer> integers = strToIntSort(list).subList(0, list.size() - i);
        return commonVerifyChain(integers);
    }

    /**
     * 字符串集合转排序后的Int集合
     * @param list
     * @return
     */
    private static List<Integer> strToIntSort(List<String> list) {
        List<Integer> integers = list.stream().map(i->{
            Integer j;
            switch (i) {
                case "A":
                    j = 14;
                    break;
                case "K":
                    j = 13;
                    break;
                case "Q":
                    j = 12;
                    break;
                case "J":
                    j = 11;
                    break;
                default:
                    j = Integer.valueOf(i);
            }
            return j;
        }).sorted().collect(Collectors.toList());
        return integers;
    }

    /**
     * 验证顺子通用方法
     * @param integers
     * @return
     */
    private static ChainFlag commonVerifyChain(List<Integer> integers) {
        ChainFlag chainFlag = new ChainFlag();
        Integer max = integers.get(integers.size() -1);
        Integer min = integers.get(0);
        chainFlag.setMaxInt(max);
        if (min == 2) {
            chainFlag.setFlag(false);
            return chainFlag;
        }
        if (max - min + 1 == integers.size()) {
            chainFlag.setFlag(true);
            return chainFlag;
        }
        chainFlag.setFlag(false);
        return chainFlag;
    }

    /**
     * 单牌转int值,方便比大小
     * @param pokerName
     * @return
     */
    private static Integer pokerValueToInt(String pokerName) {
        String[] split = pokerName.split("-");
        String s = split.length == 2 ? split[1] : split[0];
        Integer j;
        switch (s) {
            case "L":
                j = 17;
                break;
            case "S":
                j = 16;
                break;
            case "2":
                j = 15;
                break;
            case "A":
                j = 14;
                break;
            case "K":
                j = 13;
                break;
            case "Q":
                j = 12;
                break;
            case "J":
                j = 11;
                break;
            default:
                j = Integer.valueOf(s);
        }
        return j;
    }

3. 牌型比大小

各类排序比大小,比如:单牌比大小、对子比大小、顺子比大小、炸弹比大小等等,其实就是玩游戏的压牌规则,示例代码如下:

	**
     * 比较牌大小
     * @param lastVo 上家牌属性
     * @param currentVo 当前牌属性
     * @return
     */
    public static boolean verifyPokerProperty(PokerEnumVo lastVo, PokerEnumVo currentVo) {
        String lastEnumName = lastVo.getPokerEnum().getName();
        String currentEnumName = currentVo.getPokerEnum().getName();
        if ("王炸".equals(lastEnumName)) {
            return false;
        }
        if ("王炸".equals(currentEnumName)) {
            return true;
        }
        if ("炸弹".equals(lastEnumName) && "炸弹".equals(currentEnumName)) {
            if (lastVo.getMaxInt() < currentVo.getMaxInt()) {
                return true;
            } else {
                return false;
            }
        }
        if ("炸弹".equals(lastEnumName) && !"炸弹".equals(currentEnumName)) {
            return false;
        }
        if (!"炸弹".equals(lastEnumName) && "炸弹".equals(currentEnumName)) {
            return true;
        }
        //炸弹逻辑完成,常规逻辑如下
        //牌型不一致,无法比较
        if (!lastEnumName.equals(currentEnumName)) {
            return false;
        }
        //牌型一致,最大值进行比较
        if (lastVo.getMaxInt() < currentVo.getMaxInt()) {
            return true;
        }
        return false;
    }

4. 效果图示

1. 初始化

在这里插入图片描述

2. 准备发牌

在这里插入图片描述

3. 抢地主

在这里插入图片描述

4. 出牌过程

在这里插入图片描述

5. 源码地址、录屏视频

源码地址:点这里
录屏视频地址:点这里

  • 27
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值