关于游戏开发:java斗地主游戏开发-算法思路讲解

2次阅读

共计 59817 个字符,预计需要花费 150 分钟才能阅读完成。

上学期刚开学的时候我特地沉迷于斗地主 充了 6 块钱赢了 30 万豆 而后一夜之间破产 越想越气
而后我就有一个大胆的想法开发一个斗地主当初这个斗地主能在管制台上运行
本文次要解说我在开发斗地主时钻研的算法思路
当初算是一个半成品吧 差个图形界面和一个 socket 就能联机对战了
起初我又沉迷上了王者光荣到这学期才想起我还有个斗地主的源码所以明天想在这里和大家分享一下

一、先定义个常量的类

package com.liziguo.ddz;

/**
 * @Author: Liziguo
 * @Date: 2020/9/13 11:28
 */
public class GameConstants {

    public static final int NUM_3 = 0;
    public static final int NUM_4 = 1;
    public static final int NUM_5 = 2;
    public static final int NUM_6 = 3;
    public static final int NUM_7 = 4;
    public static final int NUM_8 = 5;
    public static final int NUM_9 = 6;
    public static final int NUM_10 = 7;
    public static final int NUM_J = 8;
    public static final int NUM_Q = 9;
    public static final int NUM_K = 10;
    public static final int NUM_A = 11;
    public static final int NUM_2 = 12;
    public static final int NUM_JOKER = 13;

    public static final int ID_3_1 = 0;
    public static final int ID_3_2 = 1;
    public static final int ID_3_3 = 2;
    public static final int ID_3_4 = 3;
    public static final int ID_4_1 = 4;
    public static final int ID_4_2 = 5;
    public static final int ID_4_3 = 6;
    public static final int ID_4_4 = 7;
    public static final int ID_5_1 = 8;
    public static final int ID_5_2 = 9;
    public static final int ID_5_3 = 10;
    public static final int ID_5_4 = 11;
    public static final int ID_6_1 = 12;
    public static final int ID_6_2 = 13;
    public static final int ID_6_3 = 14;
    public static final int ID_6_4 = 15;
    public static final int ID_7_1 = 16;
    public static final int ID_7_2 = 17;
    public static final int ID_7_3 = 18;
    public static final int ID_7_4 = 19;
    public static final int ID_8_1 = 20;
    public static final int ID_8_2 = 21;
    public static final int ID_8_3 = 22;
    public static final int ID_8_4 = 23;
    public static final int ID_9_1 = 24;
    public static final int ID_9_2 = 25;
    public static final int ID_9_3 = 26;
    public static final int ID_9_4 = 27;
    public static final int ID_10_1 = 28;
    public static final int ID_10_2 = 29;
    public static final int ID_10_3 = 30;
    public static final int ID_10_4 = 31;
    public static final int ID_J_1 = 32;
    public static final int ID_J_2 = 33;
    public static final int ID_J_3 = 34;
    public static final int ID_J_4 = 35;
    public static final int ID_Q_1 = 36;
    public static final int ID_Q_2 = 37;
    public static final int ID_Q_3 = 38;
    public static final int ID_Q_4 = 39;
    public static final int ID_K_1 = 40;
    public static final int ID_K_2 = 41;
    public static final int ID_K_3 = 42;
    public static final int ID_K_4 = 43;
    public static final int ID_A_1 = 44;
    public static final int ID_A_2 = 45;
    public static final int ID_A_3 = 46;
    public static final int ID_A_4 = 47;
    public static final int ID_2_1 = 48;
    public static final int ID_2_2 = 49;
    public static final int ID_2_3 = 50;
    public static final int ID_2_4 = 51;
    public static final int ID_JOKER_1 = 52;
    public static final int ID_JOKER_2 = 53;

    public static final int TYPE_ERROR = -1;
    public static final int TYPE_NULL = 0;
    public static final int TYPE_1 = 1;
    public static final int TYPE_22 = 2;
    public static final int TYPE_333 = 3;
    public static final int TYPE_BOOM = 4;
    public static final int TYPE_3331 = 5;
    public static final int TYPE_33322 = 6;
    public static final int TYPE_444412 = 7;
    public static final int TYPE_44441122 = 8;
    public static final int TYPE_34567 = 9;
    public static final int TYPE_334455 = 10;
    public static final int TYPE_333444 = 11;
    public static final int TYPE_33344412 = 12;
    public static final int TYPE_3334441122 = 13;
}

ID_3_1 指的是方块三
ID_K_2 指的是梅花十三(梅花 K 哈哈哈伍六七看多了)辨别花色
NUM_3 指的是三 不辨别花色
小提示:用 id/ 4 就能得出这张牌的 num 了
而后 type 的都是牌型了 置信打过斗地主的都看得懂吧

二、定义牌的实体类

package com.liziguo.ddz;

/**
 * @Author: Liziguo
 * @Date: 2020/9/12 11:22
 */
public class Card {

    public final int id;
    public final int num;

    public Card(int id) {
        this.id = id;
        num = id / 4;
    }

    /**
     * 这个构造方法是用来做测试用的
     *
     * @param s
     */
    public Card(String s) {if ("C".equals(s)) {
            id = GameConstants.ID_JOKER_2;
            num = id / 4;
            return;
        }
        switch (s) {
            case "3":
                num = GameConstants.NUM_3;
                break;
            case "4":
                num = GameConstants.NUM_4;
                break;
            case "5":
                num = GameConstants.NUM_5;
                break;
            case "6":
                num = GameConstants.NUM_6;
                break;
            case "7":
                num = GameConstants.NUM_7;
                break;
            case "8":
                num = GameConstants.NUM_8;
                break;
            case "9":
                num = GameConstants.NUM_9;
                break;
            case "0":
                num = GameConstants.NUM_10;
                break;
            case "J":
            case "j":
                num = GameConstants.NUM_J;
                break;
            case "Q":
            case "q":
                num = GameConstants.NUM_Q;
                break;
            case "K":
            case "k":
                num = GameConstants.NUM_K;
                break;
            case "1":
            case "A":
            case "a":
                num = GameConstants.NUM_A;
                break;
            case "2":
                num = GameConstants.NUM_2;
                break;
            case "c":
                num = GameConstants.NUM_JOKER;
                break;
            default:
                throw new RuntimeException();}
        id = num * 4;
    }

    public boolean is2() {return num == GameConstants.NUM_2;}

    public boolean isJoker() {return num == GameConstants.NUM_JOKER;}

    @Override
    public String toString() {switch (num) {
            case GameConstants.NUM_3:
                return "3";
            case GameConstants.NUM_4:
                return "4";
            case GameConstants.NUM_5:
                return "5";
            case GameConstants.NUM_6:
                return "6";
            case GameConstants.NUM_7:
                return "7";
            case GameConstants.NUM_8:
                return "8";
            case GameConstants.NUM_9:
                return "9";
            case GameConstants.NUM_10:
                return "10";
            case GameConstants.NUM_J:
                return "J";
            case GameConstants.NUM_Q:
                return "Q";
            case GameConstants.NUM_K:
                return "K";
            case GameConstants.NUM_A:
                return "A";
            case GameConstants.NUM_2:
                return "2";
            case GameConstants.NUM_JOKER:
                if (id == GameConstants.ID_JOKER_1) return "小王";
                else return "大王";
        }
        return null;
    }

}

第二个构造方法是做测试用的
留神:这里用大小写的 C 代替大小王,0 代表 10,1 和 A 都能代表 A
其余没什么好说的了

package com.liziguo.ddz;

/**
 * @Author: Liziguo
 * @Date: 2020/9/12 18:53
 */
public class CardGroup {
    public final int num;
    public int sum;

    public CardGroup(int num, int sum) {
        this.num = num;
        this.sum = sum;
    }

    @Override
    public String toString() {return "(" + "num=" + num + ", sum=" + sum + ')';
    }
}

三、创立工具类

package com.liziguo.ddz;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: Liziguo
 * @Date: 2020/9/17 18:30
 */
public class CardUtils {public static List<Card> CreateCards(String cards) {List<Card> list = new ArrayList<>();
        for (int i = 0; i < cards.length(); i++) {String s = cards.substring(i, i + 1);
            if (!" ".equals(s)) list.add(new Card(s));
        }
        return list;
    }

    /**
     * 这个办法的作用是统计 list 中每张牌呈现的次数
     *
     * @param list
     * @return
     */
    public static List<CardGroup> createGroup(List<Card> list) {List<CardGroup> groups = new ArrayList<>();
        LinkedList<Card> temp = new LinkedList<>(list);
        Map<Integer, Integer> map = new HashMap<>();// key=cardNum value=sum
        while (temp.size() > 0) {final Card card = temp.removeLast();
            final Integer sum = map.get(card.num);
            if (sum == null)
                map.put(card.num, 1);
            else
                map.put(card.num, sum.intValue() + 1);
        }
        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {groups.add(new CardGroup(entry.getKey(), entry.getValue()));
        }
        return groups;
    }

    /**
     * 删除大小王 返回新的 List<CardGroup>
     *
     * @param list
     * @return
     */
    public static List<CardGroup> removeJokers(List<CardGroup> list) {return list.stream().filter(cardGroup -> cardGroup.num != GameConstants.NUM_JOKER).collect(Collectors.toList());
    }


    public static int indexOfById(List<Card> list, int id) {for (int i = 0; i < list.size(); i++) {if (list.get(i).id == id) return i;
        }
        return -1;
    }

    public static int indexOfByNum(List<Card> list, int num) {for (int i = 0; i < list.size(); i++) {if (list.get(i).num == num) return i;
        }
        return -1;
    }

    /**
     * 获取 list 中第一张为 num 的牌
     *
     * @param list
     * @param num
     * @return
     */
    public static Card getCardByNum(List<Card> list, int num) {for (int i = 0; i < list.size(); i++) {if (list.get(i).num == num)
                return list.get(i);
        }
        return null;
    }

    /**
     * 从 list 头部开始搜寻 返回 len 张为 num 的牌(list 必须是排好序的)*
     * @param list
     * @param num
     * @param len  长度
     * @return
     */
    public static List<Card> getCardByNum(List<Card> list, int num, int len) {for (int i = 0; i < list.size(); i++) {if (list.get(i).num == num)
                return list.subList(i, i + len);// subList 后的 list 不能增加或删除
        }
        return new ArrayList<>();}

