java 1-15个 数字两两相减_任意1-10中的4个数字,使用加减乘除计算得出24结果的可能组合(java版),很多人小时候都玩过...

本文详细介绍了如何用Java实现24点游戏的算法。首先分析需求,将问题拆分为获取数字的排列组合、计算组合的合法性以及算法策略两部分。接着通过递归和循环实现所有可能的计算组合,确保结果为整数且不出现小数。最后通过用户输入获取数字并展示所有可能的解决方案。
摘要由CSDN通过智能技术生成

目录

需求;

需求该如何分析呢,怎么划分成小需求呢?

如何把小需求编排成完整需求;

学有所得

学会分析需求,由哪些组成(规则,逻辑等);

能把的需求分解成很多子需求、或孙需求、或童孙需求,直到每个需求很清晰可实施地为止

学会把各种子孙需求,通过组合编排,最终成为一个完整的大需求解决方案

需求

需求:任意1-10中的4个数字,使用加减乘除计算得出24结果的可能组合;

通过初步分析,我们可以得到如下规则:

规则:1、任意1-10中的4个数字;

2、使用加减乘除计算得出24;

3、在任何一次计算中不能出现小数,

比如:(4.0 + 8.0) / (3.0 / 6.0) = 24.0,这种是不算的,虽然最终结果是24,因为3/6=0.5;(8.0 / 3.0) * (4.0 + 5.0) = 24.0,虽然最终为24,但是在第一步结果却是小数,所以不成立;代码如下

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

/*** 是否为合法的计算结果

*@paramresult

*@return

*/

public static boolean isValidResult(doubleresult){if (result<1)

{return false;

}return result ==Math.floor(result);

}

View Code

4、整个运算中应该使用double类型,因为整数相除,使用int类型,在计算机中,会把余数抹掉,直接取整,这样就会造成结果不正确;

那需求该如何分析呢,怎么划分成小需求呢?

一般来说我们都会通过案例来分析,比如:这个需求,我们使用传统的计算,假设我们已经有这四个数[3,4,8,6],可能会有如下组合:

方案:((4.0 + 8.0) * 6.0) / 3.0=24.0;

方案:((3.0 * 4.0) - 8.0) * 6.0=24.0;

方案:((8.0 - 6.0) * 3.0) * 4.0=24.0;

方案:((4.0 + 8.0) / 3.0) * 6.0=24.0;

方案:(4.0 * 3.0) * (8.0 - 6.0) = 24.0;

方案:(6.0 / 3.0) * (4.0 + 8.0) = 24.0;

我们暂时先分析这个几个方案,大家看到这里,可以先思考一下有什么规律,有什么规则;

....................................................................................................Thinking..............................

从这些方案中,我们可以得出如下蹊跷之处:

1、所有的方案中,都在这四个数的所有可能排列组合中(我记忆之中,应该是高中数学的知识点);

2、我们可以把计算法则归纳为两种,所有的都可以归纳到一下两种中去;

第一、从左到右的依次计算;

第二、两两组合,前两个数计算结果和后两个数的计算结果再次计算;

第三、每个方案都有3个运算符;

不知道大家是不是和我发现的一样不,或者说有更多的发现;我认为不管什么发现都可以先列出来,然后在逐个去去除一些太离谱的发现;

我们再继续顺藤摸瓜,到此我们可以把需求分解如下:

我们继续分析需求,看看是否可以再次分解

从上面的需求中我们可以进一步进行分解

第一、如何获取四个数的所有排列组合?

1、举例,我们继续使用案列来分析,比如 [3,4,8,6]

[3,4,8,6](基准)

[4,3,8,6](第二和第一调换)

[3,8,4,6] [8,3,4,6](第三和第二调换,第二和第一调换)

[3,4,6,8] [3,6,4,8] [6,3,4,8] (第四和第三调换, 第三和第二调换,第二和第一调换)

这样是不是所有的排列组合呢?显然不是?因为还有三种基准进行上面的排列组合,也就是上面每行最后一列

[4,3,8,6](基准2)

[8,3,4,6](基准3)

[6,3,4,8](基准4)

2、通过上面的举例,我们就可以先获取所有的基准组合;

3、通过上面,我们可以知道每种基准的所有组合;

4、通过上面的方法获取的组合会有重复,需要前需要去重;

这样我们就能获取4个数的所有排列组合;我感觉这种获取所有排列组合的算法很笨重(有没有感觉有点想冒泡排序),不优雅,肯定有更优的方案,只是我不知道而已,如果知道的可以留言,谢谢;

所有排列分析到此,是不是还需要继续分析,可以继续思考;本人感觉可以落地了;如果觉得需要继续分析的,可以继续分解,知道自己很清晰,知道怎么干为止(这个因人而异);请看代码;

