java摸鱼小游戏之斗地主(二)


简介:
本篇内容接上篇,主要介绍主题的运行逻辑,这里先一段一段写,最后附上整个主题类
下一篇介绍判断工具类
最后介绍ai的思维类

二。主题

1.游戏开始,生成桌面信息(生产扑克牌,生成玩家登)

(1)先是准备桌面信息

这里没逻辑,一堆new set

TableTopInformation tableTopInformation = new TableTopInformation();
        Scanner sc = new Scanner(System.in);


//        List<Poker> poker = getPoker();
//        tableTopInformation.setPoker(poker);


        /**
         * key 玩家名称
         * value 玩家对应的牌
         */
        Map<String,List<Poker>> map = new HashMap<>(3);
        tableTopInformation.setPlayerPokerMap(map);

        /**
         * key 玩家名
         * value 是否显示该玩家的手牌
         */
        Map<String,Boolean> mapSB = new HashMap<>(3);
        tableTopInformation.setMapSB(mapSB);

        /**
         * key 玩家名
         * value 玩家对于的电脑ai
         */
        Map<String,Ai> aiMap = new HashMap<>();
        tableTopInformation.setAiMap(aiMap);

        List<Player> playerList = new ArrayList<>();
        tableTopInformation.setPlayerList(playerList);

        Map<String,Integer> troopsMap = new HashMap<>();
        tableTopInformation.setTroopsMap(troopsMap);

        LinkedHashSet<String> player = new LinkedHashSet<>();
        String wanJiaName = "玩家";
        tableTopInformation.setWanJiaName(wanJiaName);
        player.add(wanJiaName);
        
		//游戏次数 第几次的意思,不是只玩参数 数量的次数
        int round = 1;


        GameOverBean gameOverBean = new GameOverBean();
        gameOverBean.setIsContinue(false);
        gameOverBean.setWinNum(0);
        gameOverBean.setFailNum(0);
        gameOverBean.setScore(0);
        tableTopInformation.setGameOverBean(gameOverBean);
        Boolean isContinue = true;

(2)生成玩家

这里规定了玩家人数 3 ,并给 ai 装脑子(脑子就是后面我们继承ai抽象类的实体类,这里用的是3代脑子 Ai_3)

while (true){
            int index = (int) (Math.random() * (game_player.size() - 1));
            String s = game_player.get(index);
            player.add(s);
            if (player.size() == 3){
                break;
            }
        }
        for (String s : player) {
            map.put(s,new ArrayList<>());
            mapSB.put(s,wanJiaName.equals(s));
            if (!wanJiaName.equals(s)){
                Ai_3 ai = new Ai_3();
                ai.setName(s);
                ai.setTableTopInformation(tableTopInformation);
                aiMap.put(s,ai);
            }
        }
        tableTopInformation.setPlayer(player);

(3)生成一副扑克牌

这里我自己发明了一个混乱模式(可能17张都是一种牌)。。。。。。。。看看就好,普通模式的话就传0 就行了

/**
     * 获取不同模式下的牌
     * 0 普通模式 54 张牌
     * 1 混乱模式 54*54 张牌里取 54 张
     * @param type
     * @return
     */
    private static List<Poker> getPoker(Integer type){
        List<Poker> pokers = new ArrayList<>();
        switch (type){
            case 0:
                pokers = getPoker();
                break;
            case 1:
                for (int i = 0; i < 54; i++) {
                    pokers.addAll(getPoker());
                }
                Collections.shuffle(pokers);
                pokers = pokers.subList(0,54);
                break;
            default:
                break;
        }
        return pokers;
    }

2.游戏开始

这里play这个方法就是提出来的,后面一步一步介绍

while (isContinue){
            GameOverBean play = play(tableTopInformation, sc);
            isContinue = play.getIsContinue();
        }

(1)先把桌面信息get出来,方便一点

//基础数据
        List<Poker> poker = getPoker(0);
        Map<String,List<Poker>> map = tableTopInformation.getPlayerPokerMap();
        String wanJiaName = tableTopInformation.getWanJiaName();
        Map<String,Boolean> mapSB = tableTopInformation.getMapSB();
        LinkedHashSet<String> player = tableTopInformation.getPlayer();
        Map<String,Integer> troopsMap = tableTopInformation.getTroopsMap();
        List<Player> playerList = tableTopInformation.getPlayerList();
        Map<String,Ai> aiMap = tableTopInformation.getAiMap();
        GameOverBean gameOverBean = tableTopInformation.getGameOverBean();
        Integer beiShu = 0;
		/**
         * key 玩家名
         * value 玩家对应的出牌记录
         */
        Map<String,StringBuilder> mapCP = new LinkedHashMap<>();
        tableTopInformation.setMapCP(mapCP);


        String maxPlayer = "";
        String maxPoker = "";

(2)洗牌发牌,这里就是打乱顺序和拆分牌

//洗牌  打乱顺序 + 清空玩家手牌 + 清空 playerList
        Collections.shuffle(poker);
        for (List<Poker> value : map.values()) {
            value.clear();
        }
        playerList.clear();

        /**
         * 分出地主牌
         */
        List<Poker> poker0 = new ArrayList<>(poker.subList(0, 3));