    /**
     * 获取 list 中最初一张为 num 的牌
     *
     * @param list
     * @param num
     * @return
     */
    public static Card getLastCardByNum(List<Card> list, int num) {for (int i = list.size() - 1; i >= 0; i--) {if (list.get(i).num == num)
                return list.get(i);
        }
        return null;
    }

    /**
     * 从 list 尾部开始搜寻 返回 len 张为 num 的牌(list 必须是排好序的)*
     * @param list
     * @param num
     * @param len  长度
     * @return
     */
    public static List<Card> getLastCardByNum(List<Card> list, int num, int len) {for (int i = list.size() - 1; i >= 0; i--) {if (list.get(i).num == num)
                return list.subList(i - len + 1, i + 1);// subList 后的 list 不能增加或删除
        }
        return new ArrayList<>();}

    /**
     * 依据索引返回一个新的 list
     *
     * @param list
     * @param indexes
     */
    public static List<Card> getCardsByIndexes(List<Card> list, List<Integer> indexes) {List<Card> newList = new ArrayList<>(indexes.size());
        for (int i = 0; i < indexes.size(); i++) {newList.add(list.get(indexes.get(i)));
        }
        return newList;
    }

    /**
     * 依据索引从 list 删除 返回一个新的 list
     *
     * @param list
     * @param indexes
     */
    public static List<Card> removeByIndex(List<Card> list, List<Integer> indexes) {List<Card> newList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {if (!indexes.contains(i)) newList.add(list.get(i));
        }
        return newList;
    }

    /**
     * 把牌号为 num 的牌全副挪动到后面(list 必须是排好序的)*
     * @param num
     * @param len 挪动的牌数
     */
    public static void moveToHead(List<Card> list, int num, int len) {ArrayList<Card> temp = new ArrayList<>();
        int i = 0;
        while (i < list.size() && temp.size() < len) {if (list.get(i).num == num) temp.add(list.remove(i));
            else i++;
        }
        list.addAll(0, temp);
    }

    /**
     * 把牌号为 num 的牌全副挪动到前面(list 必须是排好序的)*
     * @param num
     * @param len 挪动的牌数
     */
    public static void moveToEnd(List<Card> list, int num, int len) {ArrayList<Card> temp = new ArrayList<>();
        int i = 0;
        while (i < list.size() && temp.size() < len) {if (list.get(i).num == num) temp.add(list.remove(i));
            else i++;
        }
        list.addAll(temp);
    }

}

工具类中蕴含了一些待会要用到的办法

亖、而后就是重头戏了 怎么判断玩家出的是什么牌 是否非法

package com.liziguo.ddz;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author: Liziguo
 * @Date: 2020/9/12 12:10
 */
public class CardsFactory {

    private final List<Card> list;// 排序形式为 order by id desc
    private final CardProducts products;
    private final List<CardGroup> groups;// 排序形式为 order by sum desc,num desc

    private CardsFactory(List<Card> list) {
        this.list = list;

        this.list.sort((o1, o2) -> o2.id - o1.id);
        products = new CardProducts();
        groups = CardUtils.createGroup(list);
        Collections.sort(groups, (o1, o2) -> {
            //order by sum desc,num desc
            final int o = o2.sum - o1.sum;
            if (o != 0) return o;
            return o2.num - o1.num;
        });

        if (is1()) return;
        if (is22()) return;
        if (is333()) return;
        if (isBoom()) return;
        if (is3331()) return;
        if (is33322()) return;
        if (is34567()) return;
        if (is334455()) return;
        //33334444 可被分为飞机和四带两对
        boolean flag = false;
        if (is444412()) flag = true;
        if (is44441122()) flag = true;
        if (is333444()) flag = true;
        if (is33344412()) flag = true;
        if (is3334441122()) flag = true;
        if (!flag) {List<Card> sorted = new ArrayList<>(list);
            products.add(new CardProduct(sorted, GameConstants.TYPE_ERROR, list.get(0), groups));
        }
    }

    /**
     * 是否全副牌的 num 都一样
     *
     * @return
     */
    public boolean isEqualsAll() {return groups.size() == 1;
    }

    public boolean is1() {if (list.size() == 1) {List<Card> sorted = new ArrayList<>(list);
            products.add(new CardProduct(sorted, GameConstants.TYPE_1, list.get(0), groups));
            return true;
        }
        return false;
    }

    public boolean is22() {if (list.size() == 2 && !list.get(0).isJoker() && isEqualsAll()) {List<Card> sorted = new ArrayList<>(list);
            products.add(new CardProduct(sorted, GameConstants.TYPE_22, list.get(0), groups));
            return true;
        }
        return false;
    }

    public boolean is333() {if (list.size() == 3 && !list.get(0).isJoker() && isEqualsAll()) {List<Card> sorted = new ArrayList<>(list);
            products.add(new CardProduct(sorted, GameConstants.TYPE_333, list.get(0), groups));
            return true;
        }
        return false;
    }

    public boolean isBoom() {if (list.size() >= 2) {if (groups.size() == 1) {if (groups.get(0).num == GameConstants.NUM_JOKER && groups.get(0).sum >= 2 || groups.get(0).sum >= 4) {List<Card> sorted = new ArrayList<>(list);
                    products.add(new CardProduct(sorted, GameConstants.TYPE_BOOM, list.get(0), groups));
                    return true;
                }
            }
        }
        return false;
    }

    public boolean is3331() {if (list.size() == 4) {if (groups.get(0).sum == 3 && groups.get(0).num != GameConstants.NUM_JOKER) {List<Card> sorted = new ArrayList<>(list);
                CardUtils.moveToEnd(sorted, groups.get(1).num, groups.get(1).sum);
                products.add(new CardProduct(sorted, GameConstants.TYPE_3331, sorted.get(0), groups));
                return true;
            }
        }
        return false;
    }

    public boolean is33322() {if (list.size() == 5) {if (CardUtils.indexOfByNum(list, GameConstants.NUM_JOKER) < 0)
                if (groups.get(0).sum == 3 && groups.get(1).sum == 2 && groups.get(0).num != GameConstants.NUM_JOKER) {List<Card> sorted = new ArrayList<>(list);
                    CardUtils.moveToEnd(sorted, groups.get(1).num, groups.get(1).sum);
                    products.add(new CardProduct(sorted, GameConstants.TYPE_33322, sorted.get(0), groups));
                    return true;
                }
        }
        return false;
    }

    public boolean is444412() {if (list.size() == 6) {if (groups.get(0).sum >= 4) {List<Card> sorted = new ArrayList<>(list);
                CardUtils.moveToHead(sorted, groups.get(0).num, 4);
                products.add(new CardProduct(sorted, GameConstants.TYPE_444412, sorted.get(0), groups));
                return true;
            }
        }
        return false;
    }

    public boolean is44441122() {if (list.size() == 8) {List<CardGroup> temp = new ArrayList<>(groups);
            temp.sort((o1, o2) -> o2.num - o1.num);// 按 num 逆序
            CardGroup ge4 = null;// 找到 num 最大 且 sum>= 4 的牌
            for (CardGroup cardGroup : temp) {if (cardGroup.sum >= 4) {
                    ge4 = cardGroup;
                    break;
                }
            }
            if (ge4 != null) {for (CardGroup cardGroup : temp) {if (cardGroup.sum % 2 != 0) return false;
                }
                List<Card> sorted = new ArrayList<>(list);
                CardUtils.moveToHead(sorted, ge4.num, 4);
                products.add(new CardProduct(sorted, GameConstants.TYPE_44441122, sorted.get(0), groups));
                return true;
            }
        }
        return false;
    }

    public boolean is34567() {if (list.size() >= 5) {if (list.get(0).id < GameConstants.ID_2_1) {for (int i = 0, len = list.size() - 1; i < len; i++) {Card card1 = list.get(i);
                    Card card2 = list.get(i + 1);
                    if (card1.num - card2.num != 1) return false;
                }
                List<Card> sorted = new ArrayList<>(list);
                products.add(new CardProduct(sorted, GameConstants.TYPE_34567, sorted.get(0), groups));
                return true;
            }
        }
        return false;
    }

    public boolean is334455() {if (list.size() >= 6 && list.get(0).id < GameConstants.ID_2_1) {if (groups.get(0).num < GameConstants.NUM_2 && groups.get(0).sum == 2) {for (int i = 0, len = groups.size() - 1; i < len; i++) {if (groups.get(i).num - groups.get(i + 1).num != 1 || groups.get(i + 1).sum != 2)
                        return false;
                }
                List<Card> sorted = new ArrayList<>(list);
                products.add(new CardProduct(sorted, GameConstants.TYPE_334455, sorted.get(0), groups));
                return true;
            }
        }
        return false;
    }

    public boolean is333444() {if (list.size() % 3 == 0 && list.size() >= 6 && groups.size() >= 2) {if (groups.get(0).num < GameConstants.NUM_2 && groups.get(0).sum == 3) {for (int i = 0, len = groups.size() - 1; i < len; i++) {if (groups.get(i).num - groups.get(i + 1).num != 1 || groups.get(i + 1).sum != 3) return false;
                }
                List<Card> sorted = new ArrayList<>(list);
                products.add(new CardProduct(sorted, GameConstants.TYPE_333444, sorted.get(0), groups));
                return true;
            }
        }
        return false;
    }

    public boolean is33344412() {if (list.size() % 4 == 0 && list.size() >= 8) {List<CardGroup> ge3 = groups.stream().filter(cardGroup -> cardGroup.sum >= 3).sorted((o1, o2) -> o2.num - o1.num).collect(Collectors.toList());

            ArrayList<ArrayList<CardGroup>> base = new ArrayList<>();// 可能不止一个三连 如 333 444 666 777 888 999 000 JJJ
            ArrayList<CardGroup> continuous = new ArrayList<>();
            for (int i = 0, len = ge3.size() - 1; i < len; i++) {final CardGroup group1 = ge3.get(i);
                final CardGroup group2 = ge3.get(i + 1);
                if (group1.num - group2.num == 1 && group1.num < GameConstants.NUM_2) {if (!continuous.contains(group1))
                        continuous.add(group1);
                    continuous.add(group2);
                    if (i == len - 1) base.add(continuous);
                } else {base.add(continuous);
                    continuous = new ArrayList<>();}
            }
            for (ArrayList<CardGroup> plane : base) {while (plane.size() >= 2) {if (plane.size() * 4 == list.size()) {List<Card> sorted = new ArrayList<>(list);
                        for (int i = plane.size() - 1; i >= 0; i--) {CardUtils.moveToHead(sorted, plane.get(i).num, 3);
                        }
                        products.add(new CardProduct(sorted, GameConstants.TYPE_33344412, sorted.get(0), groups));
                        return true;
                    } else {plane.remove(plane.size() - 1);// 切一节飞机尾
                    }
                }
            }
        }
        return false;
    }

