24点破解的Java实现

一、基本思想


要想计算24点游戏的结果,则必须要采用基于搜索的算法(即穷举法)对每种情况进行遍历,我们怎么样才能遍历所有的情况呢?其实我们只要总结一下,还是有规律可以找的。

输入a、b、c、d,组成a Op1 bOp2 c Op3 d的表达式,其中先算哪个子表达式未知,一共有5种计算方式,如下图所示:

         

 
此时如果要实现该程序,需要存储5棵树,为了能够使得存储量达到最小,通过分析,其实总的来说,只需要存储2棵树即可,即:

其他树都是冗余的,因为我们可以通过a、b、c、d的交换,比如((a+(b*c))+d)可以变为(((b*c)+a)+d);
对于每棵树来说,abcd的可能性为4*3*2*1=24;op1op2 op3的可能性为4*4*4=64,因此总个数为1536,而两棵树的总个数为3072。因此只需要穷举这些方法,就可以知道结果。

TfUtils类为实现穷举24点所有可能情况的类,calculate函数用于计算,参数a、b、c、d分别为给定的4个数,而TfUtils类中的expr属性为求解的表达式。


二、代码实现


CalculatorUtils.java

[java]  view plain copy
  1. package org.xiazdong;  
  2.   
  3. import java.util.Stack;  
  4.   
  5. public class CalculatorUtils {  
  6.   
  7.     /** 
  8.      * 计算后缀表达式 
  9.      */  
  10.     public static String calculateReversePolish(String str) {  
  11.   
  12.         String[] splitStr = str.split(" ");  
  13.         Stack<String> s = new Stack<String>();  
  14.         for (int i = 0; i < splitStr.length; i++) {  
  15.             String ch = splitStr[i];  
  16.             if (ch.matches("\\d+.\\d+")||ch.matches("\\d+")) {  
  17.                 s.push(ch);  
  18.             } else {  
  19.                 if (s.size() >= 2) {  
  20.                     String c1 = s.pop();  
  21.                     String c2 = s.pop();  
  22.                     if (ch.equals("+")) {  
  23.                         if(c1.contains(".")||c2.contains(".")){  
  24.                             s.push(String.valueOf((Double.parseDouble(c2 + "") + Double  
  25.                                 .parseDouble(c1 + ""))));  
  26.                         }  
  27.                         else{  
  28.                             s.push(String.valueOf((Integer.parseInt(c2 + "") + Integer  
  29.                                     .parseInt(c1 + ""))));  
  30.                         }  
  31.                           
  32.                     } else if ("-".equals(ch)) {  
  33.                         if(c1.contains(".")||c2.contains(".")){  
  34.                         s.push(String.valueOf((Double.parseDouble(c2 + "") - Double  
  35.                                 .parseDouble(c1 + ""))));  
  36.                         }  
  37.                         else{  
  38.                             s.push(String.valueOf((Integer.parseInt(c2 + "") - Integer  
  39.                                     .parseInt(c1 + ""))));  
  40.                         }  
  41.                     } else if ("*".equals(ch)) {  
  42.                         if(c1.contains(".")||c2.contains(".")){  
  43.                         s.push(String.valueOf((Double.parseDouble(c2 + "") * Double  
  44.                                 .parseDouble(c1 + ""))));  
  45.                         }  
  46.                         else{  
  47.                             s.push(String.valueOf((Integer.parseInt(c2 + "") * Integer  
  48.                                     .parseInt(c1 + ""))));  
  49.                         }  
  50.                     } else if ("/".equals(ch)) {  
  51.                         s.push(String.valueOf((Double.parseDouble(c2 + "") / Double  
  52.                                 .parseDouble(c1 + ""))));  
  53.                     }  
  54.   
  55.                 } else {  
  56.                     System.out.println("式子有问题!");  
  57.                     return null;  
  58.                 }  
  59.             }  
  60.         }  
  61.         return s.pop();  
  62.     }  
  63. }  

TfUtils.java


