以前用Python写过24点:传送门 。现在重新参照以前的思路用Java来写,结果发现很多问题。这里重新说一下完整的思路:
24 点的计算式主要有两种情况:
前言:先遍历由4个数全排列而得到的(List<int[]>
,每一次得到由4个数组成的int[]
,对这4个数:
第一种情况:第一个数和第二个数运算,结果记为 S12 , S12 和第三个数运算,结果记为S123 ,最后 S123 和第四个数运算,得到最终的运算值。
注意点:S12 和第三个数的运算,要考虑它们的先后位置,比如25-1 和1-25是不同的。同理, S123 也一样。
第二种情况:第一个数和第二个数运算,结果记为 S12 ;然后第三个数和第四个数运算,结果记为 S34 ,最后S12和S34运算,即得到最终的运算值。
注意点:这里不用考虑两个数运算之间的先后顺序,因为这些数都是全排列得到的数,而不是 “新数”
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
CalcOf24 game = new CalcOf24();
int[] n = game.getFourNum(); // 通过键盘输入4个数
List<int[]> L = game.permutations(n); // 全排列
if(!game.calcWayOne(L)) { // 第一种情况
if(!game.calcWayTwo(L)) { // 第二种情况
System.out.println("无解!");
}
}
}
}
/**
* 24点游戏设计类
* @author pytn
*
*/
class CalcOf24{
/**
* 4个数的全排列函数,但没有去除重复的元素,即不管4个数中是否有相同值,列表长度总是 4*3*2*1 个。但这不影响计算出24点
* @param n
*/
public List<int[]> permutations(int[] n){
List<int[]> list = new ArrayList<>();
for(int i=0; i<n.length; i++) {
for(int j=0;j<n.length; j++) {
if(j != i) {
for(int k=0; k<n.length; k++) {
if(k != i && k != j) {
for(int z=0; z<n.length; z++) {
if(z != i && z != j && z != k) {
int[] num = new int[4];
num[0] = n[i];
num[1] = n[j];
num[2] = n[k];
num[3] = n[z];
list.add(num);
}
}
}
}
}
}
}
return list;
}
// 通过键盘输入4个数
public int[] getFourNum() {
int[] num = new int[4];
String pattern = "[1-9]+\\d*"; // 匹配任何大于零的整数
while(true) {
boolean flag = false;
String result;
String[] nums = {"a","b","c","d"};
@SuppressWarnings("resource")
Scanner scanner = new Scanner(System.in);
for(int i=0; i<nums.length; i++) {
System.out.printf("请输入%s:", nums[i]);
result = scanner.nextLine();
if(Pattern.matches(pattern, result)) {
num[i] = Integer.parseInt(result);
}else {
System.out.println("输入有误,请正确输入大于零的整数");
flag = true;
break;
}
}
if(flag) {
continue;
}else {
break;
}
}
return num;
}
/**
* 第一种情况
* 即实现 ((a⊕b)⊕c)⊕d、(c⊕(a⊕b))⊕d、d⊕((a⊕b)⊕c)、d⊕(c⊕(a⊕b))的形式
* @param L
*/
public boolean calcWayOne(List<int[]> L) {
String[] symbols1= {"+", "-", "-", "*", "/", "/"};
String[] symbols2= {"+", "-", "*", "/"};
for(int[] num : L) {
float a = num[0];
float b = num[1];
float c = num[2];
float d = num[3];
float[] list2 = {a+b, a-b, a*b, a/b};
float[] list3;
float[] list4;
for(int i=0; i<list2.length; i++) {
if(list2[i] == 0) {
list3 = new float[] {list2[i]+c, list2[i]-c, c-list2[i], list2[i]*c, list2[i]/c};
}else {
list3 = new float[] {list2[i]+c, list2[i]-c, c-list2[i], list2[i]*c, list2[i]/c, c/list2[i]};
}
for(int j=0; j<list3.length; j++) {
if(list3[j] == 0) {
list4 = new float[] {list3[j]+d, list3[j]-d, d-list3[j], list3[j]*d, list3[j]/d};
}else {
list4 = new float[] {list3[j]+d, list3[j]-d, d-list3[j], list3[j]*d, list3[j]/d, d/list3[j]};
}
for(int k=0; k<list4.length; k++) {
if(Math.abs(list4[k]-24) < 1e-5 && list4[i] > 0) {
String equation3 = null;
String equation4 = null;
String equation2 = "(" + (int)a + symbols2[i] + (int)b + ")";
if(j == 2 || j == 5) {
equation3 = "(" + (int)c + symbols1[j] + equation2 + ")";
}else {
equation3 = "(" + equation2 + symbols1[j] + (int)c + ")";
}
if(k == 2 || k == 5) {
equation4 = (int)d + symbols1[k] + equation3;
}else {
equation4 = equation3 + symbols1[k] + (int)d;
}
System.out.println(equation4);
return true;
}
}
}
}
}
return false;
}
/**
* 实现 (a⊕b)⊕(c⊕d) 的形式
* @param L
*/
public boolean calcWayTwo(List<int[]> L) {
String[] symbols= {"+", "-", "*", "/"};
for(int[] num : L) {
float a = num[0];
float b = num[1];
float c = num[2];
float d = num[3];
float[] list2 = {a+b, a-b, a*b, a/b};
float[] list3 = {c+d, c-d, c*d, c/d};
float[] list4;
for(int i=0; i<list2.length; i++) {
for(int j=0; j<list3.length; j++) {
if(list3[j] == 0) {
list4 = new float[] {list2[i]+list3[j], list2[i]-list3[j], list2[i]*list3[j]};
}else {
list4 = new float[] {list2[i]+list3[j], list2[i]-list3[j], list2[i]*list3[j], list2[i]/list3[j]};
}
for(int k=0; k<list4.length; k++) {
if(Math.abs(list4[k]-24) < 1e-5 && list4[i] > 0) {
String equation2 = "(" + (int)a + symbols[i] + (int)b + ")";
String equation3 = "(" + (int)c + symbols[j] + (int)d + ")";
String equation4 = equation2 + symbols[k] + equation3;
System.out.println(equation4);
return true;
}
}
}
}
}
return false;
}
}