//        poker.removeAll(poker0);
        poker = poker.subList(3,poker.size());


        //发牌
        licensing(map,poker);
        
		//key 抢到地主的人
        String key = wanJiaName;
        //给地主发地主牌
        panDuanDiZhu(map,key,poker0,mapSB,player);
/**
     * 发牌
     * @param map
     * @param poker
     */
    private static void licensing(Map<String,List<Poker>> map,List<Poker> poker){
        int n = 0;
        Map<Integer, String> map1 = new HashMap<>(3);
        for (String s : map.keySet()) {
            map1.put(n,s);
            n++;
        }
        n = 0;
        for (Poker p : poker) {
            String put = map1.get(n);
            List<Poker> pokers = map.get(put);
            pokers.add(p);
            if (n == 2){
                n = 0;
            }else {
                n++;
            }
        }
    }

private static void panDuanDiZhu(Map<String,List<Poker>> map,String key,List<Poker> poker0,Map<String,Boolean> mapSB,LinkedHashSet<String> player){
        List<Poker> remove = map.remove(key);
        remove.addAll(poker0);
        map.put(key,remove);
    }

(3)给玩家设置出牌顺序,在原有的基础上,地主先出,再排序

int priority = 1;
        for (String s : player) {
            Player p = new Player();
            p.setName(s);
            Integer troopsType = s.contains(key) ? 0 : 2;
            troopsMap.put(s,troopsType);
            p.setTroopsType(troopsType);
            p.setPriority(priority);
            playerList.add(p);
            priority++;
        }
//排序 优先级越小,排序越靠前
        playerList = playerList.stream().sorted(Comparator.comparing(Player::getPriority)).collect(Collectors.toList());

(4)接下来就是循环出牌,直到一方手牌为0

【1】判断手牌数方法
private static Integer pokerSize(List<Poker> list){
        Integer sum = list.stream().filter(item -> item.getShow()).collect(Collectors.toList()).size();
        return sum;
    }
【2】展示桌面信息方法
private static void showTableTop(Map<String,StringBuilder> mapCP,List<Poker> poker0,Map<String,List<Poker>> map,String maxPlayer,String maxPoker,String key){
        String s0 = "";
        if (!"".equals(maxPlayer)){
            s0 = " 当前" + (key.equals(maxPlayer) ? "(地主):" : ":") + maxPlayer + "," + maxPoker;
        }
        System.out.println("地主牌:" + poker0.toString() + s0);
        for (String s : mapCP.keySet()) {
            System.out.println((key.equals(s) ? "(地主)" : "") + s + "("+pokerSize(map.get(s))+")" + ":" + mapCP.get(s).toString());
        }
    }

效果如下
在这里插入图片描述

【3】校验出牌是否符合逻辑方法

斗地主的出牌规则应该知道赛,这里就是按照规则判断的

/**
     * 判断是否符合出牌规则
     * x 单 1
     * xx 对 2
     * xxxy 三带一 3
     * xxxx Ww 炸弹 4
     * abcde...顺子 5
     * aabbcc...连对 6
     * aaabbb... xy... 飞机 7
     * @param s
     * @return null 格式错误 1 单牌 2 对子 3 三带一 4 炸弹 5 顺子 6 连对 7 飞机
     */
    public static Integer panDuanGZ(String s){
        Integer b = null;
        String[] split = s.split("");
        Pattern p;
        Matcher matcher;
        if (split.length == 0){
            return b;
        }
        else if (split.length == 1){
            p = Pattern.compile(CANONICAL_X);
            matcher = p.matcher(s);
            boolean b1 = matcher.find();
            if (b1){
                b = 1;
            }
        }
        else if (split.length == 2){
            if (s.equals("Ww") || s.equals("wW")){
                b = 4;
            }else{
                p = Pattern.compile(CANONICAL_XX);
                matcher = p.matcher(s);
                Boolean b1 = matcher.find();
                if (b1){
                    b = 2;
                }
            }
        }
        else if (split.length == 3){
            return b;
        }
        else if (split.length == 4){
            p = Pattern.compile(CANONICAL_XXXX);
            matcher = p.matcher(s);
            Boolean b1 = matcher.find();
            p = Pattern.compile(CANONICAL_XXXY);
            matcher = p.matcher(s);
            Boolean b2 = matcher.find();
            if (b1){
                b = 4;
            }else if (b2){
                b = 3;
            }
        }
        else if (split.length > 4){
            //验证超级炸弹
            p = Pattern.compile(CANONICAL_XXXX_Min);
            matcher = p.matcher(s);
            Boolean cjzd = matcher.find();
            if (cjzd && matcher.group().length() == s.length()){
                return 4;
            }
            String s1 = "";
            int num = 0;
            String newStr = "";
            //先验证飞机
            p = Pattern.compile(CANONICAL_XXX);
            matcher = p.matcher(s);
            while (matcher.find()){
                String group = matcher.group();
                num++;
                s1 +=group;
                newStr += group.split("")[0];
            }
            Boolean aBoolean1 = puanDuanLX(newStr, 2);
            if (s.length() - s1.length() == num && aBoolean1){
                return 7;
            }
            //验证连对
            p = Pattern.compile(CANONICAL_XX);
            matcher = p.matcher(s);
            Boolean b6 = false;
            while (matcher.find()){
                b6 = true;
                String group = matcher.group();
                s1 +=group;
                newStr += group.split("")[0];
            }
            if (b6){
                Boolean aBoolean2 = puanDuanLX(newStr, 3);
                if (aBoolean2){
                    return 6;
                }
            }
            //验证顺子
            Boolean aBoolean = puanDuanLX(s, 5);
            if (aBoolean){
                return 5;
            }
        }
        return b;
    }
