24点运算2
这是本人2年前业余时间写的application版本的24点游戏的简单实现。共享出来,希望能起到抛砖引玉的作用,一起探讨24点的实现。
1、计算方式的改变——引入分数计算概念
求24点涉及到除法,所以必须转变直接计算的思路。经过一段时间的摸索,本人发现可以采用分数计算。任何两个数的计算都可以转换成对应的分数计算形式。
例如:3 / 8 可以转换成 (3/1) / (8/1)
1.1 待计算数字的初始化
于是待计算的4个值必须先转换成分数:
- private int[] aArray = new int[2];
- private int[] bArray = new int[2];
- private int[] cArray = new int[2];
- private int[] dArray = new int[2];
当然,我们得初始化它们: 效果就是2->2/ 1
- aArray[0] = a;
- aArray[1] = 1;
- bArray[0] = b;
- bArray[1] = 1;
- cArray[0] = c;
- cArray[1] = 1;
- dArray[0] = d;
- dArray[1] = 1;
1.2 分数的计算
小学的时候就学过,分数的加减法用到最小公倍数和最大公约数。
- /**
- * 求最小公倍数
- *
- * @param a
- * @param b
- * @return
- */
- public int leaseCommonMultiple(int a, int b) {
- return a * b / greatestCommonDivisor(a, b);
- }
- /**
- * 求最大公约数
- *
- * @param a
- * @param b
- * @return
- */
- public int greatestCommonDivisor(int a, int b) {
- if (0 == a && 0 == b) {
- return 1;
- }
- if (0 == a) {
- return b;
- }
- if (0 == b) {
- return a;
- }
- if (a > b) {
- int c = a;
- a = b;
- b = c;
- }
- for (int c = a % b; c > 0; c = a % b) {
- a = b;
- b = c;
- }
- return b;
- }
对应的加减方法如下:
- /**
- * 加
- */
- public int[] plus(int[] a, int[] b) {
- if (0 == a[1]) {
- return new int[] { 0, 0 };
- }
- if (0 == b[1]) {
- return new int[] { 0, 0 };
- }
- int denominator = leaseCommonMultiple(a[1], b[1]);
- return new int[] {
- denominator / a[1] * a[0] + denominator / b[1] * b[0],
- denominator };
- }
- /**
- * 减
- *
- * @param a
- * @param b
- * @return
- */
- public int[] reduce(int[] a, int[] b) {
- if (0 == a[1]) {
- return new int[] { 0, 0 };
- }
- if (0 == b[1]) {
- return new int[] { 0, 0 };
- }
- int denominator = leaseCommonMultiple(a[1], b[1]);
- return new int[] {
- denominator / a[1] * a[0] - denominator / b[1] * b[0],
- denominator };
- }
相对来说,乘除方法就简单多了:
- /**
- * 乘
- *
- * @param a
- * @param b
- * @return
- */
- public int[] multiply(int[] a, int[] b) {
- return new int[] { a[0] * b[0], a[1] * b[1] };
- }
- /**
- * 除
- *
- * @param a
- * @param b
- * @return
- */
- public int[] divide(int[] a, int[] b) {
- return new int[] { a[0] * b[1], a[1] * b[0] };
- }
2、计算规则
2.1 算法——穷举法
24点的计算涉及到以下三种元素:
待计算的4个数、三个计算符号(加减乘除)、括号
本人采用的是穷举法,进行一个一个数值和符号的尝试——这样的话,在循环中数值和符号都必须是动态的。
- /**
- * 动态加载符号数
- * @param i
- * @param a
- * @param b
- * @return
- */
- public int[] dispose(int i, int a[], int[] b){
- if(i == 0){
- return plus(a, b);
- }else if(i == 1){
- return reduce(a, b);
- }else if(i == 2){
- return multiply(a, b);
- }else{
- return divide(a, b);
- }
- }
- /**
- * 动态加载计算数
- * @param i
- * @param a
- * @param b
- * @param c
- * @param d
- * @return
- */
- public int[] number(int i, int[] a, int[] b, int[] c, int[] d){
- if(i == 0){
- return a;
- }else if(i == 1){
- return b;
- }else if(i == 2){
- return c;
- }else if(i == 3){
- return d;
- }else{
- return new int[]{0,1};
- }
- }
2.2 括号规则:
类型1:A(A(A(a,b),c),d)
类型2:A(A(a,A(b,c)),d)
类型3:A(a,A(b,A(c,d)))
类型4:A(a,A(A(b,c),d))
类型5:A(A(a,b),A(c,d))
注:A就是1个符号,A(a,b)就是指:a+b, a-b, a*b, a/b四种情况
2.3 数值与符号的穷举
把每个数值和符号一个进行尝试:
i,j,k :符号
m,n,o,p :数值
- for(int i = 0; i < 4; i++){
- for(int j = 0; j < 4; j++){
- for(int k = 0; k < 4; k++){
- for(int m = 0; m < 4; m++){
- for(int n = 0; n < 4; n++){
- if(n == m)
- continue;
- for(int o = 0; o < 4; o++){
- if(o == m || o == n)
- continue;
- for(int p = 0; p < 4; p++){
- if(p == m || p == n || p == o)
- continue;
- 。。。 计算方法。。。
- }
- }
- }
- }
- }
- }
- }
计算方法:
- //类型1:A(A(A(a,b),c),d)
- int[] result1 = dispose(k,dispose(j,dispose(i,number(m,a,b,c,d),number(n,a,b,c,d)),number(o,a,b,c,d)),number(p,a,b,c,d));
- //类型2:A(A(a,A(b,c)),d)
- int[] result2 = dispose(k,dispose(i,number(m,a,b,c,d),dispose(j,number(n,a,b,c,d),number(o,a,b,c,d))),number(p,a,b,c,d));
- //类型3:A(a,A(b,A(c,d)))
- int[] result3 = dispose(i,number(m,a,b,c,d),dispose(j,number(n,a,b,c,d),dispose(k,number(o,a,b,c,d),number(p,a,b,c,d))));
- //类型4:A(a,A(A(b,c),d))
- int[] result4 = dispose(i,number(m,a,b,c,d),dispose(k,dispose(j,number(n,a,b,c,d),number(o,a,b,c,d)),number(p,a,b,c,d)));
- //类型5:A(A(a,b),A(c,d))
- int[] result5 = dispose(j,dispose(i,number(m,a,b,c,d),number(n,a,b,c,d)),dispose(k,number(o,a,b,c,d),number(p,a,b,c,d)));
- if (0 != result1[1]) {
- if (result1[0] % result1[1] == 0) {
- if (result1[0] / result1[1] == 24) {
- if ((!map.containsKey(new Integer(i)))|| (!map.containsKey(new Integer(j)))|| (!map.containsKey(new Integer(k)))) {
- map.put(new Integer(i),new Integer(i));
- map.put(new Integer(j),new Integer(j));
- map.put(new Integer(k),new Integer(k));
- count += 1;
- System.out.println("((" + printNumber(m) + printSymbol(i) + printNumber(n) + ")" + printSymbol(j) + printNumber(o) + ")" + printSymbol(k) + printNumber(p));
- }
- }
- }
- }
- if (0 != result2[1]) {
- if (result2[0] % result2[1] == 0) {
- if (result2[0] / result2[1] == 24) {
- if ((!map.containsKey(new Integer(i)))|| (!map.containsKey(new Integer(j)))|| (!map.containsKey(new Integer(k)))) {
- map.put(new Integer(i),new Integer(i));
- map.put(new Integer(j),new Integer(j));
- map.put(new Integer(k),new Integer(k));
- count += 1;
- System.out.println("(" + printNumber(m) + printSymbol(i) +"(" + printNumber(n) + printSymbol(j) + printNumber(o) + "))" + printSymbol(k) + printNumber(p));
- }
- }
- }
- }
- if (0 != result3[1]) {
- if (result3[0] % result3[1] == 0) {
- if (result3[0] / result3[1] == 24) {
- if ((!map.containsKey(new Integer(i))) || (!map.containsKey(new Integer(j)))|| (!map.containsKey(new Integer(k)))) {
- map.put(new Integer(i),new Integer(i));
- map.put(new Integer(j),new Integer(j));
- map.put(new Integer(k),new Integer(k));
- count += 1;
- System.out.println(printNumber(m) + printSymbol(i) +"(" + printNumber(n) + printSymbol(j) + "(" + printNumber(o) + printSymbol(k) + printNumber(p) + "))");
- }
- }
- }
- }
- if (0 != result4[1]) {
- if (result4[0] % result4[1] == 0) {
- if (result4[0] / result4[1] == 24) {
- if ((!map
- .containsKey(new Integer(i)))|| (!map.containsKey(new Integer(j)))|| (!map.containsKey(new Integer(k)))) {
- map.put(new Integer(i),new Integer(i));
- map.put(new Integer(j),new Integer(j));
- map.put(new Integer(k),new Integer(k));
- count += 1;
- System.out.println(printNumber(m) + printSymbol(i) +"((" + printNumber(n) + printSymbol(j) + printNumber(o) + ")" + printSymbol(k) + printNumber(p) + ")");
- }
- }
- }
- }
- if (0 != result5[1]) {
- if (result5[0] % result5[1] == 0) {
- if (result5[0] / result5[1] == 24) {
- if ((!map.containsKey(new Integer(i)))|| (!map.containsKey(new Integer(j)))|| (!map.containsKey(new Integer(k)))) {
- map.put(new Integer(i),new Integer(i));
- map.put(new Integer(j),new Integer(j));
- map.put(new Integer(k),new Integer(k));
- count += 1;
- System.out.println("(" + printNumber(m) + printSymbol(i) + printNumber(n) + ")" + printSymbol(j) + "(" + printNumber(o) + printSymbol(k) + printNumber(p) + ")");
- }
- }
- }
- }
该程序目前存在的一些问题:
1)、存在括号多余的情况——如:1 + (2 + (3 * 7))和((2 + 7) - 1) * 3
2)、结果打印耦合在核心计算方法中
具体代码:
package com.chanson; /* * @date Aug 3, 2006 * @project 学习 * @company 个人 * @author chanson * @version 1.0 */ import java.util.HashMap; public class TwentyFour { private int[] aArray = new int[2]; private int[] bArray = new int[2]; private int[] cArray = new int[2]; private int[] dArray = new int[2]; /** * main方法 * * @param args */ public static void main(String[] args) { new TwentyFour().dispose(3, 3, 8, 8); } public void dispose(int a, int b, int c, int d){ aArray[0] = a; aArray[1] = 1; bArray[0] = b; bArray[1] = 1; cArray[0] = c; cArray[1] = 1; dArray[0] = d; dArray[1] = 1; core(aArray, bArray, cArray, dArray); } /** * 加 */ public int[] plus(int[] a, int[] b){ if(0 == a[1]){ return new int[]{0,0}; } if(0 == b[1]){ return new int[]{0,0}; } int denominator = leaseCommonMultiple(a[1],b[1]); return new int[]{denominator/a[1]*a[0] + denominator/b[1]*b[0] ,denominator}; } /** * 减 * @param a * @param b * @return */ public int[] reduce(int[] a, int[] b){ if(0 == a[1]){ return new int[]{0,0}; } if(0 == b[1]){ return new int[]{0,0}; } int denominator = leaseCommonMultiple(a[1],b[1]); return new int[]{denominator/a[1]*a[0] - denominator/b[1]*b[0] ,denominator}; } /** * 乘 * @param a * @param b * @return */ public int[] multiply(int[] a, int[] b){ return new int[]{a[0] * b[0], a[1] * b[1]}; } /** * 除 * @param a * @param b * @return */ public int[] divide(int[] a, int[] b){ return new int[]{a[0] * b[1], a[1] * b[0]}; } /** * 求最小公倍数 * @param a * @param b * @return */ public int leaseCommonMultiple(int a, int b){ return a*b/greatestCommonDivisor(a,b); } /** * 求最大公约数 * @param a * @param b * @return */ public int greatestCommonDivisor(int a, int b) { if(0 == a && 0 == b){ return 1; } if (0 == a) { return b; } if (0 == b) { return a; } if (a > b) { int c = a; a = b; b = c; } for (int c = a % b; c > 0; c = a % b) { a = b; b = c; } return b; } /** * 动态加载符号数 * @param i * @param a * @param b * @return */ public int[] dispose(int i, int a[], int[] b){ if(i == 0){ return plus(a, b); }else if(i == 1){ return reduce(a, b); }else if(i == 2){ return multiply(a, b); }else{ return divide(a, b); } } /** * 动态加载计算数 * @param i * @param a * @param b * @param c * @param d * @return */ public int[] number(int i, int[] a, int[] b, int[] c, int[] d){ if(i == 0){ return a; }else if(i == 1){ return b; }else if(i == 2){ return c; }else if(i == 3){ return d; }else{ return new int[]{0,1}; } } /** * 核心算法部分 * @param a * @param b * @param c * @param d */ private void core(int[] a, int[] b, int[] c, int[] d) { HashMap map = new HashMap(); int count = 0; for(int i = 0; i < 4; i++){ for(int j = 0; j < 4; j++){ for(int k = 0; k < 4; k++){ for(int m = 0; m < 4; m++){ for(int n = 0; n < 4; n++){ if(n == m) continue; for(int o = 0; o < 4; o++){ if(o == m || o == n) continue; for(int p = 0; p < 4; p++){ if(p == m || p == n || p == o) continue; //类型1:A(A(A(a,b),c),d) int[] result1 = dispose(k,dispose(j,dispose(i,number(m,a,b,c,d),number(n,a,b,c,d)),number(o,a,b,c,d)),number(p,a,b,c,d)); //类型2:A(A(a,A(b,c)),d) int[] result2 = dispose(k,dispose(i,number(m,a,b,c,d),dispose(j,number(n,a,b,c,d),number(o,a,b,c,d))),number(p,a,b,c,d)); //类型3:A(a,A(b,A(c,d))) int[] result3 = dispose(i,number(m,a,b,c,d),dispose(j,number(n,a,b,c,d),dispose(k,number(o,a,b,c,d),number(p,a,b,c,d)))); //类型4:A(a,A(A(b,c),d)) int[] result4 = dispose(i,number(m,a,b,c,d),dispose(k,dispose(j,number(n,a,b,c,d),number(o,a,b,c,d)),number(p,a,b,c,d))); //类型5:A(A(a,b),A(c,d)) int[] result5 = dispose(j,dispose(i,number(m,a,b,c,d),number(n,a,b,c,d)),dispose(k,number(o,a,b,c,d),number(p,a,b,c,d))); if (0 != result1[1]) { if (result1[0] % result1[1] == 0) { if (result1[0] / result1[1] == 24) { if ((!map.containsKey(new Integer(i)))|| (!map.containsKey(new Integer(j)))|| (!map.containsKey(new Integer(k)))) { map.put(new Integer(i),new Integer(i)); map.put(new Integer(j),new Integer(j)); map.put(new Integer(k),new Integer(k)); count += 1; System.out.println("((" + printNumber(m) + printSymbol(i) + printNumber(n) + ")" + printSymbol(j) + printNumber(o) + ")" + printSymbol(k) + printNumber(p)); } } } } if (0 != result2[1]) { if (result2[0] % result2[1] == 0) { if (result2[0] / result2[1] == 24) { if ((!map.containsKey(new Integer(i)))|| (!map.containsKey(new Integer(j)))|| (!map.containsKey(new Integer(k)))) { map.put(new Integer(i),new Integer(i)); map.put(new Integer(j),new Integer(j)); map.put(new Integer(k),new Integer(k)); count += 1; System.out.println("(" + printNumber(m) + printSymbol(i) +"(" + printNumber(n) + printSymbol(j) + printNumber(o) + "))" + printSymbol(k) + printNumber(p)); } } } } if (0 != result3[1]) { if (result3[0] % result3[1] == 0) { if (result3[0] / result3[1] == 24) { if ((!map.containsKey(new Integer(i))) || (!map.containsKey(new Integer(j)))|| (!map.containsKey(new Integer(k)))) { map.put(new Integer(i),new Integer(i)); map.put(new Integer(j),new Integer(j)); map.put(new Integer(k),new Integer(k)); count += 1; System.out.println(printNumber(m) + printSymbol(i) +"(" + printNumber(n) + printSymbol(j) + "(" + printNumber(o) + printSymbol(k) + printNumber(p) + "))"); } } } } if (0 != result4[1]) { if (result4[0] % result4[1] == 0) { if (result4[0] / result4[1] == 24) { if ((!map .containsKey(new Integer(i)))|| (!map.containsKey(new Integer(j)))|| (!map.containsKey(new Integer(k)))) { map.put(new Integer(i),new Integer(i)); map.put(new Integer(j),new Integer(j)); map.put(new Integer(k),new Integer(k)); count += 1; System.out.println(printNumber(m) + printSymbol(i) +"((" + printNumber(n) + printSymbol(j) + printNumber(o) + ")" + printSymbol(k) + printNumber(p) + ")"); } } } } if (0 != result5[1]) { if (result5[0] % result5[1] == 0) { if (result5[0] / result5[1] == 24) { if ((!map.containsKey(new Integer(i)))|| (!map.containsKey(new Integer(j)))|| (!map.containsKey(new Integer(k)))) { map.put(new Integer(i),new Integer(i)); map.put(new Integer(j),new Integer(j)); map.put(new Integer(k),new Integer(k)); count += 1; System.out.println("(" + printNumber(m) + printSymbol(i) + printNumber(n) + ")" + printSymbol(j) + "(" + printNumber(o) + printSymbol(k) + printNumber(p) + ")"); } } } } } } } } } } } //总共几种答案,过滤了类似的答案 System.out.println("count: " + count); } public int printNumber(int i){ if(i == 0){ return aArray[0]; } if(i == 1){ return bArray[0]; } if(i == 2){ return cArray[0]; } if(i == 3){ return dArray[0]; } return 0; } public String printSymbol(int i){ if(i == 0){ return " + "; } if(i == 1){ return " - "; } if(i == 2){ return " * "; } if(i == 3){ return " / "; } return ""; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端