获取所有基准代码:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

double[] array = {3, 4, 6, 8};

List resultAllList = new ArrayList<>();

List list = new ArrayList<>();

list.add(array);

list.add(new double[]{array[1], array[2], array[3], array[0]});

list.add(new double[]{array[2], array[3], array[0], array[1]});

list.add(new double[]{array[3], array[0], array[1], array[2]});

View Code

获取每个基准的所有排列组合:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

/*** 获取array的所有可能组合

*

*@paramlist

*@paramarray*/

public static void getAllArray(List list, double[] array) {if (!exists(list, array)) {

list.add(array);

}for (int i = 1; i < 4; i++) {double[] arrayCopy =Arrays.copyOf(array, array.length);

List newList =getArrayList(arrayCopy, i);

Iterator iterator =newList.iterator();while(iterator.hasNext()) {double[] temp =iterator.next();if (!exists(list, temp)) {

list.add(temp);

}

}

}

}/*** 获取array下标遇到i的位置左右组合

*

*@paramarray

*@parami

*@return

*/

public static List getArrayList(double[] array, inti) {

List list = new ArrayList<>();for (int j = i; j > 0; j--) {double temp =array[j];

array[j]= array[j - 1];

array[j- 1] =temp;

list.add(array);

array=Arrays.copyOf(array, array.length);

}returnlist;

}

View Code

第二,对于算法法则该如何继续分析呢?我们可以继续使用举例

从上面随意获取一种排列组合,比如:[3,4,8,6]

1、从左到右的组合,在上面四个数字中,任意两个数中,我们可以有+,- ,*,/这四种算法,这又是一种计算的所有排列组合,并把结果和24对比,如果相等,那就是可行方案;

那我们是不是继续使用上面获取组合的方式呢?显然不是,这里关键点在于:任意两个数中都有+-*/的算法,这里我们可以使用三个for循环解决;

举例:((3.0 * 4.0) - 8.0) * 6.0=24.0;

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

/*** 计算array能算24点的所有组合,从左到右的顺序

*

*@param*@throwsException*/

public static int caculate24Point(double[] array) throwsException {int count = 0;if (array.length != 4) {throw new Exception("不是四个数");

}for(String op : operators) {

String expressionStr= "";double result = getTwoNumCaculate(array[0], array[1], op);if (!isValidResult(result))

{continue;

}

expressionStr= String.format("(%s %s %s)", array[0], op, array[1]);for(String op2 : operators) {double result1 = getTwoNumCaculate(result, array[2], op2);if (!isValidResult(result1))

{continue;

}

String expressionStr2= String.format("(%s %s %s)", expressionStr, op2, array[2]);for(String op3 : operators) {double result2 = getTwoNumCaculate(result1, array[3], op3);

String expressionStr3= String.format("%s %s %s", expressionStr2, op3, array[3]);if (result2 == 24.0d) {

count++;

System.out.println(String.format("方案:%s=%s", expressionStr3, result2));

}

}

}

}returncount;

}

View Code

2、两两组合,思路和上面有些相似,

前两个数的任意计算结果1,

后两个数的任意计算结果2,

结果1和结果2的任意计算结果3,

结果3和24对比,如果相等,那就是可行方案;

举例:(3.0 * 4.0) * (8.0 - 6.0) = 24.0;

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

/*** 计算array能算24点的所有组合 ,两两组合

*

*@paramarray

*@return*@throwsException*/

public static int caculate24Point2(double[] array) throwsException {int count = 0;if (array.length != 4) {throw new Exception("不是四个数");

}for(String op : operators) {double result1 = getTwoNumCaculate(array[0], array[1], op);if (!isValidResult(result1))

{continue;

}

String expressionStr1= String.format("(%s %s %s)", array[0], op, array[1]);for(String op2 : operators) {double result2 = getTwoNumCaculate(array[2], array[3], op2);if (!isValidResult(result2))

{continue;

}

String expressionStr2= String.format("(%s %s %s)", array[2], op2, array[3]);for(String op3 : operators) {double result3 =getTwoNumCaculate(result1, result2, op3);

String expressionStr3= String.format("%s %s %s", expressionStr1, op3, expressionStr2);if (result3 == 24.0d) {

count++;

System.out.println(String.format("方案: %s = %s", expressionStr3, result3));

}

}

}

}returncount;

}

View Code

某一种四个数的所有运算排列通过上面的方式我们可以全部获取,分析到此,我觉得代码可以落地,当然,如果你觉得还不够清晰,可以继续分析,直到自己清晰为止,这里我只是提供分解需求的思路而已;在软件工程中,我们必定先分析需求,然后分解需求,我们有四色分析方式,我们还有DDD领域的分析方式等,都是需要通过逐步分解成更小的需求来反复验证的;