【4】再比较牌的大小
/**
     * 判断出牌是否能接上最大牌面
     * 判断是否为炸弹,为炸弹直接比面值
     * 不为炸弹先比较类型是否相同
     * 相同类型比较 各自面值
     * @param max
     * @param next
     * @return
     */
    private static Boolean panDuanXT(String max,String next){
        Pattern p;
        Matcher matcher;
        p = Pattern.compile(CANONICAL_NP);
        matcher = p.matcher(next);
        boolean b1 = matcher.find();
        //包含非牌面符号为fales
        if (b1){
            return false;
        }
        //先手不出 为false
        if ("".equals(max) && "-".equals(next)){
            return false;
        }
        //后手不出为 true
        if (!"".equals(max) && "-".equals(next)){
            return true;
        }
        Boolean b = false;
        try{
            Integer maxI = panDuanGZ(max);
            Integer nextI = panDuanGZ(next);
            if (nextI == 4 || (maxI.equals(nextI) && max.length() == next.length()) ){
                b = true;
            }
            Integer maxValue = PokerPanDuan.countValue(max, maxI);
            Integer nextValue = PokerPanDuan.countValue(next, nextI);
            if (b){
                b = nextValue > maxValue;
            }
        }catch (Exception e){
            b = false;
        }finally {
            return b;
        }
    }
【5】判断是否能出牌,也就是手牌有没有你输入的这些牌,再出牌,这里是将已经打出的牌让手牌不显示,并不是ai判断怎么出牌的逻辑,这个逻辑后面后讲
public static Boolean outPoker(List<Poker> pokers,String s){
        Boolean b = true;
        String[] split = s.split("");
        List<Poker> updateList = new ArrayList<>();
        for (String s1 : split) {
            for (Poker poker : pokers) {
                if (poker.getName().equals(s1) && poker.getShow()){
                    updateList.add(poker);
                    poker.setShow(false);
                    break;
                }
            }
        }
        if (!"-".equals(s) && updateList.size() != split.length){
            b = false;
            for (Poker poker : updateList) {
                poker.setShow(true);
            }
        }
        return b;
    }
【6】判断剩余手牌数,手牌数为0,一轮游戏就结束了
private static Integer pokerSize(List<Poker> list){
        Integer sum = list.stream().filter(item -> item.getShow()).collect(Collectors.toList()).size();
        return sum;
    }

3.以上就是该主体的基本代码块,下面直接附上整个代码

package com.fxp.linuxdemo.game.poker;

import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;
import com.fxp.linuxdemo.domain.bean.Poker;
import com.fxp.linuxdemo.game.poker.ai.Ai_2;
import com.fxp.linuxdemo.game.poker.ai.Ai_3;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;

import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.*;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Author: fxp
 * @Date: 2023/3/14 14:56
 * @Description
 */
public class DouDiZhu {

    /**
     * 测试
     */
    private static final String CANONICAL_test = "(\\d)\\1{2}";

    /**
     * 正则单牌
     */
    private static final String CANONICAL_NP = "[^2-9XJQKAWw\\-\\*]";

    /**
     * 正则单牌
     */
    private static final String CANONICAL_X = "[2-9XJQKAWw\\*]";

    /**
     * 正则对子
     */
    private static final String CANONICAL_XX = "([2-9XJQKAWw\\*])\\1{1}";

    /**
     * 正则三个
     */
    private static final String CANONICAL_XXX = "([2-9XJQKAWw\\*])\\1{2}";

    /**
     * 正则炸弹
     */
    private static final String CANONICAL_XXXX = "([2-9XJQKAWw\\*])\\1{3}";

    /**
     * 正则至少重复4次
     */
    private static final String CANONICAL_XXXX_Min = "([2-9XJQKAWw\\*])\\1{4,}";

    /**
     * 正则三带一
     */
    private static final String CANONICAL_XXXY = "([2-9XJQKAWw\\*])\\1{2}[2-9XJQKAWw\\*]";

    /**
     * 顺子
     */
    private static final String CANONICAL_ABCDE = "(3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)|9(?=X)|X(?=J)|J(?=Q)|Q(?=K)|K(?=A)){4,}";
    /**
     * 顺子
     */
    private static final String CANONICAL_EDCBA = "((?<=3)4|(?<=4)5|(?<=5)6|(?<=6)7|(?<=7)8|(?<=8)9|(?<=9)X|(?<=X)J|(?<=J)Q|(?<=Q)K|(?<=K)A){4,}";