    public boolean is3334441122() {if (list.size() % 5 == 0 && list.size() >= 10) {List<CardGroup> ge3 = groups.stream().filter(cardGroup -> cardGroup.sum >= 3).sorted((o1, o2) -> o2.num - o1.num).collect(Collectors.toList());

            ArrayList<ArrayList<CardGroup>> base = new ArrayList<>();// 可能不止一个三连 如 333 444 666 777 888 999 000 JJJ
            ArrayList<CardGroup> continuous = new ArrayList<>();
            for (int i = 0, len = ge3.size() - 1; i < len; i++) {final CardGroup group1 = ge3.get(i);
                final CardGroup group2 = ge3.get(i + 1);
                if (group1.num - group2.num == 1 && group1.num < GameConstants.NUM_2) {if (!continuous.contains(group1))
                        continuous.add(group1);
                    continuous.add(group2);
                    if (i == len - 1) base.add(continuous);
                } else {base.add(continuous);
                    continuous = new ArrayList<>();}
            }
            for (ArrayList<CardGroup> plane : base) {
                int cut = 0;
                while (plane.size() - cut >= 2) {if ((plane.size() - cut) * 5 == list.size()) {for (int i = 0; i < cut + 1; i++) {List<CardGroup> temp = plane.subList(i, i + plane.size() - cut);
                            // 在 this.groups 里找到 temp 里存在的元素 并让他的 sum-3 意思大略就是把当机身的牌从 this.groups 取走 3 张
                            List<CardGroup> diff = this.groups.stream()
                                    .map(cardGroup -> {if (temp.stream().anyMatch(group -> group.num == cardGroup.num))
                                            return new CardGroup(cardGroup.num, cardGroup.sum - 3);// 为了不影响到原来的汇合 这里抉择 new 一个
                                        else return cardGroup;
                                    })
                                    .collect(Collectors.toList());
                            // 判断剩下的牌的 sum 是否都是偶数
                            if (diff.stream().allMatch(cardGroup -> cardGroup.sum % 2 == 0)) {List<Card> sorted = new ArrayList<>(list);
                                for (int j = temp.size() - 1; j >= 0; j--) {CardUtils.moveToHead(sorted, temp.get(j).num, 3);
                                }
                                products.add(new CardProduct(sorted, GameConstants.TYPE_3334441122, sorted.get(0), groups));
                                return true;
                            }
                        }
                    }
                    cut++;
                }
            }
        }
        return false;
    }

    public static CardProducts builder(List<Card> list) {return new CardsFactory(list).products;
    }

    /**
     * 测试用
     *
     * @param cards
     * @return
     */
    public static CardProducts builder(String cards) {List<Card> list = new ArrayList<>();
        for (int i = 0; i < cards.length(); i++) {String s = cards.substring(i, i + 1);
            if (!" ".equals(s)) list.add(new Card(s));
        }
        return builder(list);
    }

}

这个类次要写的是解析牌型的算法 例如我打出 333A 让电脑判断我打的是三带一还是四带二
大部分的牌型还是比拟好判断的 这里就不一一列举了

简略的只挑这一个讲
这个办法能够判断玩家出的这一组牌是不是三带一
首先看一下这条语句 if (groups.get(0).sum == 3 && groups.get(0).num != GameConstants.NUM_JOKER)
groups 是一个列表排序形式是按 sum 从大到小排(list 是按 id 从大到小排)
首先判断最多的那张牌是不是有 3 张 再判断他是不是 3 张王 如果是那就是王炸了 王炸是不能带单排的
如果条件成立 那剩下那张牌就不必管它了 它必定不会和那三张牌一样 也必定只有一张牌
所以说 你带啥都行 不关我事
而后拷贝一个 list 把剩下的那张牌移到最初面
为什么要挪动到最初面呢 把三张一样的放后面另一张不一样的放前面 这样看的是不是难受点?
最初增加进后果集即可

比较复杂的是 is33344412()和 is3334441122()的这两个办法

先看看这个办法 - 飞机带单排:

飞机带翅膀是这游戏最简单的局部了
我的思路是先把大于等于 3 张牌的牌号找进去
例如传进来的牌是 33344412 这是最简略的状况
把大于等于三张的牌取出来失去 333 和 444
判断他们是否间断所以这里机身就是 333444
刚好差剩下的两张牌能够组成飞机带翅膀

下面这种算法曾经能够满足很多种状况了不过还是有很多 bug 的(上面 10 用 0 示意)
例如咱们要打的是 JJJ 000 999 888 777 666 555 333 电脑人就傻了
当然这种状况个别不会呈现 然而我想玩一把每人 50 张牌斗地主的话零碎就会解体
咱们用之前的算法来剖析一下
先把三顺找进去失去 JJJ 000 999 888 777 666 555 而后剩下的 3 张牌无奈组成翅膀啊 组成翅膀要 7 张牌
有没有发现如果我把飞尾的 555 从机身取出来装到机翼上刚好能够组成 JJJ 000 999 888 777 666 带 555 333
其实把 JJJ 取出来当成机翼也是能够的 如果你想切机头的话能够参考下飞机带对子的写法
然而这样写的话出牌就存在不确定性 须要弹出提示框让玩家自行抉择
所以我这里默认切机尾

还没有完
如果咱们传入的牌是 333 444 666 777 888 999 000 JJJ 电脑人又傻了
因为这里有两个三顺一个是 333444 一个是 666777888999000JJJ
按之前的算法电脑只能找到机身 333444 这时候电脑就发话了 你这机身多大本人心里没点数吗还想带 18 张单排?
这样的话咱们就要把每个三顺都存到一个汇合里 让每一个三顺都当一遍机身 失去最优解

如果有发现我没有思考到的状况请看齐全文后 欢送留言评论

再看看这个办法 - 飞机带对子:

飞机带对子写法和飞机带单排大抵类似
不同的中央有:
1. 飞机带单牌的的话如 33344412 咱们是间接把 333444 取出来 而后判断单排的数量是否满足条件
而飞机带对子的话你须要将剩下的牌再做一个判断
如 3334441122 把 333444 取出来后失去两组牌 别离是两张 1 两张 2
只有剩下的牌的数量是偶数就能成立

2. 飞机带对子是须要切飞机头的
为了解决以下两种状况
334445556667777 -> 666555444 77 77 33 切机头
334444555666777 -> 777666555 44 44 33 切机尾
如果应用切机尾的办法那么第一个电脑将辨认不了
切机身的思路大略是这样的 如果只切一个机身那么 333444555 先切掉 555 进行判断 再切 333
如果切两个机身那么 333444555666 先切掉 666555 而后切 666333 再切 444333

构造方法:

让咱们再看看构造方法
为什么 if(is444412())之后的办法不间接 return 呢
因为有些牌型是能够被解析为四带两对和飞机带翅膀的
例如 33334444 能够被解析为 四个 3 带两个对 4 四个 4 带两个对 3 和 333444 带 34 的飞机 当然还能够解析成连炸

我的斗地主规定是参考腾讯欢畅斗地主手游的 欢畅斗地主没有连炸所以我这也没有
据说在斗地主职业较量中打出这种牌型是要玩家指定牌型的 什么斗地主也有打职业的?
而在腾讯的欢畅斗地主中打出 33334444 并没有让玩家指定牌型
会被解析成四带两对 不要问我是怎么晓得的 这个答案是我用豆子换来的
既然腾讯都没有这么做那咱们也不这么做

我的算法是这样的 会把这种有多重牌型的牌存到一个汇合里 (CardProducts 这个类里)
如果上家出的牌是四带两对就 那打出 33334444 就会被解析成四带两对
如果上家出的牌是飞机就 那打出 33334444 就会被解析成飞机
如果是你先出牌 打出 33334444 就会跟腾讯斗地主一样解析成四带两对

而 33334444 到底是被解析为 四个 3 带两个对 4 还是四个 4 带两个对 3 呢 预计没哪个傻子会这么打吧
这里我不好做测试 毕竟豆子无限 能拿到这样牌的机会也不多
而且还要上家也有四带两对能力测进去 十分须要运气成分
所以我把 33334444 默认解析成大的牌带小的牌 即四个 4 带两个对 3

五、后果类和后果集

后果类:

package com.liziguo.ddz;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: Liziguo
 * @Date: 2020/9/13 10:56
 */
public class CardProduct {
    public final List<Card> list;
    public final int type;
    public final Card maxCard;
    public final List<CardGroup> group;

    public CardProduct(List<Card> list, int type, Card maxCard, List<CardGroup> group) {
        this.list = list;
        this.type = type;
        this.maxCard = maxCard;
        this.group = group;
    }

    public boolean isGreaterThan(CardProduct cardProduct) {
        if (type != GameConstants.TYPE_ERROR && type != GameConstants.TYPE_NULL
                && cardProduct.type == GameConstants.TYPE_NULL) {return true;} else if (type == GameConstants.TYPE_BOOM) {if (cardProduct.type == GameConstants.TYPE_BOOM) {if (list.get(0).isJoker() && cardProduct.list.get(0).isJoker()) {
                    // 王炸 炸 王炸
                    if (list.size() == cardProduct.list.size()) {
                        int bigJokerSum1 = 0, bigJokerSum2 = 0;
                        for (Card card : list) {if (card.id == GameConstants.ID_JOKER_2) bigJokerSum1++;
                        }
                        for (Card card : cardProduct.list) {if (card.id == GameConstants.ID_JOKER_2) bigJokerSum2++;
                        }
                        return bigJokerSum1 > bigJokerSum2;
                    } else return list.size() > cardProduct.list.size();
                } else if (list.get(0).isJoker() && !cardProduct.list.get(0).isJoker()) {
                    // 王炸 炸 炸弹
                    return list.size() * 2 >= cardProduct.list.size();
                } else if (!list.get(0).isJoker() && cardProduct.list.get(0).isJoker()) {
                    // 炸弹 炸 王炸
                    return list.size() > cardProduct.list.size() * 2;
                } else if (!list.get(0).isJoker() && !cardProduct.list.get(0).isJoker()) {
                    // 炸弹 炸 炸弹
                    if (list.size() > cardProduct.list.size()) return true;
                    else if (list.size() == cardProduct.list.size()) {return list.get(0).num > cardProduct.list.get(0).num;
                    } else return false;
                }
            } else return true;
        } else if (type == cardProduct.type && list.size() == cardProduct.list.size()) {if (type == GameConstants.TYPE_1 && maxCard.num == GameConstants.NUM_JOKER && cardProduct.maxCard.num == GameConstants.NUM_JOKER) {
                // 因为大小王的 num 都是雷同的 所以比拟大小王的话要比照 id
                return maxCard.id > cardProduct.maxCard.id;
            } else {return maxCard.num > cardProduct.maxCard.num;}
        }
        return false;
    }