到目前为止我们可以得出如下思维导图

edb36162f71fe8f24df27868b0ca724d.png

把各种子孙需求,通过组合编排,最终成为一个完整的大需求解决方案

最后,我们把每个小的需求加上一些规则逻辑组合成完整的大需求,我们暂时叫做编排吧;

这里其实也是一个难点,很多人希望一次性把代码写完整,写正确,其实这种思路是不正确的,这样只会增加代码的难度,一次性能把代码写的有多完整多正确,这个跟每个人的编程经验熟练度有关;

不管编程多牛,从无到有的敲代码方向不是一次性把左右的代码完成,重点方向把核心逻辑思路编写上,其次才逐步把一些细节逻辑规则加上去,这个就和我们小时候学画画一样,画一颗树先画主干然后画叶子最后添加果子和花之类的;

到目前为止是否完整呢?其实还差一点,任意的1-10的数字从哪里获取,不过需求没有明确,可以是用户输入,数据库获取,其他接口的传入,我们这里就定位用户输入吧

获取用户输入代码如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

double[] array = new double[4];int index=0;

Scanner scanner=newScanner(System.in);while (index<4)

{

System.out.println(String.format("请输入第%s个1-10的整数",index+1));

String tempNumStr=scanner.nextLine();if(!StringUtils.isNumeric(tempNumStr))

{

System.out.println("你输入的不是一个整数");continue;

}double tmpNum=Double.valueOf(tempNumStr);if (tmpNum<0 || tmpNum>10)

{

System.out.println("你输入的数字不是1-10的数字");continue;

}

array[index++]=tmpNum;

}

System.out.println(String.format("你输入的4个1-10的整数为%s,%s,%s,%s",array[0],array[1],array[2],array[3]));

View Code

最终完整代码如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

importorg.apache.commons.lang3.StringUtils;import java.util.*;/*** Author:

* Date:*/

