java斗地主游戏开发 算法思路讲解

在这里插入图片描述

上学期刚开学的时候我特别沉迷于斗地主 充了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;
				}

			}
		}
	}

}

在这里插入图片描述

我竟然输给了我自己。。。

创作不易 求关注点赞收藏
转载请注明出处

  • 18
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值