    private String typeToString() {switch (type) {
            case GameConstants.TYPE_ERROR:
                return "谬误";
            case GameConstants.TYPE_NULL:
                return "无";
            case GameConstants.TYPE_1:
                return "单牌";
            case GameConstants.TYPE_22:
                return "对子";
            case GameConstants.TYPE_333:
                return "三个";
            case GameConstants.TYPE_BOOM:
                return "炸弹";
            case GameConstants.TYPE_3331:
                return "三带一";
            case GameConstants.TYPE_33322:
                return "三带一对";
            case GameConstants.TYPE_444412:
                return "四带二";
            case GameConstants.TYPE_44441122:
                return "四带两对";
            case GameConstants.TYPE_34567:
                return "顺子";
            case GameConstants.TYPE_334455:
                return "连对";
            case GameConstants.TYPE_333444:
                return "飞机";
            case GameConstants.TYPE_33344412:
                return "飞机带单牌";
            case GameConstants.TYPE_3334441122:
                return "飞机带对子";
        }
        return "未知";
    }

    @Override
    public String toString() {
        return "CardProduct{" +
                "list=" + list +
                ", type=" + typeToString() +
                ", maxCard=" + maxCard +
                ", len=" + list.size() +
                ", group=" + group +
                '}';
    }

    public static CardProduct createNullType() {return new CardProduct(new ArrayList<>(), GameConstants.TYPE_NULL, null, null);
    }

}

这个类很简略 maxCard 并不一定是指最大的那张牌
举个例子吧:

顺子:34567 的 maxCard 是 7
三带一:5556 的 maxCard 是 5
飞机带翅膀:777666A4 的 maxCard 是 7

懂了吧 这个属性是用来比大小的 被带的牌是不会被算上的

isGreaterThan(CardProduct cardProduct)用来比拟大小
这里的炸弹也严格依照欢畅斗地主的规定

四炸 < 双王炸 < 五炸 < 六炸 < 三王炸 < 七炸 < 八炸 < 四王炸
以此类推
并且 [大王, 大王] 是能够打赢 [大王, 小王] 和[小王, 小王]的

后果集:

package com.liziguo.ddz;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: Liziguo
 * @Date: 2020/9/13 13:38
 */
public class CardProducts {
    public final List<CardProduct> list;

    public CardProducts() {list = new ArrayList<>();
    }

    public boolean add(CardProduct product) {return list.add(product);
    }

    public boolean addAll(List<CardProduct> list) {return this.list.addAll(list);
    }

    /**
     * @param product
     * @return 打得过则返回 CardProduct 在 list 里的索引 否则返回 -1
     */
    public int isGreaterThan(CardProduct product) {for (int i = 0; i < list.size(); i++)
            if (list.get(i).isGreaterThan(product))
                return i;
        return -1;
    }

    @Override
    public String toString() {return list.size() + " " + list;
    }
}

这不须要我多做解释了吧
之前将 33334444 的时候讲过了
后果不止一个 所以咱们要弄一个后果集的类
这个类也有 isGreaterThan 这个办法返回值和 CardProduct(后果类)的不一样

如果上家打的是 44433365 你打出 55554444 就会通过这个办法
拿出另外一个后果 飞机 55544454 压上家的牌

六、提醒性能

每个斗地主游戏都有一个提醒性能 依据上一家出的牌从小到大提醒接下来你该怎么打

例:以后扑克牌:[6, K, 2, 小王, 大王] 上家出牌:[A] 提醒:[[2], [小王], [大王], [小王, 大王]]

package com.liziguo.ddz;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author: Liziguo
 * @Date: 2020/9/16 15:57
 */
public class Prompt {

    private final List<Card> list;// 从小到大
    private final List<CardGroup> groups;// 按 num 从小到大
    private final CardProduct last;
    public final List<List<Card>> prompt;

    public Prompt(List<Card> list, CardProduct last) {this.list = new ArrayList<>(list);
        this.groups = CardUtils.createGroup(list);
        // 从小到大排序
        this.list.sort((o1, o2) -> o1.id - o2.id);
        this.groups.sort(Comparator.comparingInt(o -> o.num));

        this.last = last;
        prompt = new ArrayList<>();

        if (last.type == GameConstants.TYPE_ERROR) return;
        else if (last.type == GameConstants.TYPE_NULL) prompt.addAll(findNull());
        else if (last.type == GameConstants.TYPE_1) prompt.addAll(find1(last.maxCard.num, last.maxCard.id));
        else if (last.type == GameConstants.TYPE_22) prompt.addAll(find22(last.maxCard.num));
        else if (last.type == GameConstants.TYPE_333) prompt.addAll(find333(last.maxCard.num));
        else if (last.type == GameConstants.TYPE_3331) prompt.addAll(find3331(last.maxCard.num));
        else if (last.type == GameConstants.TYPE_33322) prompt.addAll(find33322(last.maxCard.num));
        else if (last.type == GameConstants.TYPE_444412) prompt.addAll(find444412(last.maxCard.num));
        else if (last.type == GameConstants.TYPE_44441122) prompt.addAll(find44441122(last.maxCard.num));
        else if (last.type == GameConstants.TYPE_34567) prompt.addAll(find34567(last.maxCard.num, last.list.size()));
        else if (last.type == GameConstants.TYPE_334455) prompt.addAll(find334455(last.maxCard.num, last.list.size()));
        else if (last.type == GameConstants.TYPE_333444) prompt.addAll(find333444(last.maxCard.num, last.list.size()));
        else if (last.type == GameConstants.TYPE_33344412)
            prompt.addAll(find33344412(last.maxCard.num, last.list.size()));
        else if (last.type == GameConstants.TYPE_3334441122)
            prompt.addAll(find3334441122(last.maxCard.num, last.list.size()));

        prompt.addAll(findBoom(last));
    }

    public List<List<Card>> findNull() {
        // 判断能不能一次把所有牌打完 如果能就间接打完
        if (CardsFactory.builder(list).list.get(0).type != GameConstants.TYPE_ERROR) {List<List<Card>> find = new ArrayList<>();
            find.add(list);
            return find;
        }

        // 查找飞机带对子
        if (list.size() > 10) {final int length = list.size() - list.size() % 5;
            for (int i = length; i >= 10; i -= 5) {List<List<Card>> find = find3334441122(null, i);
                if (find.size() > 0) return find;
            }
        }
        // 查找飞机带单排
        if (list.size() > 8) {final int length = list.size() - list.size() % 4;
            for (int i = length; i >= 8; i -= 4) {List<List<Card>> find = find33344412(null, i);
                if (find.size() > 0) return find;
            }
        }
        // 查找飞机
        if (list.size() > 6) {for (int i = list.size() - list.size() % 3; i >= 6; i -= 3) {List<List<Card>> find = find333444(null, i);
                if (find.size() > 0) return find;
            }
            // 查找连对
            for (int i = list.size() - list.size() % 2; i >= 6; i -= 2) {List<List<Card>> find = find334455(null, i);
                if (find.size() > 0) return find;
            }
        }
        if (list.size() > 5) {
            // 查找顺子
            for (int i = list.size() - 1; i >= 5; i -= 1) {List<List<Card>> find = find34567(null, i);
                if (find.size() > 0) return find;
            }
            // 查找三带一对
            List<List<Card>> find = find33322(null);
            if (find.size() > 0) return find;
        }
        if (list.size() > 4) {
            // 查找三带一
            List<List<Card>> find = find3331(null);
            if (find.size() > 0) return find;
        }
        // 最初伎俩
        List<List<Card>> find = new ArrayList<>();
        List<CardGroup> temp = new ArrayList<>();
        List<CardGroup> temp1 = new ArrayList<>();
        for (CardGroup group : groups) {if (group.sum < 4 || (group.num == GameConstants.NUM_JOKER && group.sum < 2)) {temp.add(group);
            } else {temp1.add(group);
            }
        }
        temp.addAll(temp1);
        CardGroup group = temp.get(0);
        find.add(CardUtils.getCardByNum(list, group.num, group.sum));
        return find;
    }

    public List<List<Card>> find1(int maxCardNum, int maxCardId) {List<List<Card>> find = new ArrayList<>();
        List<CardGroup> groups = new ArrayList<>();
        for (CardGroup cardGroup : this.groups) {if (cardGroup.num > maxCardNum) groups.add(cardGroup);
        }
        groups.sort((o1, o2) -> {
            //order by sum desc,num desc
            final int o = o1.sum - o2.sum;
            if (o != 0) return o;
            return o1.num - o2.num;
        });
//        groups.sort(Comparator.comparingInt((CardGroup o) -> o.sum).thenComparingInt(o -> o.num));
        for (CardGroup group : groups) {find.add(CardUtils.getCardByNum(list, group.num, 1));
        }
        if (maxCardId < GameConstants.ID_JOKER_2) {for (Card card : list) {if (card.id == GameConstants.ID_JOKER_2) {List<Card> cards = new ArrayList<>();
                    cards.add(card);
                    find.add(cards);
                    break;
                }
            }
        }
        return find;
    }

    public List<List<Card>> find22(int maxCardNum) {List<List<Card>> find = new ArrayList<>();
        List<CardGroup> groups = new ArrayList<>();
        for (CardGroup cardGroup : this.groups) {if (cardGroup.num > maxCardNum && cardGroup.sum >= 2 && cardGroup.sum < 4 && cardGroup.num != GameConstants.NUM_JOKER)
                groups.add(cardGroup);
        }
        groups.sort((o1, o2) -> {
            //order by sum desc,num desc
            final int o = o1.sum - o2.sum;
            if (o != 0) return o;
            return o1.num - o2.num;
        });
        for (CardGroup group : groups) {find.add(CardUtils.getCardByNum(list, group.num, 2));
        }
        return find;
    }