[java]  view plain copy
  1. package org.xiazdong;  
  2.   
  3. import java.io.Serializable;  
  4.   
  5. public class TfUtils implements Serializable{  
  6.     private int result;  
  7.     private String expr = "";   //存放中缀表达式  
  8.       
  9.     public String getExpr() {  
  10.         return expr;  
  11.     }  
  12.   
  13.     public void setExpr(String expr) {  
  14.         this.expr = expr;  
  15.     }  
  16.   
  17.     /* 
  18.                         (操作符1) 
  19.                         /      \  
  20.                    (操作符2) (操作数4)  
  21.                    /     \  
  22.               (操作符3)  (操作数3)  
  23.                /     \  
  24.           (操作数1) (操作数2) 
  25.      */  
  26.     private int tree1[] = new int[7];; // 存放第一棵树  
  27.     //private int tree2[]; // 存放第二棵树  
  28.     private final int PLUS = 1// 加  
  29.     private final int MINUS = 2// 减  
  30.     private final int MULT = 3// 乘  
  31.     private final int DIV = 4// 除  
  32.   
  33.     /** 
  34.      * 计算24点的主函数 
  35.      */  
  36.     public void calculate(int a, int b, int c, int d) {  
  37.   
  38.         int data[] = { a, b, c, d };  
  39.   
  40.           
  41.         // 1.用数组构建一棵树,其中0,1,3处填操作符;2,4,5,6填充操作数  
  42.         // 2.按照参数a,b,c,d不同顺序填充树,+-*/也填充  
  43.         for (int h = 0; h < 4; h++) {  
  44.             for (int i = 0; i < 4; i++) {  
  45.                 if (i == h) {  
  46.                     continue;  
  47.                 }  
  48.                 for (int j = 0; j < 4; j++) {  
  49.                     if (j == i || j == h) {  
  50.                         continue;  
  51.                     }  
  52.                     for (int k = 0; k < 4; k++) {  
  53.                         if (k == h || k == i || k == j) {  
  54.                             continue;  
  55.                         }  
  56.                         tree1[2] = data[h];  
  57.                         tree1[4] = data[i];  
  58.                         tree1[5] = data[j];  
  59.                         tree1[6] = data[k];  
  60.   
  61.                         // 填充操作符  
  62.                         for (int m = PLUS; m <= DIV; m++) {  
  63.                             for (int n = PLUS; n <= DIV; n++) {  
  64.                                 for (int o = PLUS; o <= DIV; o++) {  
  65.                                     tree1[0] = m;  
  66.                                     tree1[1] = n;  
  67.                                     tree1[3] = o;  
  68.                                     String t[] = new String[4];  
  69.                                     for (int z = 0; z < 4; z++) {  
  70.                                         switch (tree1[z]) {  
  71.                                         case PLUS:  
  72.                                             t[z] = "+";  
  73.                                             break;  
  74.                                         case MINUS:  
  75.                                             t[z] = "-";  
  76.                                             break;  
  77.                                         case MULT:  
  78.                                             t[z] = "*";  
  79.                                             break;  
  80.                                         case DIV:  
  81.                                             t[z] = "/";  
  82.                                             break;  
  83.                                         }  
  84.                                     }  
  85.   
  86.                                     // 目前为止tree数组全部已赋值  
  87.                                     String postexpr = tree1[5] + " " + tree1[6]  
  88.                                             + " " + t[3] + " " + tree1[4] + " "  
  89.                                             + t[1] + " " + tree1[2] + " " + t[0];  
  90.                                     String result = CalculatorUtils  
  91.                                             .calculateReversePolish(postexpr);  
  92.                                     if (Double.parseDouble((result)) == 24.0) {  
  93.                                         expr = "(((" + tree1[5] + t[3] + tree1[6]  
  94.                                                 + ")" + t[1] + tree1[4] + ")"  
  95.                                                 + t[0] + tree1[2] + ")";  
  96.                                         System.out.println(expr);  
  97.                                         return;  
  98.                                     }  
  99.                                 }  
  100.                             }  
  101.                         }  
  102.                     }  
  103.                 }  
  104.             }  
  105.         }  
  106.         //tree2 = new int[7];  
  107.         for (int h = 0; h < 4; h++) {  
  108.             for (int i = 0; i < 4; i++) {  
  109.                 if (i == h) {  
  110.                     continue;  
  111.                 }  
  112.                 for (int j = 0; j < 4; j++) {  
  113.                     if (j == i || j == h) {  
  114.                         continue;  
  115.                     }  
  116.                     for (int k = 0; k < 4; k++) {  
  117.                         if (k == h || k == i || k == j) {  
  118.                             continue;  
  119.                         }  
  120.                         tree1[3] = data[h];  
  121.                         tree1[4] = data[i];  
  122.                         tree1[5] = data[j];  
  123.                         tree1[6] = data[k];  
  124.   
  125.                         // 填充操作符  
  126.                         for (int m = PLUS; m <= DIV; m++) {  
  127.                             for (int n = PLUS; n <= DIV; n++) {  
  128.                                 for (int o = PLUS; o <= DIV; o++) {  
  129.                                     tree1[0] = m;  
  130.                                     tree1[1] = n;  
  131.                                     tree1[2] = o;  
  132.                                     String t[] = new String[3];  
  133.                                     for (int z = 0; z < 3; z++) {  
  134.                                         switch (tree1[z]) {  
  135.                                         case PLUS:  
  136.                                             t[z] = "+";  
  137.                                             break;  
  138.                                         case MINUS:  
  139.                                             t[z] = "-";  
  140.                                             break;  
  141.                                         case MULT:  
  142.                                             t[z] = "*";  
  143.                                             break;  
  144.                                         case DIV:  
  145.                                             t[z] = "/";  
  146.                                             break;  
  147.                                         }  
  148.                                     }  
  149.                                     // 目前为止tree数组全部已赋值  
  150.                                     String postexpr = tree1[4] + " " + tree1[3]  
  151.                                             + " " + t[1] + " " + tree1[6] + " "  
  152.                                             + tree1[5] + " " + t[2] + " " + t[0];  
  153.                                     String result = CalculatorUtils  
  154.                                             .calculateReversePolish(postexpr);  
  155.                                     if (Double.parseDouble((result)) == 24.0) {  
  156.                                         expr = "((" + tree1[3] + t[1] + tree1[4]  
  157.                                                 + ")" + t[0] +"("+tree1[5]  
  158.                                                 + t[2] + tree1[6] + "))";  
  159.                                         System.out.println(expr);  
  160.                                         return;  
  161.                                     }  
  162.                                 }  
  163.                             }  
  164.                         }  
  165.                     }  
  166.                 }  
  167.             }  
  168.         }  
  169.         expr = "无解";  
  170.     }  
  171.   
  172.     public int getResult() {  
  173.         return result;  
  174.     }  
  175.   
  176.     public void setResult(int result) {  
  177.         this.result = result;  
  178.     }  
  179.   
  180.   
  181.       
  182. }  

测试代码:

[html]  view plain copy
  1. TfUtils tf = new TfUtils();  
  2. tf.calculate(d1, d2, d3, d4);  
  3. System.out.println(tf.getExpr());  

输入为:3,3,7,7

输出为:(((3/7)+3)*7)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值