    /**
     * 连续 至少两次
     */
    private static final String CANONICAL_ABCDE_N = "(3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)|9(?=X)|X(?=J)|J(?=Q)|Q(?=K)|K(?=A)){N,}";
    /**
     * 连续 至少两次
     */
    private static final String CANONICAL_EDCBA_N = "((?<=3)4|(?<=4)5|(?<=5)6|(?<=6)7|(?<=7)8|(?<=8)9|(?<=9)X|(?<=X)J|(?<=J)Q|(?<=Q)K|(?<=K)A){N,}";


    private static final List<String> game_player = new ArrayList<String>(){
        {
            add("吊炸天");
            add("拖拉机");
            add("煤炭");
            add("输不起");
            add("再来");
            add("你大爷");
            add("二愣子");
            add("最美富二代");
        }
    };

    public static final Map<String, Integer> valueMap = new HashMap<String, Integer>(){
        {
            put("3",3);
            put("4",4);
            put("5",5);
            put("6",6);
            put("7",7);
            put("8",8);
            put("9",9);
            put("X",10);
            put("J",11);
            put("Q",12);
            put("K",13);
            put("A",14);
            put("2",15);
            put("w",16);
            put("W",17);
        }
    };


    private static List<Poker> getPoker(){
        List<Poker> pokers = new ArrayList<>();
        for (int i = 1; i < 15; i++) {
            if (i == 14){
                for (int j = 4; j < 6; j++) {
                    Poker p = new Poker();
                    p.setName(j == 4 ? "w" : "W" );
                    p.setValue(12 + j);
                    pokers.add(p);
                }
            }else {
                for (int j = 0; j < 4; j++) {
                    Poker p = new Poker();
                    switch (i){
                        case 1:
                            p.setName("A");
                            p.setValue(14);
                            break;
                        case 2:
                            p.setName("2");
                            p.setValue(15);
                            break;
                        case 10:
                            p.setName("X");
                            p.setValue(10);
                            break;
                        case 11:
                            p.setName("J");
                            p.setValue(11);
                            break;
                        case 12:
                            p.setName("Q");
                            p.setValue(12);
                            break;
                        case 13:
                            p.setName("K");
                            p.setValue(13);
                            break;
                        default:
                            p.setName(i + "");
                            p.setValue(i);
                            break;
                    }
                    p.setType(j);
                    pokers.add(p);
                }
            }
        }
        return pokers;
    }

    /**
     * 获取不同模式下的牌
     * 0 普通模式 54 张牌
     * 1 混乱模式 54*54 张牌里取 54 张
     * @param type
     * @return
     */
    private static List<Poker> getPoker(Integer type){
        List<Poker> pokers = new ArrayList<>();
        switch (type){
            case 0:
                pokers = getPoker();
                break;
            case 1:
                for (int i = 0; i < 54; i++) {
                    pokers.addAll(getPoker());
                }
                Collections.shuffle(pokers);
                pokers = pokers.subList(0,54);
                break;
            default:
                break;
        }
        return pokers;
    }

    /**
     * 发牌
     * @param map
     * @param poker
     */
    private static void licensing(Map<String,List<Poker>> map,List<Poker> poker){
        int n = 0;
        Map<Integer, String> map1 = new HashMap<>(3);
        for (String s : map.keySet()) {
            map1.put(n,s);
            n++;
        }
        n = 0;
        for (Poker p : poker) {
            String put = map1.get(n);
            List<Poker> pokers = map.get(put);
            pokers.add(p);
            if (n == 2){
                n = 0;
            }else {
                n++;
            }
        }
    }

    private static void panDuanDiZhu(Map<String,List<Poker>> map,String key,List<Poker> poker0,Map<String,Boolean> mapSB,LinkedHashSet<String> player){
        List<Poker> remove = map.remove(key);
        remove.addAll(poker0);
        map.put(key,remove);
//        Boolean b = mapSB.remove(key);
//        mapSB.put("(地主)" + key,b);
//
//        List<String> list = new ArrayList<>(player);
//        list.remove(key);
//        list.add(0,"(地主)" + key);
//        player.clear();
//        player.addAll(list);
    }

    public static void show(Map<String,List<Poker>> map,Map<String,Boolean> mapSB){
        for (String s : map.keySet()) {
            List<Poker> pokers = map.get(s);
            if (mapSB.get(s)){
                System.out.println(s + ":" + showPokers(pokers));
            }else {
                System.out.println(s + ":" + pokerSize(pokers) + "张");
            }

        }
    }

    public static void show(Map<String,List<Poker>> map,Map<String,Boolean> mapSB,String user){
        for (String s : map.keySet()) {
            List<Poker> pokers = map.get(s);
            if (mapSB.get(s)){
                System.out.println(s + ":" + showPokers(pokers));
            }else {
                System.out.println(s + ":" + pokerSize(pokers) + "张");
            }
        }
    }