    public List<List<Card>> find333(int maxCardNum) {List<List<Card>> find = new ArrayList<>();
        List<CardGroup> groups = new ArrayList<>();
        for (CardGroup cardGroup : this.groups) {if (cardGroup.num > maxCardNum && cardGroup.sum == 3 && cardGroup.num != GameConstants.NUM_JOKER)
                groups.add(cardGroup);
        }
        groups.sort((o1, o2) -> {
            //order by sum desc,num desc
            final int o = o1.sum - o2.sum;
            if (o != 0) return o;
            return o1.num - o2.num;
        });
        for (CardGroup group : groups) {find.add(CardUtils.getCardByNum(list, group.num, 3));
        }
        return find;
    }

    public List<List<Card>> findBoom(CardProduct last) {List<List<Card>> find = new ArrayList<>();
        List<CardGroup> booms = new ArrayList<>();
        for (CardGroup cardGroup : groups) {if (cardGroup.num == GameConstants.NUM_JOKER && cardGroup.sum >= 2 || cardGroup.sum >= 4) {booms.add(cardGroup);
            }
        }
        booms.sort((o1, o2) -> {
            final int o;
            if (o1.num == GameConstants.NUM_JOKER) {o = o1.sum * 2 - o2.sum;} else if (o2.num == GameConstants.NUM_JOKER) {o = o1.sum - o2.sum * 2;} else {o = o1.sum - o2.sum;}
            if (o != 0)
                return o;
            return o1.num - o2.num;
        });
        for (CardGroup cardGroup : booms) {find.add(CardUtils.getCardByNum(list, cardGroup.num, cardGroup.sum));
        }
        // 拆
        List<List<Card>> split = new ArrayList<>();
        for (List<Card> boom : find) {if (boom.size() > 4 && boom.get(0).num != GameConstants.NUM_JOKER) {for (int i = 0; i < boom.size() - 4; i++) {
                    // 拆一般炸
                    List<Card> cards = new ArrayList<>(boom);
                    cards.remove(0);
                    for (int j = 0; j < i; j++)
                        cards.remove(cards.size() - 1);
                    split.add(cards);
                }
            } else if (boom.size() > 2 && boom.get(0).num == GameConstants.NUM_JOKER) {
                // 拆王炸
                List<Card> joker1List = new ArrayList<>();
                List<Card> joker2List = new ArrayList<>();
                for (Card card : boom) {if (card.id == GameConstants.ID_JOKER_1)
                        joker1List.add(card);
                    else
                        joker2List.add(card);
                }
                for (int i = 2, len = boom.size(); i < len; i++) {for (int j = 0; j <= i; j++) {// j= 大王数量
                        if (i - j <= joker1List.size() && j <= joker2List.size()) {List<Card> cards = new ArrayList<>();
                            for (int k = 0; k < i - j; k++)
                                cards.add(joker1List.get(k));
                            for (int k = 0; k < j; k++)
                                cards.add(joker2List.get(k));
                            split.add(cards);
                        }
                    }
                }
            }
        }
        find.addAll(split);
        // 只留下打得过的炸
        if (last != null && last.type == GameConstants.TYPE_BOOM) {
            int i = 0;
            while (i < find.size()) {if (CardsFactory.builder(find.get(i)).isGreaterThan(last) < 0) {find.remove(i);
                } else {i++;}
            }
        }
        return find;
    }

    public List<List<Card>> find3331(Integer maxCardNum) {List<List<Card>> find = new ArrayList<>();
        for (CardGroup group : CardUtils.removeJokers(groups)) {if ((maxCardNum == null || group.num > maxCardNum) && group.sum == 3) {List<Card> cards = new ArrayList<>(CardUtils.getCardByNum(list, group.num, 3));
                List<Card> fill = getMinSingleCard(cards, true, 1);
                if (fill.size() == 1) {cards.addAll(fill);
                    find.add(cards);
                }
            }
        }
        return find;
    }

    public List<List<Card>> find33322(Integer maxCardNum) {List<List<Card>> find = new ArrayList<>();
        for (CardGroup group : CardUtils.removeJokers(groups)) {if ((maxCardNum == null || group.num > maxCardNum) && group.sum == 3) {List<Card> cards = new ArrayList<>(CardUtils.getCardByNum(list, group.num, 3));
                List<Card> fill = getMinDoubleCards(cards, true, 1);
                if (fill.size() == 2) {cards.addAll(fill);
                    find.add(cards);
                }
            }
        }
        return find;
    }

    public List<List<Card>> find444412(int maxCardNum) {List<List<Card>> find = new ArrayList<>();
        for (CardGroup group : CardUtils.removeJokers(groups)) {if (group.num > maxCardNum && group.sum == 4) {List<Card> cards = new ArrayList<>(CardUtils.getCardByNum(list, group.num, 4));
                List<Card> fill = getMinSingleCard(cards, true, 2);
                if (fill.size() == 2) {cards.addAll(fill);
                    find.add(cards);
                }
            }
        }
        return find;
    }

    public List<List<Card>> find44441122(int maxCardNum) {List<List<Card>> find = new ArrayList<>();
        for (CardGroup group : CardUtils.removeJokers(groups)) {if (group.num > maxCardNum && group.sum == 4) {List<Card> cards = new ArrayList<>(CardUtils.getCardByNum(list, group.num, 4));
                List<Card> fill = getMinDoubleCards(cards, true, 2);
                if (fill.size() == 4) {cards.addAll(fill);
                    find.add(cards);
                }
            }
        }
        return find;
    }

    public List<List<Card>> find34567(Integer maxCardNum, int len) {List<List<Card>> find = new ArrayList<>();
        List<List<CardGroup>> continuous = new ArrayList<>();
        int start = 0;
        int end = start + 1;
        while (start + len <= groups.size()) {if (groups.get(end).num - groups.get(start).num == end - start && groups.get(end).num < GameConstants.NUM_2
                    && end < groups.size()) {if (end + 1 - start == len) {if (maxCardNum == null || groups.get(end).num > maxCardNum) {List<CardGroup> tempGroups = new ArrayList<>();
                        for (int i = start; i <= end; i++) {tempGroups.add(groups.get(i));
                        }
                        continuous.add(tempGroups);
                    }
                    start++;
                    end = start + 1;
                } else {end++;}
            } else {
                start++;
                end = start + 1;
            }
        }
        for (List<CardGroup> cardGroups : continuous) {List<Card> temp = new ArrayList<>();
            for (CardGroup cardGroup : cardGroups) {temp.add(CardUtils.getCardByNum(list, cardGroup.num));
            }
            find.add(temp);
        }
        return find;
    }

    public List<List<Card>> find334455(Integer maxCardNum, int length) {List<List<Card>> find = new ArrayList<>();
        List<List<CardGroup>> continuous = new ArrayList<>();
        List<CardGroup> ge2AndLt4 = this.groups.stream().filter(cardGroup -> cardGroup.sum >= 2 && cardGroup.sum < 4).sorted(Comparator.comparingInt(o -> o.num)).collect(Collectors.toList());

        int len = length / 2;// len 为打消反复 num 后的长度
        int start = 0;
        int end = start + 1;
        while (start + len <= ge2AndLt4.size()) {if (ge2AndLt4.get(end).num - ge2AndLt4.get(start).num == end - start && ge2AndLt4.get(end).num < GameConstants.NUM_2
                    && end < ge2AndLt4.size()) {if (end + 1 - start == len) {if (maxCardNum == null || ge2AndLt4.get(end).num > maxCardNum) {List<CardGroup> tempGroups = new ArrayList<>();
                        for (int i = start; i <= end; i++) {tempGroups.add(ge2AndLt4.get(i));
                        }
                        continuous.add(tempGroups);
                    }
                    start++;
                    end = start + 1;
                } else {end++;}
            } else {
                start++;
                end = start + 1;
            }
        }
        for (List<CardGroup> cardGroups : continuous) {List<Card> temp = new ArrayList<>();
            for (CardGroup cardGroup : cardGroups) {temp.addAll(CardUtils.getCardByNum(list, cardGroup.num, 2));
            }
            find.add(temp);
        }
        return find;
    }

    public List<List<Card>> find333444(Integer maxCardNum, int length) {List<List<Card>> find = new ArrayList<>();
        List<List<CardGroup>> continuous = new ArrayList<>();
        List<CardGroup> eq3 = groups.stream().filter(cardGroup -> cardGroup.sum == 3).sorted(Comparator.comparingInt(o -> o.num)).collect(Collectors.toList());

        int len = length / 3;// len 为打消反复 num 后的长度
        int start = 0;
        int end = start + 1;
        while (start + len <= eq3.size()) {if (eq3.get(end).num - eq3.get(start).num == end - start && eq3.get(end).num < GameConstants.NUM_2
                    && end < eq3.size()) {if (end + 1 - start == len) {if (maxCardNum == null || eq3.get(end).num > maxCardNum) {List<CardGroup> tempGroups = new ArrayList<>();
                        for (int i = start; i <= end; i++) {tempGroups.add(eq3.get(i));
                        }
                        continuous.add(tempGroups);
                    }
                    start++;
                    end = start + 1;
                } else {end++;}
            } else {
                start++;
                end = start + 1;
            }
        }
        for (List<CardGroup> cardGroups : continuous) {List<Card> temp = new ArrayList<>();
            for (CardGroup cardGroup : cardGroups) {temp.addAll(CardUtils.getCardByNum(list, cardGroup.num, 3));
            }
            find.add(temp);
        }
        return find;
    }