public classPoint24Caculator {/*** 计算24点中可以到的操作*/

private static String[] operators ={"+", "-", "*", "/"};public static void main(String[] args) throwsException {double[] array = new double[4];int index=0;

Scanner scanner=newScanner(System.in);while (index<4)

{

System.out.println(String.format("请输入第%s个1-10的整数",index+1));

String tempNumStr=scanner.nextLine();if(!StringUtils.isNumeric(tempNumStr))

{

System.out.println("你输入的不是一个整数");continue;

}double tmpNum=Double.valueOf(tempNumStr);if (tmpNum<0 || tmpNum>10)

{

System.out.println("你输入的数字不是1-10的数字");continue;

}

array[index++]=tmpNum;

}

System.out.println(String.format("你输入的4个1-10的整数为%s,%s,%s,%s",array[0],array[1],array[2],array[3]));

System.out.println("结果如下:");

List resultAllList = new ArrayList<>();

List list = new ArrayList<>();

list.add(array);

list.add(new double[]{array[1], array[2], array[3], array[0]});

list.add(new double[]{array[2], array[3], array[0], array[1]});

list.add(new double[]{array[3], array[0], array[1], array[2]});for (int i = 0; i < list.size(); i++) {

getAllArray(resultAllList, Arrays.copyOf(list.get(i), list.get(i).length));

}int sum = 0;

Iterator iterator =resultAllList.iterator();while(iterator.hasNext()) {double[] tempArray =iterator.next();

sum+=caculate24Point(tempArray);

sum+=caculate24Point2(tempArray);

}

System.out.println("总共方案数量:" +sum);

}/*** 获取array的所有可能组合

*

*@paramlist

*@paramarray*/

public static void getAllArray(List list, double[] array) {if (!exists(list, array)) {

list.add(array);

}for (int i = 1; i < 4; i++) {double[] arrayCopy =Arrays.copyOf(array, array.length);

List newList =getArrayList(arrayCopy, i);

Iterator iterator =newList.iterator();while(iterator.hasNext()) {double[] temp =iterator.next();if (!exists(list, temp)) {

list.add(temp);

}

}

}

}/*** 获取array下标遇到i的位置左右组合

*

*@paramarray

*@parami

*@return

*/

public static List getArrayList(double[] array, inti) {

List list = new ArrayList<>();for (int j = i; j > 0; j--) {double temp =array[j];

array[j]= array[j - 1];

array[j- 1] =temp;

list.add(array);

array=Arrays.copyOf(array, array.length);

}returnlist;

}/*** array是否存啊在list中

*

*@paramlist

*@paramarray

*@return

*/

public static boolean exists(List list, double[] array) {

Iterator iterator =list.iterator();while(iterator.hasNext()) {double[] tmpArray =iterator.next();if (tmpArray[0] == array[0] && tmpArray[1] == array[1] && tmpArray[2] == array[2] && tmpArray[3] == array[3]) {return true;

}

}return false;

}/*** 计算array能算24点的所有组合,从左到右的顺序

*

*@param*@throwsException*/

public static int caculate24Point(double[] array) throwsException {int count = 0;if (array.length != 4) {throw new Exception("不是四个数");

}for(String op : operators) {

String expressionStr= "";double result = getTwoNumCaculate(array[0], array[1], op);if (!isValidResult(result))

{continue;

}

expressionStr= String.format("(%s %s %s)", array[0], op, array[1]);for(String op2 : operators) {double result1 = getTwoNumCaculate(result, array[2], op2);if (!isValidResult(result1))

{continue;

}

String expressionStr2= String.format("(%s %s %s)", expressionStr, op2, array[2]);for(String op3 : operators) {double result2 = getTwoNumCaculate(result1, array[3], op3);

String expressionStr3= String.format("%s %s %s", expressionStr2, op3, array[3]);if (result2 == 24.0d) {

count++;

System.out.println(String.format("方案:%s=%s", expressionStr3, result2));

}

}

}

}returncount;

}/*** 计算array能算24点的所有组合 ,两两组合

*

*@paramarray

*@return*@throwsException*/

public static int caculate24Point2(double[] array) throwsException {int count = 0;if (array.length != 4) {throw new Exception("不是四个数");

}for(String op : operators) {double result1 = getTwoNumCaculate(array[0], array[1], op);if (!isValidResult(result1))

{continue;

}

String expressionStr1= String.format("(%s %s %s)", array[0], op, array[1]);for(String op2 : operators) {double result2 = getTwoNumCaculate(array[2], array[3], op2);if (!isValidResult(result2))

{continue;

}

String expressionStr2= String.format("(%s %s %s)", array[2], op2, array[3]);for(String op3 : operators) {double result3 =getTwoNumCaculate(result1, result2, op3);

String expressionStr3= String.format("%s %s %s", expressionStr1, op3, expressionStr2);if (result3 == 24.0d) {

count++;

System.out.println(String.format("方案: %s = %s", expressionStr3, result3));

}

}

}

}returncount;

}/*** 是否为合法的计算结果

*@paramresult

*@return

*/

public static boolean isValidResult(doubleresult){if (result<1)

{return false;

}return result ==Math.floor(result);

}private static double getTwoNumCaculate(double num1, double num2, String operator) throwsException {switch(operator) {case "+":return num1 +num2;case "-":return num1 -num2;case "*":return num1 *num2;case "/":return num1 /num2;default:throw new Exception("运算符不符合规范");

}

}

}

View Code

学有所得

是否学会了这种分析思路

是否这种需求分析思路可以运用在地方?

这种把每个原子需求编排成一个完整大需求,是否可以在他地方使用?

最后效果图:

8e8b76c9fe41c0501423775b829f439b.png

在C语言,为了实现这个功能,你可以创建一个函数接受两个整数作为输入,然后根据用户的选择执行相应的运算并返回结果的字符串表示。这里是一个简单的示例: ```c #include <stdio.h> #include <stdlib.h> // 定义一个函数,接收两个整数和操作符作为参数 char* calculate(int num1, int num2, char operation) { switch (operation) { case '+': return "两数相加的结果是: " + ((num1 + num2) ? (int) num1 + num2 : 0); case '-': return "两数相减的结果是: " + ((num1 - num2) ? (int) num1 - num2 : 0); case '*': return "两数相乘的结果是: " + ((num1 * num2) ? (int) num1 * num2 : 0); case '/': if (num2 != 0) { return "两数相除的结果是: " + ((double) num1 / num2); } else { return "错误: 除数不能为零"; } default: return "无效的操作符"; } } int main() { int num1, num2; char operation; printf("请输入第一个数字 (0-30): "); scanf("%d", &num1); printf("请输入第二个数字 (0-30): "); scanf("%d", &num2); printf("请输入运算符 (+, -, *, /): "); scanf(" %c ", &operation); // 注意处理空格 if (operation >= '0' && operation <= '9') { // 检查是否输入的是操作符 operation = operation - '0'; // 转换为对应的整数值 } char* result = calculate(num1, num2, operation); printf("%s\n", result); return 0; } ``` 在这个代码,`calculate` 函数根据输入的操作符执行相应的数学运算,然后将结果转换成字符串返回。注意,除法运算需要检查除数是否为零。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值