    public static void show(List<Poker> list,Boolean b){
        if (b){
            System.out.println(":" + showPokers(list));
        }else {
            System.out.println(":" + pokerSize(list) + "张");
        }
    }

    public static String showPokers(List<Poker> list){
        list = list.stream().sorted(Comparator.comparing(Poker::getValue).reversed()).collect(Collectors.toList());
        String s = "";
        for (Poker poker : list) {
            if (poker.getShow()){
                s += poker.getName();
            }
        }
        return s;
    }

    public static Boolean outPoker(List<Poker> pokers,String s){
        Boolean b = true;
        String[] split = s.split("");
        List<Poker> updateList = new ArrayList<>();
        for (String s1 : split) {
            for (Poker poker : pokers) {
                if (poker.getName().equals(s1) && poker.getShow()){
                    updateList.add(poker);
                    poker.setShow(false);
                    break;
                }
            }
        }
        if (!"-".equals(s) && updateList.size() != split.length){
            b = false;
            for (Poker poker : updateList) {
                poker.setShow(true);
            }
        }
        return b;
    }

    public static void clear() throws AWTException{
        Robot ro = new Robot();
        ro.delay(100);//延时
        ro.mousePress(InputEvent.BUTTON3_MASK);//单机鼠标右键
        ro.mouseRelease(InputEvent.BUTTON3_MASK);//松开右键
        ro.keyPress(KeyEvent.VK_CONTROL);//按ctrl键
        ro.keyPress(KeyEvent.VK_R);//按R
        ro.keyRelease(KeyEvent.VK_R);//松开R
        ro.keyRelease(KeyEvent.VK_CONTROL);//松开ctrl
        ro.delay(100);//延时
    }





    public static void main(String[] args) throws AWTException, InterruptedException {
        TableTopInformation tableTopInformation = new TableTopInformation();
        Scanner sc = new Scanner(System.in);


        List<Poker> poker = getPoker();
//        tableTopInformation.setPoker(poker);


        /**
         * key 玩家名称
         * value 玩家对应的牌
         */
        Map<String,List<Poker>> map = new HashMap<>(3);
        tableTopInformation.setPlayerPokerMap(map);

        /**
         * key 玩家名
         * value 是否显示该玩家的手牌
         */
        Map<String,Boolean> mapSB = new HashMap<>(3);
        tableTopInformation.setMapSB(mapSB);

        /**
         * key 玩家名
         * value 玩家对于的电脑ai
         */
        Map<String,Ai> aiMap = new HashMap<>();
        tableTopInformation.setAiMap(aiMap);

        List<Player> playerList = new ArrayList<>();
        tableTopInformation.setPlayerList(playerList);

        Map<String,Integer> troopsMap = new HashMap<>();
        tableTopInformation.setTroopsMap(troopsMap);

        LinkedHashSet<String> player = new LinkedHashSet<>();
        String wanJiaName = "玩家";
        tableTopInformation.setWanJiaName(wanJiaName);
        player.add(wanJiaName);
        int num = 1;
        while (true){
            int index = (int) (Math.random() * (game_player.size() - 1));
            String s = game_player.get(index);
            player.add(s);
            if (player.size() == 3){
                break;
            }
        }
        for (String s : player) {
            map.put(s,new ArrayList<>());
            mapSB.put(s,wanJiaName.equals(s));
            if (!wanJiaName.equals(s)){
                Ai_3 ai = new Ai_3();
                ai.setName(s);
                ai.setTableTopInformation(tableTopInformation);
                aiMap.put(s,ai);
            }
        }
        tableTopInformation.setPlayer(player);

        //游戏次数
        int round = 1;


        GameOverBean gameOverBean = new GameOverBean();
        gameOverBean.setIsContinue(false);
        gameOverBean.setWinNum(0);
        gameOverBean.setFailNum(0);
        gameOverBean.setScore(0);
        tableTopInformation.setGameOverBean(gameOverBean);
        Boolean isContinue = true;

        while (isContinue){
            GameOverBean play = play(tableTopInformation, sc);
            isContinue = play.getIsContinue();
        }

        sc.close();

        System.out.println("gameOverBean = " + gameOverBean.toString());

    }