    public List<List<Card>> find33344412(Integer maxCardNum, int length) {List<List<Card>> find = new ArrayList<>();
        List<List<CardGroup>> continuous = new ArrayList<>();
        List<CardGroup> eq3 = groups.stream().filter(cardGroup -> cardGroup.sum == 3).sorted(Comparator.comparingInt(o -> o.num)).collect(Collectors.toList());

        int len = length / 4;// len 为三顺长度 如 333444555 的话 len 就等于 3
        int start = 0;
        int end = start + 1;
        while (start + len <= eq3.size()) {if (eq3.get(end).num - eq3.get(start).num == end - start && eq3.get(end).num < GameConstants.NUM_2 && end < eq3.size()) {if (end + 1 - start == len) {if (maxCardNum == null || eq3.get(end).num > maxCardNum) {List<CardGroup> tempGroups = new ArrayList<>();
                        for (int i = start; i <= end; i++) {tempGroups.add(eq3.get(i));
                        }
                        continuous.add(tempGroups);
                    }
                    start++;
                    end = start + 1;
                } else {end++;}
            } else {
                start++;
                end = start + 1;
            }
        }
        for (List<CardGroup> cardGroups : continuous) {List<Card> temp = new ArrayList<>();
            for (CardGroup cardGroup : cardGroups) {temp.addAll(CardUtils.getCardByNum(list, cardGroup.num, 3));
            }
            List<Card> fill = getMinSingleCard(temp, true, len);
            if (fill.size() == len) {temp.addAll(fill);
                find.add(temp);
            }
        }
        return find;
    }

    public List<List<Card>> find3334441122(Integer maxCardNum, int length) {List<List<Card>> find = new ArrayList<>();
        List<List<CardGroup>> continuous = new ArrayList<>();
        List<CardGroup> eq3 = groups.stream().filter(cardGroup -> cardGroup.sum == 3).sorted(Comparator.comparingInt(o -> o.num)).collect(Collectors.toList());

        int len = length / 5;// len 为三顺长度 如 333444555 的话 len 就等于 3
        int start = 0;
        int end = start + 1;
        while (start + len <= eq3.size()) {if (eq3.get(end).num - eq3.get(start).num == end - start && eq3.get(end).num < GameConstants.NUM_2 && end < eq3.size()) {if (end + 1 - start == len) {if (maxCardNum == null || eq3.get(end).num > maxCardNum) {List<CardGroup> tempGroups = new ArrayList<>();
                        for (int i = start; i <= end; i++) {tempGroups.add(eq3.get(i));
                        }
                        continuous.add(tempGroups);
                    }
                    start++;
                    end = start + 1;
                } else {end++;}
            } else {
                start++;
                end = start + 1;
            }
        }
        for (List<CardGroup> cardGroups : continuous) {List<Card> temp = new ArrayList<>();
            for (CardGroup cardGroup : cardGroups) {temp.addAll(CardUtils.getCardByNum(list, cardGroup.num, 3));
            }
            List<Card> fill = getMinDoubleCards(temp, true, len);
            if (fill.size() == len * 2) {temp.addAll(fill);
                find.add(temp);
            }
        }
        return find;
    }

    /**
     * 获取最小单牌
     *
     * @param notIn
     * @param removeAll 为 false 时只删除雷同的牌 为 true 时删除 num 相等的牌
     * @param len       获取的单排数量 最多返回 len 张牌 也可能一张都不返回
     * @return
     */

    public List<Card> getMinSingleCard(List<Card> notIn, boolean removeAll, int len) {List<Card> result = new ArrayList<>();
        List<Card> temp;
        if (removeAll) {temp = list.stream().filter(card -> notIn.stream().noneMatch(card1 -> card.num == card1.num)).collect(Collectors.toList());
        } else {temp = new ArrayList<>(list);
            temp.removeAll(notIn);
        }
        List<CardGroup> groups = CardUtils.createGroup(temp);
        groups.sort(Comparator.comparingInt((CardGroup o) -> o.sum).thenComparingInt(o -> o.num));// order by sum,num
        int index = 0;
        while (result.size() < len && index < groups.size()) {CardGroup cardGroup = groups.get(index);
            if (cardGroup.sum > 0) {
                cardGroup.sum--;
                Card card = CardUtils.getCardByNum(list, cardGroup.num);
                result.add(card);
            } else
                index++;
        }
        return result;
    }

    /**
     * 获取最小对子(不包含大小王)
     *
     * @param notIn
     * @param removeAll 为 false 时只删除雷同的牌 为 true 时删除 num 相等的牌
     * @param len       获取的对子数量 最多返回 len* 2 张牌 也可能一张都不返回
     * @return
     */
    public List<Card> getMinDoubleCards(List<Card> notIn, boolean removeAll, int len) {List<Card> result = new ArrayList<>();
        List<Card> temp;
        // 获取对子不能蕴含对王
        if (removeAll) {temp = list.stream().filter(card -> card.num != GameConstants.NUM_JOKER && notIn.stream().noneMatch(card1 -> card.num == card1.num)).collect(Collectors.toList());
        } else {temp = list.stream().filter(card -> card.num != GameConstants.NUM_JOKER && notIn.stream().noneMatch(card1 -> card == card1)).collect(Collectors.toList());
        }
        List<CardGroup> groups = CardUtils.createGroup(temp);
        groups.sort(Comparator.comparingInt((CardGroup o) -> o.sum).thenComparingInt(o -> o.num));// order by sum,num
        if (groups.size() > 0) {
            int index = 0;
            while (result.size() < len * 2 && index < groups.size()) {CardGroup cardGroup = groups.get(index);
                if (cardGroup.sum >= 2) {
                    cardGroup.sum -= 2;
                    List<Card> cards = CardUtils.getCardByNum(list, cardGroup.num, 2);
                    result.addAll(cards);
                } else
                    index++;
            }
        }
        return result;
    }

    @Override
    public String toString() {return "以后扑克牌:" + list + "上家出牌:" + last.list + "提醒(" + prompt.size() + "):" + prompt;
    }

}

提醒算法和判断牌型的算法是差不多的 这里就挑最简略的一个飞机带翅膀的算法来讲

通过变量 length 确定变量 len(机身长度)。例:44433365 的机身长度是 2
而后在本身的扑克牌里寻找三顺 并存到一个汇合里
如果上家出的是 44433365 我以后的扑克牌有 44455566678
就会找到两组三顺 [444555,555666]而后调取 getMinSingleCard 办法从剩下的牌里 [6678]
找到零碎认为最没用那两张单排
所以最终后果就是:
以后扑克牌:[4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 8] 上家出牌:[4, 4, 4, 3, 3, 3, 6, 5] 提醒:[[4, 4, 4, 5, 5, 5, 7, 8], [5, 5, 5, 6, 6, 6, 7, 8]]

七、测试类

package com.liziguo.ddz;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: Liziguo
 * @Date: 2020/9/14 11:03
 */
