歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> 24點破解的Java實現

24點破解的Java實現

日期:2017/3/1 10:15:56   编辑:Linux編程

一、基本思想

要想計算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

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

TfUtils.java

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

測試代碼:

  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)

Copyright © Linux教程網 All Rights Reserved