    private static GameOverBean play(TableTopInformation tableTopInformation,Scanner sc) throws AWTException, InterruptedException {
        //基础数据
        List<Poker> poker = getPoker(0);
        Map<String,List<Poker>> map = tableTopInformation.getPlayerPokerMap();
        String wanJiaName = tableTopInformation.getWanJiaName();
        Map<String,Boolean> mapSB = tableTopInformation.getMapSB();
        LinkedHashSet<String> player = tableTopInformation.getPlayer();
        Map<String,Integer> troopsMap = tableTopInformation.getTroopsMap();
        List<Player> playerList = tableTopInformation.getPlayerList();
        Map<String,Ai> aiMap = tableTopInformation.getAiMap();
        GameOverBean gameOverBean = tableTopInformation.getGameOverBean();
        Integer beiShu = 0;


        /**
         * key 玩家名
         * value 玩家对应的出牌记录
         */
        Map<String,StringBuilder> mapCP = new LinkedHashMap<>();
        tableTopInformation.setMapCP(mapCP);


        String maxPlayer = "";
        String maxPoker = "";

        //洗牌  打乱顺序 + 清空玩家手牌 + 清空 playerList
        Collections.shuffle(poker);
        for (List<Poker> value : map.values()) {
            value.clear();
        }
        playerList.clear();

        /**
         * 分出地主牌
         */
        List<Poker> poker0 = new ArrayList<>(poker.subList(0, 3));
//        poker.removeAll(poker0);
        poker = poker.subList(3,poker.size());


        //发牌
        licensing(map,poker);

        /**
         * 下面方法,写抢地主时再打开
         */
        //展示桌面,用来抢地主
//        show(map,mapSB);

        //key 抢到地主的人
        String key = wanJiaName;
        //给地主发地主牌
        panDuanDiZhu(map,key,poker0,mapSB,player);

        int priority = 1;
        for (String s : player) {
            Player p = new Player();
            p.setName(s);
            Integer troopsType = s.contains(key) ? 0 : 2;
            troopsMap.put(s,troopsType);
            p.setTroopsType(troopsType);
            p.setPriority(priority);
            playerList.add(p);
            priority++;
        }

        //排序 优先级越小,排序越靠前
        playerList = playerList.stream().sorted(Comparator.comparing(Player::getPriority)).collect(Collectors.toList());

        for (Player s : playerList) {
            mapCP.put(s.getName(),new StringBuilder(""));
        }

//        show(map,mapSB);

        Boolean end = false;
        while (!end){
            for (Player p : playerList) {
                //s 玩家名称
                String s = p.getName();
                boolean isDiZhu = key.equals(s);
                boolean isWanJia = s.contains(wanJiaName);
                if (s.equals(maxPlayer)){
                    maxPlayer = "";
                    maxPoker = "";
                }
                clear();
                showTableTop(mapCP,poker0,map,maxPlayer,maxPoker,key);
                List<Poker> pokers = map.get(s);
                if (isWanJia){
                    System.out.print(s + ",请出牌");
                }else {
                    System.out.print(s + ",出牌");
                }
                show(pokers,mapSB.get(s));
                String next = "";
                if (isWanJia){
                    next = sc.next();
                }else {
                    Ai ai = aiMap.get(s);
                    String s1 = showPokers(pokers);
                    next = ai.outPoker(OutPokerVo.builder().s(s1).type(null).max(maxPoker).maxPlayer(maxPlayer).build());
                    //模拟思考 1 秒
                    Thread.sleep(500);
                    System.out.println(next);
                    //出牌后停3秒
                    Thread.sleep(500);
                }
                Boolean b = true;
                //校验
                //出牌规则是否正确
                //是否大于最大排
                while (true){
                    b = true;
                    if(!"".equals(maxPoker)){
                        b = panDuanXT(maxPoker, next);
                    }
                    if (b){
                        Integer integer = PokerPanDuan.panDuanGZ(next);
                        if (null == integer && !"-".equals(next)){
                            System.out.println("出牌不复合规则,请重新出牌");
                            next = sc.next();
                            continue;
                        }
                        b = outPoker(pokers, next);
                        if (b){
                            if (!"-".equals(next)){
                                maxPlayer = s;
                                maxPoker = next;
                                if (4 == integer){
                                    beiShu++;
                                }
                            }
                            break;
                        }else {
                            System.out.println("出牌不复合规则,请重新出牌");
                            next = sc.next();
                        }
                    }else {
                        System.out.println("出牌不复合规则,请重新出牌");
                        next = sc.next();
                    }
                }
                Integer sy = pokerSize(pokers);
                if ( sy == 0){
                    end = true;
                    break;
                }
                StringBuilder stringBuilder = mapCP.get(s);
                if (!"".equals(stringBuilder.toString())){
                    stringBuilder.append(",");
                }
                stringBuilder.append(next);
                mapCP.put(s,stringBuilder);
            }
        }
        System.out.println("恭喜 " + maxPlayer + " 获胜,是否继续,1 继续");
        String next = sc.next();

        gameOverBean.setIsContinue("1".equals(next));
        Integer integer = panDuanVictoryOrDefeat(troopsMap, maxPlayer, wanJiaName, beiShu);
        gameOverBean.setScore(gameOverBean.getScore() + integer);
        if (integer > 0){
            gameOverBean.setWinNum(gameOverBean.getWinNum() + 1);
        }else {
            gameOverBean.setFailNum(gameOverBean.getFailNum() + 1);
        }
        return gameOverBean;
    }