public class CardTest {private static void typeTest() {System.out.println("---------------------------------- 单排 ----------------------------------");
        System.out.println(CardsFactory.builder("3"));
        System.out.println(CardsFactory.builder("4"));
        System.out.println(CardsFactory.builder("5"));
        System.out.println(CardsFactory.builder("6"));
        System.out.println(CardsFactory.builder("7"));
        System.out.println(CardsFactory.builder("8"));
        System.out.println(CardsFactory.builder("9"));
        System.out.println(CardsFactory.builder("0"));
        System.out.println(CardsFactory.builder("J"));
        System.out.println(CardsFactory.builder("Q"));
        System.out.println(CardsFactory.builder("K"));
        System.out.println(CardsFactory.builder("A"));
        System.out.println(CardsFactory.builder("2"));
        System.out.println(CardsFactory.builder("C"));
        System.out.println("---------------------------------- 对子 ----------------------------------");
        System.out.println(CardsFactory.builder("33"));
        System.out.println(CardsFactory.builder("44"));
        System.out.println(CardsFactory.builder("55"));
        System.out.println(CardsFactory.builder("66"));
        System.out.println(CardsFactory.builder("77"));
        System.out.println(CardsFactory.builder("88"));
        System.out.println(CardsFactory.builder("99"));
        System.out.println(CardsFactory.builder("00"));
        System.out.println(CardsFactory.builder("JJ"));
        System.out.println(CardsFactory.builder("QQ"));
        System.out.println(CardsFactory.builder("KK"));
        System.out.println(CardsFactory.builder("AA"));
        System.out.println(CardsFactory.builder("22"));
        System.out.println(CardsFactory.builder("CC") + "炸弹");
        System.out.println("---------------------------------- 3 个 ----------------------------------");
        System.out.println(CardsFactory.builder("333"));
        System.out.println(CardsFactory.builder("444"));
        System.out.println(CardsFactory.builder("555"));
        System.out.println(CardsFactory.builder("666"));
        System.out.println(CardsFactory.builder("777"));
        System.out.println(CardsFactory.builder("888"));
        System.out.println(CardsFactory.builder("999"));
        System.out.println(CardsFactory.builder("000"));
        System.out.println(CardsFactory.builder("JJJ"));
        System.out.println(CardsFactory.builder("QQQ"));
        System.out.println(CardsFactory.builder("KKK"));
        System.out.println(CardsFactory.builder("AAA"));
        System.out.println(CardsFactory.builder("222"));
        System.out.println(CardsFactory.builder("CCC") + "炸弹");
        System.out.println("---------------------------------- 4 个 ----------------------------------");
        System.out.println(CardsFactory.builder("3333"));
        System.out.println(CardsFactory.builder("4444"));
        System.out.println(CardsFactory.builder("5555"));
        System.out.println(CardsFactory.builder("6666"));
        System.out.println(CardsFactory.builder("7777"));
        System.out.println(CardsFactory.builder("8888"));
        System.out.println(CardsFactory.builder("9999"));
        System.out.println(CardsFactory.builder("0000"));
        System.out.println(CardsFactory.builder("JJJJ"));
        System.out.println(CardsFactory.builder("QQQQ"));
        System.out.println(CardsFactory.builder("KKKK"));
        System.out.println(CardsFactory.builder("AAAA"));
        System.out.println(CardsFactory.builder("2222"));
        System.out.println(CardsFactory.builder("CCCC"));
        System.out.println("---------------------------------- 5 个 ----------------------------------");
        System.out.println(CardsFactory.builder("33333"));
        System.out.println(CardsFactory.builder("44444"));
        System.out.println(CardsFactory.builder("55555"));
        System.out.println(CardsFactory.builder("66666"));
        System.out.println(CardsFactory.builder("77777"));
        System.out.println(CardsFactory.builder("88888"));
        System.out.println(CardsFactory.builder("99999"));
        System.out.println(CardsFactory.builder("00000"));
        System.out.println(CardsFactory.builder("JJJJJ"));
        System.out.println(CardsFactory.builder("QQQQQ"));
        System.out.println(CardsFactory.builder("KKKKK"));
        System.out.println(CardsFactory.builder("AAAAA"));
        System.out.println(CardsFactory.builder("22222"));
        System.out.println(CardsFactory.builder("CCCCC"));
        System.out.println("---------------------------------- 6 个 ----------------------------------");
        System.out.println(CardsFactory.builder("333333"));
        System.out.println(CardsFactory.builder("444444"));
        System.out.println(CardsFactory.builder("555555"));
        System.out.println(CardsFactory.builder("666666"));
        System.out.println(CardsFactory.builder("777777"));
        System.out.println(CardsFactory.builder("888888"));
        System.out.println(CardsFactory.builder("999999"));
        System.out.println(CardsFactory.builder("000000"));
        System.out.println(CardsFactory.builder("JJJJJJ"));
        System.out.println(CardsFactory.builder("QQQQQQ"));
        System.out.println(CardsFactory.builder("KKKKKK"));
        System.out.println(CardsFactory.builder("AAAAAA"));
        System.out.println(CardsFactory.builder("222222"));
        System.out.println(CardsFactory.builder("CCCCCC"));
        System.out.println("---------------------------------- 7 个 ----------------------------------");
        System.out.println(CardsFactory.builder("3333333"));
        System.out.println(CardsFactory.builder("4444444"));
        System.out.println(CardsFactory.builder("5555555"));
        System.out.println(CardsFactory.builder("6666666"));
        System.out.println(CardsFactory.builder("7777777"));
        System.out.println(CardsFactory.builder("8888888"));
        System.out.println(CardsFactory.builder("9999999"));
        System.out.println(CardsFactory.builder("0000000"));
        System.out.println(CardsFactory.builder("JJJJJJJ"));
        System.out.println(CardsFactory.builder("QQQQQQQ"));
        System.out.println(CardsFactory.builder("KKKKKKK"));
        System.out.println(CardsFactory.builder("AAAAAAA"));
        System.out.println(CardsFactory.builder("2222222"));
        System.out.println(CardsFactory.builder("CCCCCCC"));
        System.out.println("---------------------------------- 8 个 ----------------------------------");
        System.out.println(CardsFactory.builder("33333333"));
        System.out.println(CardsFactory.builder("44444444"));
        System.out.println(CardsFactory.builder("55555555"));
        System.out.println(CardsFactory.builder("66666666"));
        System.out.println(CardsFactory.builder("77777777"));
        System.out.println(CardsFactory.builder("88888888"));
        System.out.println(CardsFactory.builder("99999999"));
        System.out.println(CardsFactory.builder("00000000"));
        System.out.println(CardsFactory.builder("JJJJJJJJ"));
        System.out.println(CardsFactory.builder("QQQQQQQQ"));
        System.out.println(CardsFactory.builder("KKKKKKKK"));
        System.out.println(CardsFactory.builder("AAAAAAAA"));
        System.out.println(CardsFactory.builder("22222222"));
        System.out.println(CardsFactory.builder("CCCCCCCC"));
        System.out.println("---------------------------------- 三带一 ----------------------------------");
        System.out.println(CardsFactory.builder("3331"));
        System.out.println(CardsFactory.builder("4442"));
        System.out.println(CardsFactory.builder("5553"));
        System.out.println(CardsFactory.builder("6664"));
        System.out.println(CardsFactory.builder("7775"));
        System.out.println(CardsFactory.builder("8886"));
        System.out.println(CardsFactory.builder("9997"));
        System.out.println(CardsFactory.builder("0008"));
        System.out.println(CardsFactory.builder("JJJ9"));
        System.out.println(CardsFactory.builder("QQQ0"));
        System.out.println(CardsFactory.builder("KKKJ"));
        System.out.println(CardsFactory.builder("AAAQ"));
        System.out.println(CardsFactory.builder("222K"));
        System.out.println(CardsFactory.builder("CCC1") + "谬误");
        System.out.println("---------------------------------- 三带一对 ----------------------------------");
        System.out.println(CardsFactory.builder("33311"));
        System.out.println(CardsFactory.builder("44422"));
        System.out.println(CardsFactory.builder("55533"));
        System.out.println(CardsFactory.builder("66644"));
        System.out.println(CardsFactory.builder("77755"));
        System.out.println(CardsFactory.builder("88866"));
        System.out.println(CardsFactory.builder("99977"));
        System.out.println(CardsFactory.builder("00088"));
        System.out.println(CardsFactory.builder("JJJ99"));
        System.out.println(CardsFactory.builder("QQQ00"));
        System.out.println(CardsFactory.builder("KKKJJ"));
        System.out.println(CardsFactory.builder("AAAQQ"));
        System.out.println(CardsFactory.builder("222KK"));
        System.out.println(CardsFactory.builder("CCC11") + "谬误");
        System.out.println(CardsFactory.builder("JcJCJ") + "不能带对王");
        System.out.println(CardsFactory.builder("222K1") + "不是对子");
        System.out.println("---------------------------------- 四带二 ----------------------------------");
        System.out.println(CardsFactory.builder("444412"));
        System.out.println(CardsFactory.builder("444466"));
        System.out.println(CardsFactory.builder("444445"));
        System.out.println(CardsFactory.builder("4444Cc"));
        System.out.println("---------------------------------- 四带两对 ----------------------------------");
        System.out.println(CardsFactory.builder("44441122"));
        System.out.println(CardsFactory.builder("44446666"));
        System.out.println(CardsFactory.builder("44444455"));
        System.out.println(CardsFactory.builder("444466Cc"));
        System.out.println(CardsFactory.builder("4444Cc33"));
        System.out.println("---------------------------------- 顺子 ----------------------------------");
        System.out.println(CardsFactory.builder("34567"));
        System.out.println("---------------------------------- 连对 ----------------------------------");
        System.out.println(CardsFactory.builder("334455"));
        System.out.println("---------------------------------- 飞机 ----------------------------------");
        System.out.println(CardsFactory.builder("333444"));
        System.out.println("---------------------------------- 飞机带单排 ----------------------------------");
        System.out.println(CardsFactory.builder("33 555666777 7"));
        System.out.println(CardsFactory.builder("333444555666"));
        System.out.println(CardsFactory.builder("33334444") + "飞机 / 四带两对");
        System.out.println(CardsFactory.builder("33334445"));
        System.out.println(CardsFactory.builder("33344445"));
        System.out.println(CardsFactory.builder("33344455"));
        System.out.println(CardsFactory.builder("33344456"));
        System.out.println(CardsFactory.builder("333444555777"));
        System.out.println(CardsFactory.builder("333555666777"));
        System.out.println(CardsFactory.builder("222555666777"));
        System.out.println(CardsFactory.builder("333444555444"));
        System.out.println(CardsFactory.builder("222111KKKQQQ"));
        System.out.println(CardsFactory.builder("333444555666"));
        System.out.println(CardsFactory.builder("333 555 666 777 888 999 000 JJJ"));
        System.out.println(CardsFactory.builder("333 555 666 777 888 999 000 QQQ"));
        System.out.println(CardsFactory.builder("633 555 666 777 888 999 000 QQQ"));
        System.out.println(CardsFactory.builder("333 444 666 777 888 999 000 JJJ"));
        System.out.println(CardsFactory.builder("JJJ 000 888 777 666 555 444 333"));
        System.out.println(CardsFactory.builder("222AAAKKK JJJ000999888777666555444333"));
        System.out.println(CardsFactory.builder("333 444 555 666 777 888 999 000 JJJ QQQ KKK AAA"));
        System.out.println("--------------------------------- 飞机带对子 ---------------------------------");
        System.out.println(CardsFactory.builder("334445556667777") + "头切");
        System.out.println(CardsFactory.builder("334444555666777") + "尾切");
        System.out.println(CardsFactory.builder("334455 555666777"));
        System.out.println(CardsFactory.builder("384455 555666777") + "谬误");
        System.out.println(CardsFactory.builder("33334444455566677777") + "飞机带单双");
        System.out.println(CardsFactory.builder("444555666777888999 9447733") + "飞机带单双");
        System.out.println(CardsFactory.builder("33334444 555666777888"));
        System.out.println(CardsFactory.builder("33334444 666777888999"));
        System.out.println(CardsFactory.builder("333444555666 88889999"));
        System.out.println(CardsFactory.builder("3333344455"));
        System.out.println(CardsFactory.builder("3334444455"));
        System.out.println(CardsFactory.builder("3344444555"));
    }

    private static void outCardTest() {
        //TODO 55554444 压 44445566 和 33334445
        //TODO 444555666777 压 333444555777
        System.out.println("--------------------------------- 胜利区 上面不能呈现 -1---------------------------------");
        System.out.println(CardsFactory.builder("C").isGreaterThan(CardsFactory.builder("c").list.get(0)));
        System.out.println(CardsFactory.builder("C").isGreaterThan(CardsFactory.builder("2").list.get(0)));
        System.out.println(CardsFactory.builder("c").isGreaterThan(CardsFactory.builder("1").list.get(0)));
        System.out.println(CardsFactory.builder("77").isGreaterThan(CardsFactory.builder("66").list.get(0)));
        System.out.println(CardsFactory.builder("CC").isGreaterThan(CardsFactory.builder("Cc").list.get(0)));
        System.out.println(CardsFactory.builder("Cc").isGreaterThan(CardsFactory.builder("cc").list.get(0)));
        System.out.println(CardsFactory.builder("CC").isGreaterThan(CardsFactory.builder("cc").list.get(0)));

        System.out.println(CardsFactory.builder("55554444").isGreaterThan(CardsFactory.builder("44445656").list.get(0)));
        System.out.println(CardsFactory.builder("55554444").isGreaterThan(CardsFactory.builder("33334445").list.get(0)));
        System.out.println(CardsFactory.builder("444555666777").isGreaterThan(CardsFactory.builder("333444555777").list.get(0)));
        System.out.println("--------------------------------- 失败区 上面只能呈现 -1---------------------------------");
        // 黑桃 6 压方块 6 测试
        Card card4 = new Card(GameConstants.ID_6_4);
        Card card1 = new Card(GameConstants.ID_6_1);
        List<Card> list1 = new ArrayList<>();
        list1.add(card4);
        List<Card> list2 = new ArrayList<>();
        list2.add(card1);
        System.out.println(CardsFactory.builder(list1).isGreaterThan(CardsFactory.builder(list2).list.get(0)));
        System.out.println(CardsFactory.builder(list2).isGreaterThan(CardsFactory.builder(list1).list.get(0)));
        System.out.println(CardsFactory.builder("6").isGreaterThan(CardsFactory.builder("6").list.get(0)));
        System.out.println(CardsFactory.builder("66").isGreaterThan(CardsFactory.builder("66").list.get(0)));
        System.out.println(CardsFactory.builder("Cc").isGreaterThan(CardsFactory.builder("cC").list.get(0)));
    }

