科技颠覆者 发表于 2023-2-26 11:01:46

张昌蒲 严教 卡牌计算器

1.描述
  玩过三国杀的朋友应该都知道有个将叫张昌蒲,他会随机给出N张卡牌,卡牌的点数在1-13之间,可能重复。现在要求把卡牌分为两堆,两边卡牌的点数之和必须相等,要求两堆的卡牌数之和尽量多。
  针对这个逻辑,我自己写了一些JAVA的实现,经过测试可行,下面给出代码,有兴趣的朋友可以看看,有改进的地方欢迎指出!
2.代码如下
计算分配方式的代码:
1 public class CalculateCard {
2
3   public static void main(String[] args) {
4         Scanner scanner = new Scanner(System.in);
5         System.out.println("请输入严教牌,按点数,以空格割开,如(13 11 10):");
6         String input = scanner.nextLine();
7         System.out.println(input);
8         String[] inputCards = input.split(" ");
9         List<Integer> list = new ArrayList<>();
10         try {
11             Arrays.stream(inputCards).forEach(card -> list.add(Integer.parseInt(card)));
12         }catch (NumberFormatException e) {
13             System.out.println("请输入数字,牌的点数在1-13");
14         }
15         AtomicBoolean isCorrect = new AtomicBoolean(true);
16         list.forEach(item -> isCorrect.set(item <= 13 && item >= 1));
17         if(!isCorrect.get()){
18             System.out.println("----请输入数字,牌的点数在1-13");
19         }
20         calculateAll(list);
21   }
22
23   /**
24      * 计算所有可能的分配方式,并找到使用卡牌最多的组合方式
25      * @param list 所有输入的数字
26      */
27   private static void calculateAll(List<Integer> list){
28         List<Pair<Integer,Pair<String,String>>> okResult = new ArrayList<>();
29         List<Pair<Integer,Pair<String,String>>> okResultLast = new ArrayList<>();
30         List<Pair<Integer,Pair<Integer,String>>> result = new ArrayList<>();
31         //获取所有的数字组合方式
32         getAllComb(list,result);
33         int countNum = 0;
34         //遍历所有组合方式
35         for (int i = 0; i < result.size(); i++) {
36             /*
37            * 思路
38            * 1.取出其中一种组合,拿到这个组合的点数和sum
39            * 2.将当前组合中的所有数字放在一个List--currentList中
40            * 3.从原来得包含所有点数的卡牌集合中筛选出去掉currentList所有数字的其他数字,放在listLeft中
41            * 5.获得listLeft中所有数字的全部组合方式,放在result1中
42            * 6.遍历result1,比对总和与sum是否相等,相等则为一种成功的组合方式。
43            * 7.找到成功组合中使用卡牌最多的组合方式
44            */
45             Pair<Integer,Pair<Integer,String>> pair = result.get(i);
46             int sum = pair.getValue().getKey();
47             int numCount = pair.getKey();
48             String com = pair.getValue().getValue();
49             String[] numStr = com.split(",");
50             List<Integer> listLeft = new ArrayList<>();
51             List<Integer> currentList = new ArrayList<>();
52             for (int j = 0; j < numStr.length; j++) {
53               currentList.add(Integer.parseInt(numStr));
54             }
55             for (int j = 0; j < list.size(); j++) {
56               if(!currentList.contains(list.get(j))) listLeft.add(list.get(j));
57             }
58             List<Pair<Integer,Pair<Integer,String>>> result1 = new ArrayList<>();
59             getAllComb(listLeft,result1);
60             for (int j = 0; j < result1.size(); j++) {
61               Pair<Integer,Pair<Integer,String>> pair1 = result1.get(j);
62               int leftSum = pair1.getValue().getKey();
63               int leftCount = pair1.getKey();
64               String com1 = pair1.getValue().getValue();
65               countNum = countNum == 0 ? numCount + leftCount : countNum;
66               if(leftSum == sum && countNum <= numCount + leftCount){
67                     //计数,如果组合中的数字个数更大,则移除结果集,重新添加,只保存最多的
68                     if(countNum != 0 && countNum < numCount+leftCount){
69                         countNum = numCount + leftCount;
70                         okResultLast.clear();
71                     }
72                     okResult.add(new Pair<>(numCount+leftCount,new Pair<>(com,com1)));
73                     okResultLast.add(new Pair<>(numCount+leftCount,new Pair<>(com,com1)));
74               }
75             }
76         }
77 //      System.out.println("所有组合:");
78 //      for (int i = 0; i < okResult.size(); i++) {
79 //            Pair<Integer,Pair<String,String>> resultPair = okResult.get(i);
80 //            System.out.println("组合的总牌数:"+resultPair.getKey() +
81 //                  "===>组合1为:" + resultPair.getValue().getKey() +
82 //                  "===>组合2为:" + resultPair.getValue().getValue());
83 //      }
84         System.out.println("=================================================");
85         System.out.println("使用卡牌最多的组合方式:");
86         System.out.println("=================================================");
87         for (int i = 0; i < okResultLast.size(); i++) {
88             Pair<Integer,Pair<String,String>> resultPair = okResultLast.get(i);
89             System.out.println("当前分配方"+i+"式总牌数:"+resultPair.getKey() +
90                              "\n====>堆一卡牌点数分别为:" + resultPair.getValue().getKey() +
91                              "\n====>堆二卡牌点数分别为:" + resultPair.getValue().getValue());
92         }
93         System.out.println("=================================================");
94   }
95
96   /**
97      * 获得所有可能的组合
98      * 如数字列表为:【1,2,3】
99      * 那么得到的所有组合为【1】,【2】,【3】,【1,2】,【1,3】,【2,3】,【1,2,3】
100      * @param list 所有数字
101      * @param result 返回的组合集合
102      */
103   private static void getAllComb(List<Integer> list,List<Pair<Integer,Pair<Integer,String>>> result){
104         List<String> com = new ArrayList<>();
105         for (int i = 1; i != list.size() + 1; i++) {
106             ComputCombinations.getCombination(result,list,0,i,com);
107         }
108 //      result.stream().forEach(item -> System.out.println("数字数:"+ item.getKey()+
109 //                "=====>总值:"+ item.getValue().getKey()+ " 内容:" + item.getValue().getValue()));
110   }
111
112 }计算数字组合方式的代码:
public static void getCombination(List<Pair<Integer,Pair<Integer,String>>> result,
                                                    List<Integer> list, int start, int len , List<String> com){
      if(len == 0){
            String s = "";
            for (int i = 0; i != com.size() ; i++) {
                s = s.concat(com.get(i));
            }
            String comStr = s.substring(0,s.length() - 1);
            String[] all = comStr.split(",");
            AtomicInteger sum = new AtomicInteger();
            Arrays.stream(all).forEach(item -> sum.addAndGet(Integer.parseInt(item)));
            result.add(new Pair<>(com.size(),new Pair<>(sum.get(),comStr)));
            return;
      }
      if(start == list.size()){
            return;
      }
      com.add(list.get(start)+",");
      getCombination(result,list, start+1,len - 1,com);
      com.remove(com.size()-1);
      getCombination(result,list,start+1,len,com);
    }测试结果:
 https://img2023.cnblogs.com/blog/2065820/202302/2065820-20230226103809422-678095169.png
有可以改进的地方,欢迎指出...

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 张昌蒲 严教 卡牌计算器