    /**
     * 判断胜负
     * 返回得分
     * @return
     */
    private static Integer panDuanVictoryOrDefeat(Map<String,Integer> troopsMap,String maxPlayer,String wanJia,Integer beiShu){
        Integer i = 0;
        Integer deiFen = 1;
        while (beiShu > 0){
            deiFen *= 2;
            beiShu--;
        }

        //玩家是地主时胜利 0 地主 1 地主队 2 农民队
        int diZhuNum = 0;
        int nongMingNum = 0;
        for (Integer value : troopsMap.values()) {
            if (1 == value || 0 == value){
                diZhuNum++;
            }else if (2 == value){
                nongMingNum++;
            }
        }

        Integer integer1 = troopsMap.get(maxPlayer);
        Integer integer2 = troopsMap.get(wanJia);
        if (null == integer2){
            integer2 = troopsMap.get("(地主)" + wanJia);
        }

        Boolean shenLi = false;
        if (maxPlayer.equals(wanJia)){
            shenLi = true;
        }else if (integer1.equals(integer2)){
            shenLi = true;
        }else if (integer1 == 0 && integer2 == 1){
            shenLi = true;
        }else if (integer1 == 1 && integer2 == 0){
            shenLi = true;
        }

        if (shenLi){
            //胜利
            if (integer2 == 0 || integer2 == 1){
                i = nongMingNum * deiFen / diZhuNum;
            }else {
                i = deiFen;
            }
        }else {
            //失败
            if (integer2 == 0 || integer2 == 1){
                i = -1 * (nongMingNum * deiFen / diZhuNum);
            }else {
                i = -1 * deiFen;
            }
        }
        return i;
    }

    private static void showTableTop(Map<String,StringBuilder> mapCP,List<Poker> poker0,Map<String,List<Poker>> map,String maxPlayer,String maxPoker,String key){
        String s0 = "";
        if (!"".equals(maxPlayer)){
            s0 = " 当前" + (key.equals(maxPlayer) ? "(地主):" : ":") + maxPlayer + "," + maxPoker;
        }
        System.out.println("地主牌:" + poker0.toString() + s0);
        for (String s : mapCP.keySet()) {
            System.out.println((key.equals(s) ? "(地主)" : "") + s + "("+pokerSize(map.get(s))+")" + ":" + mapCP.get(s).toString());
        }
    }

//    public static void main(String[] args) throws AWTException {
//        // TODO Auto-generated method stub
//        System.out.println("欢迎来到Narnat的水果店");
//        System.out.println("请在控制台内单击 enter 以继续:");
//        System.out.println("...................");
//        Scanner sc = new Scanner(System.in);
//        String s = sc.nextLine();
//        clear();
//    }



    private static Integer pokerSize(List<Poker> list){
        Integer sum = list.stream().filter(item -> item.getShow()).collect(Collectors.toList()).size();
        return sum;
    }


    /**
     * 计算牌面
     * 最大面值 468
     * @return
     */
    private static Integer CalculateDeck(String s){
        Integer i = 0;
        String[] split = s.split("");

        return i;
    }

//    public static void main(String[] args) {
//        Boolean aBoolean = panDuanXT("6666", "55555");
//        System.out.println("aBoolean = " + aBoolean);
//        Integer integer = PokerPanDuan.panDuanGZ("55555");
//        System.out.println("integer = " + integer);
//    }

    public static Boolean test(String s){
        Pattern p;
        Matcher matcher;
        p = Pattern.compile(CANONICAL_test);
        matcher = p.matcher(s);
        Boolean b1 = matcher.find();
        return b1;
    }

    /**
     * 判断是否符合出牌规则
     * x 单 1
     * xx 对 2
     * xxxy 三带一 3
     * xxxx Ww 炸弹 4
     * abcde...顺子 5
     * aabbcc...连对 6
     * aaabbb... xy... 飞机 7
     * @param s
     * @return null 格式错误 1 单牌 2 对子 3 三带一 4 炸弹 5 顺子 6 连对 7 飞机
     */
    private static Integer panDuanGZ(String s){
        Integer b = null;
        String[] split = s.split("");
        Pattern p;
        Matcher matcher;
        if (split.length == 0){
            return b;
        }
        else if (split.length == 1){
            p = Pattern.compile(CANONICAL_X);
            matcher = p.matcher(s);
            boolean b1 = matcher.find();
            if (b1){
                b = 1;
            }
        }
        else if (split.length == 2){
            if (s.equals("Ww") || s.equals("wW")){
                b = 4;
            }else{
                p = Pattern.compile(CANONICAL_XX);
                matcher = p.matcher(s);
                Boolean b1 = matcher.find();
                if (b1){
                    b = 2;
                }
            }
        }
        else if (split.length == 3){
            return b;
        }
        else if (split.length == 4){

            int num_W = 0;
            int num_w = 0;
            String[] split1 = s.split("");
            for (String s1 : split1) {
                if ("w".equals(s1)){
                    num_w++;
                }else if ("W".equals(s1)){
                    num_W++;
                }
            }
            if (num_w != 0 && num_W != 0 && num_w == num_W && num_w + num_W == split1.length){
                b = 4;
                return b;
            }

            p = Pattern.compile(CANONICAL_XXXX);
            matcher = p.matcher(s);
            Boolean b1 = matcher.find();
            p = Pattern.compile(CANONICAL_XXXY);
            matcher = p.matcher(s);
            Boolean b2 = matcher.find();
            if (b1){
                b = 4;
            }else if (b2){
                b = 3;
            }
        }
        else if (split.length > 4){

            int num_W = 0;
            int num_w = 0;
            String[] split1 = s.split("");
            for (String s1 : split1) {
                if ("w".equals(s1)){
                    num_w++;
                }else if ("W".equals(s1)){
                    num_W++;
                }
            }
            if (num_w != 0 && num_W != 0 && num_w == num_W){
                b = 4;
                return b;
            }

            p = Pattern.compile(CANONICAL_XXXX_Min);
            matcher = p.matcher(s);
            Boolean b1 = matcher.find();
            if (b1){
                b = 4;
                return b;
            }


            String s1 = "";
            int num = 0;
            String newStr = "";
            //先验证飞机
            p = Pattern.compile(CANONICAL_XXX);
            matcher = p.matcher(s);
            while (matcher.find()){
                String group = matcher.group();
                num++;
                s1 +=group;
                newStr += group.split("")[0];
            }
            Boolean aBoolean1 = puanDuanLX(newStr, 2);
            if (s.length() - s1.length() == num && aBoolean1){
                return 7;
            }
            //验证连对
            p = Pattern.compile(CANONICAL_XX);
            matcher = p.matcher(s);
            while (matcher.find()){
                String group = matcher.group();
                s1 +=group;
                newStr += group.split("")[0];
            }
            Boolean aBoolean2 = puanDuanLX(newStr, 3);
            if (aBoolean2){
                return 6;
            }
            //验证顺子
            Boolean aBoolean = puanDuanLX(s, 5);
            if (aBoolean){
                return 5;
            }
        }
        return b;
    }