    private static void prompt() {System.out.println("---------------------------------- 单牌 ----------------------------------");
        // 独自提醒 小王大王 优先提醒单牌 出小王提醒大王
        System.out.println(new Prompt(CardUtils.CreateCards("34567890JQKA2cC"), CardsFactory.builder("5").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("3300JQQKA22Cc"), CardsFactory.builder("5").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("Cc2k6"), CardsFactory.builder("A").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("Cc654"), CardsFactory.builder("c").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("Cc654"), CardsFactory.builder("C").list.get(0)));
        System.out.println("---------------------------------- 对子 ----------------------------------");
        System.out.println(new Prompt(CardUtils.CreateCards("3344556677889900JJQQKKA22ccCC"), CardsFactory.builder("55").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("8888000JJQQQKKKKAA222cCC"), CardsFactory.builder("55").list.get(0)));
        System.out.println("---------------------------------- 三个 ----------------------------------");
        System.out.println(new Prompt(CardUtils.CreateCards("77788899"), CardsFactory.builder("888").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("777888999"), CardsFactory.builder("888").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("77778888000ccc"), CardsFactory.builder("888").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("77778888000CCC"), CardsFactory.builder("888").list.get(0)));
        System.out.println("---------------------------------- 炸弹 ----------------------------------");
        System.out.println("---------------------------------- 三带一 ----------------------------------");
        System.out.println(new Prompt(CardUtils.CreateCards("555666c"), CardsFactory.builder("4441").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("CCC6"), CardsFactory.builder("4441").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("33334444555666777"), CardsFactory.builder("4441").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("333456cccCCC777"), CardsFactory.builder("4441").list.get(0)));
        System.out.println("---------------------------------- 三带一对 ----------------------------------");
        System.out.println(new Prompt(CardUtils.CreateCards("555666cC"), CardsFactory.builder("44411").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("33334444555666777"), CardsFactory.builder("44422").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("333445566cccCCC777"), CardsFactory.builder("444133").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("333445566cccCCC777"), CardsFactory.builder("4441CC").list.get(0)));
        System.out.println("---------------------------------- 四带二 ----------------------------------");
        System.out.println(new Prompt(CardUtils.CreateCards("44446666"), CardsFactory.builder("555512").list.get(0)));
        System.out.println("---------------------------------- 四带两队 ----------------------------------");
        System.out.println(new Prompt(CardUtils.CreateCards("444455556666"), CardsFactory.builder("33334444").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("4444455556666"), CardsFactory.builder("33334444").list.get(0)));//TODO
        System.out.println("---------------------------------- 顺子 ----------------------------------");
        System.out.println(new Prompt(CardUtils.CreateCards("34567890JQKA2cC"), CardsFactory.builder("34567").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("34567890JQKA2cC"), CardsFactory.builder("345678").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("34567890JQKA2cC"), CardsFactory.builder("3456789").list.get(0)));
        System.out.println("---------------------------------- 连对 ----------------------------------");
        System.out.println(new Prompt(CardUtils.CreateCards("34567890JQKA234567890JQKA2cC"), CardsFactory.builder("334455").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("34567890JQKA234567890JQKA2cC"), CardsFactory.builder("33445566").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("34567890JQKA234567890JQKA2cC"), CardsFactory.builder("3344556677").list.get(0)));
        System.out.println("---------------------------------- 飞机 ----------------------------------");
        System.out.println(new Prompt(CardUtils.CreateCards("34567890JQKA234567890JQKA234567890JQKA2cC"), CardsFactory.builder("333444").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("34567890JQKA234567890JQKA234567890JQKA2cC"), CardsFactory.builder("333444555").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("34567890JQKA234567890JQKA234567890JQKA2cC"), CardsFactory.builder("333444555666").list.get(0)));
        System.out.println("---------------------------------- 飞机带单牌 ----------------------------------");
        System.out.println(new Prompt(CardUtils.CreateCards("44455566678"), CardsFactory.builder("44433365").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("444555666"), CardsFactory.builder("33344456").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("333444666777888"), CardsFactory.builder("33344456").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("4444555666789"), CardsFactory.builder("33344456").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("4445556666"), CardsFactory.builder("33344456").list.get(0)));
        System.out.println("---------------------------------- 飞机带对子 ----------------------------------");
        System.out.println(new Prompt(CardUtils.CreateCards("777666Cc3344"), CardsFactory.builder("3334445566").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("34567890JQKA234567890JQKA234567890JQKA2cC"), CardsFactory.builder("3334445566").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("34567890JQKA234567890JQKA234567890JQKA2cC"), CardsFactory.builder("333444555112244").list.get(0)));
        System.out.println(new Prompt(CardUtils.CreateCards("34567890JQKA234567890JQKA234567890JQKA2cC"), CardsFactory.builder("33344455566611227788").list.get(0)));
        System.out.println("----------------------------------NULL----------------------------------");
        System.out.println(new Prompt(CardUtils.CreateCards("66778"), CardProduct.createNullType()));
    }

    public static void main(String[] args) {typeTest();
        outCardTest();
        prompt();}

}

而后你就会失去一个这个货色

有急躁的话看下后果有没有错吧

八、最初

和电脑来一场缓和刺激的 solo 吧

package com.liziguo.ddz;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Play {

    private static List<Card> player;
    private static List<Card> bot;
    private static CardProduct last = CardProduct.createNullType();

    /**
     * 发牌
     *
     * @param sum         多少副牌
     * @param contains345 是否蕴含 345
     */
    public static void licensing(int sum, boolean contains345) {player = new ArrayList<>();
        bot = new ArrayList<>();
        ArrayList<Integer> list = new ArrayList<>();
        for (int i = 0; i < sum; i++) {for (int j = contains345 ? GameConstants.ID_3_1 : GameConstants.ID_6_1; j < 54; j++) {list.add(j);
            }
        }
        while (list.size() > 0) {player.add(new Card(list.remove((int) (Math.random() * list.size()))));
            bot.add(new Card(list.remove((int) (Math.random() * list.size()))));
        }
        player.sort((o1, o2) -> o2.id - o1.id);
        bot.sort((o1, o2) -> o2.id - o1.id);
    }

    public static List<Integer> searchIndexByNum(List<Card> list, List<Card> card) {if (card.size() > list.size()) return null;
        int[] cardNum = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {cardNum[i] = list.get(i).num;
        }
        List<Integer> indexes = new ArrayList<>();
        for (int i = 0; i < card.size(); i++) {if (card.get(i).num > GameConstants.NUM_2) {final int id = card.get(i).id;
                for (int j = 0; j < list.size(); j++) {if (card.get(i).id == list.get(j).id && !indexes.contains(j)) {indexes.add(j);
                        break;
                    }
                }
            } else {for (int j = 0; j < cardNum.length; j++) {if (card.get(i).num == cardNum[j] && !indexes.contains(j)) {indexes.add(j);
                        break;
                    }
                }
            }
        }
        if (indexes.size() != card.size()) return null;
        return indexes;
    }

    public static void main(String[] args) {licensing(1, false);
        System.out.println("您的扑克牌:" + player);
        System.out.println("电脑扑克牌:" + bot);
        boolean playing = true;
        boolean toMe = Math.random() < 0.5;
        Scanner scanner = new Scanner(System.in);
        while (playing) {System.out.println("=======================================================================");
            if (toMe) {System.out.println("上家出牌:" + last);
                System.out.println("您以后的扑克牌:" + player);
                System.out.println("请您出牌:(输出. 不出 输出? 提醒 输出, 偷看电脑的牌)");
                String line = scanner.nextLine();
                if (line == null || line.length() == 0) continue;
                else if (".".equals(line)) {//                    if (last.type==GameConstants.TYPE_NULL)
                    toMe = !toMe;
                    last = CardProduct.createNullType();
                    continue;
                } else if ("?".equals(line)) {System.out.println("提醒:" + new Prompt(player, last).prompt);
                    continue;
                } else if (",".equals(line)) {System.out.println("电脑以后扑克牌:" + bot);
                    continue;
                }
                List<Integer> indexes = searchIndexByNum(player, CardUtils.CreateCards(line));
                if (indexes == null) {System.out.println("您输出的扑克牌有效请从新输出");
                    continue;
                }
                CardProducts cardProducts = CardsFactory.builder(CardUtils.getCardsByIndexes(player, indexes));
                int index = cardProducts.isGreaterThan(last);
                if (index >= 0) {CardProduct newCardProduct = cardProducts.list.get(index);
                    last = newCardProduct;
                    player.removeAll(last.list);
                    System.out.println("出牌胜利:" + last);
                    if (player.size() == 0) {System.out.println("你赢啦!");
                        playing = false;
                    }
                    toMe = !toMe;
                } else {System.out.println("不合乎游戏规则:" + cardProducts);
                    continue;
                }
            } else {System.out.println("电脑以后扑克牌:" + bot);
                Prompt prompt = new Prompt(bot, last);
                if (prompt.prompt.size() > 0) {CardProducts cardProducts = CardsFactory.builder(prompt.prompt.get(0));
                    int index = cardProducts.isGreaterThan(last);
                    if (index >= 0) {last = cardProducts.list.get(index);
                        bot.removeAll(last.list);
                        System.out.println("电脑出牌:" + last.list);
                        if (bot.size() == 0) {System.out.println("你输啦!");
                            playing = false;
                        }
                        toMe = !toMe;
                        continue;
                    }
                    System.out.println("异样:prompt.prompt.size() > 0 且 cardProducts.isGreaterThan(last) < 0");
                    System.out.println(prompt);
                    System.out.println(cardProducts);
                    return;
                } else {System.out.println("电脑不要");
                    last = CardProduct.createNullType();
                    toMe = !toMe;
                }

            }
        }
    }

}

图片起源:http://www.lyouxi.com/ 游戏盒子

正文完
 0