目录
需求;
需求该如何分析呢,怎么划分成小需求呢?
如何把小需求编排成完整需求;
学有所得
学会分析需求,由哪些组成(规则,逻辑等);
能把的需求分解成很多子需求、或孙需求、或童孙需求,直到每个需求很清晰可实施地为止
学会把各种子孙需求,通过组合编排,最终成为一个完整的大需求解决方案
需求
需求:任意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,但是在第一步结果却是小数,所以不成立;代码如下
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/**
* 是否为合法的计算结果
* @param result
* @return
*/
public static boolean isValidResult(double result){
if (result 0; j--) {
double temp = array[j];
array[j] = array[j - 1];
array[j - 1] = temp;
list.add(array);
array = Arrays.copyOf(array, array.length);
}
return list;
}
View Code
第二,对于算法法则该如何继续分析呢?我们可以继续使用举例 从上面随意获取一种排列组合,比如:[3,4,8,6] 1、从左到右的组合,在上面四个数字中,任意两个数中,我们可以有+,- ,*,/这四种算法,这又是一种计算的所有排列组合,并把结果和24对比,如果相等,那就是可行方案; 那我们是不是继续使用上面获取组合的方式呢?显然不是,这里关键点在于:任意两个数中都有+-*/的算法,这里我们可以使用三个for循环解决; 举例:((3.0 * 4.0) - 8.0) * 6.0=24.0;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/**
* 计算array能算24点的所有组合,从左到右的顺序
*
* @param
* @throws Exception
*/
public static int caculate24Point(double[] array) throws Exception {
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));
}
}
}
}
return count;
}
View Code
2、两两组合,思路和上面有些相似,
前两个数的任意计算结果1, 后两个数的任意计算结果2, 结果1和结果2的任意计算结果3, 结果3和24对比,如果相等,那就是可行方案; 举例:(3.0 * 4.0) * (8.0 - 6.0) = 24.0;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/**
* 计算array能算24点的所有组合 ,两两组合
*
* @param array
* @return
* @throws Exception
*/
public static int caculate24Point2(double[] array) throws Exception {
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));
}
}
}
}
return count;
}
View Code
某一种四个数的所有运算排列通过上面的方式我们可以全部获取,分析到此,我觉得代码可以落地,当然,如果你觉得还不够清晰,可以继续分析,直到自己清晰为止,这里我只是提供分解需求的思路而已;在软件工程中,我们必定先分析需求,然后分解需求,我们有四色分析方式,我们还有DDD领域的分析方式等,都是需要通过逐步分解成更小的需求来反复验证的;
到目前为止我们可以得出如下思维导图
![](https://img2018.cnblogs.com/blog/41504/201905/41504-20190505165732188-1081415895.png)
把各种子孙需求,通过组合编排,最终成为一个完整的大需求解决方案
最后,我们把每个小的需求加上一些规则逻辑组合成完整的大需求,我们暂时叫做编排吧;这里其实也是一个难点,很多人希望一次性把代码写完整,写正确,其实这种思路是不正确的,这样只会增加代码的难度,一次性能把代码写的有多完整多正确,这个跟每个人的编程经验熟练度有关;不管编程多牛,从无到有的敲代码方向不是一次性把左右的代码完成,重点方向把核心逻辑思路编写上,其次才逐步把一些细节逻辑规则加上去,这个就和我们小时候学画画一样,画一颗树先画主干然后画叶子最后添加果子和花之类的;
到目前为止是否完整呢?其实还差一点,任意的1-10的数字从哪里获取,不过需求没有明确,可以是用户输入,数据库获取,其他接口的传入,我们这里就定位用户输入吧
获取用户输入代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
double[] array = new double[4];
int index=0;
Scanner scanner=new Scanner(System.in);
while (index |