    /**
     * 判断连续
     * @param s 需要判断的字符串
     * @param num 至少连续的次数
     * @return
     */
    public static Boolean puanDuanLX(String s ,int num){
        Boolean b = false;
        Pattern p;
        Matcher matcher;
        //验证顺子
        p = Pattern.compile(CANONICAL_ABCDE_N.replace("N",(num-1) + ""));
        matcher = p.matcher(s);
        boolean b1 = matcher.find();
        String group1 = "";
        if (b1){
            group1 = matcher.group();
        }
        p = Pattern.compile(CANONICAL_EDCBA_N.replace("N",(num-1) + ""));
        matcher = p.matcher(s);
        boolean b2 = matcher.find();
        String group2 = "";
        if (b2){
            group2 = matcher.group();
        }
        if (group1.length() + group2.length() == s.length() * 2 - 2){
            b = true;
        }
        return b;
    }

    /**
     * 计算面值
     * 当为非炸弹时,面值为各值相加
     * 当为炸弹时,面值为个值相加 + 一副牌总值
     * 当为王炸时,面值为两副牌总值
     * 一副牌总值 416 (除大小王)
     * @return
     */
    private static Integer countValue(String s,Integer type){
        Integer value = 0;
        if (4 == type){
            value += 416;
            if (2 == s.length()){
                value += 416;
            }
        }
        if (type == 3 || type == 7){
            Pattern p = Pattern.compile(CANONICAL_XXX);
            Matcher m = p.matcher(s);
            while (m.find()){
                String group = m.group();
                value = simpleCountValue(group,value);
            }
        }else {
            value = simpleCountValue(s,value);
        }
        return value;
    }

    private static Integer simpleCountValue(String s,Integer value){
        if (null == value){
            value = 0;
        }
        String[] split = s.split("");
        for (String s1 : split) {
            value += valueMap.get(s1);
        }
        return value;
    }

    /**
     * 判断出牌是否能接上最大牌面
     * 判断是否为炸弹,为炸弹直接比面值
     * 不为炸弹先比较类型是否相同
     * 相同类型比较 各自面值
     * @param max
     * @param next
     * @return
     */
    private static Boolean panDuanXT(String max,String next){
        Pattern p;
        Matcher matcher;
        p = Pattern.compile(CANONICAL_NP);
        matcher = p.matcher(next);
        boolean b1 = matcher.find();
        //包含非牌面符号为fales
        if (b1){
            return false;
        }
        //先手不出 为false
        if ("".equals(max) && "-".equals(next)){
            return false;
        }
        //后手不出为 true
        if (!"".equals(max) && "-".equals(next)){
            return true;
        }
        Boolean b = false;
        try{
            Integer maxI = panDuanGZ(max);
            Integer nextI = panDuanGZ(next);
            if (nextI == 4 || (maxI.equals(nextI) && max.length() == next.length()) ){
                b = true;
            }
            Integer maxValue = PokerPanDuan.countValue(max, maxI);
            Integer nextValue = PokerPanDuan.countValue(next, nextI);
            if (b){
                b = nextValue > maxValue;
            }
        }catch (Exception e){
            b = false;
        }finally {
            return b;
        }
    }





}

4.下篇介绍判断工具类,这一类主要是给ai用的,来获取一副牌的所有类型的组合牌,比如说获取所有对子,所有顺子之类的

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值