二柱子四则运算升级版
二柱子又来了,这次二柱子受到的要求更高了/汪汪,二柱子不仅得在上次的基础之上把各种功能搞成方法,还要能实现字符画页面的输出,全部完成后还得输出错题率,并将错题放到错题集中,以便用户进行错题重做。
页面如下:
非常羞愧地悄悄告诉你,我没有实现带括号的表达式的计算,原因是嫌太麻烦了,感觉很难,简单思考之后直接放弃,诶嘿。
在这次“升级”二柱子四则运算题目的途中,我也碰到了几个问题,下面就说说吧:
(1)在开始写的时候只想着通过之前写的去提升,但是实际上不通过大动筋骨真的没法去完成这一项任务。由此可见,不能拘泥于之前写的那点东西,拿到新的任务为之后一定要先分析需求,然后去规划出不同的类,在类中构想出大概的方法和实现方式,一定不要边写边想,那样写到一半肯定会后悔的。
(2)在写到一半的时候,我没有把这些子方法放到ClassTest2类中,而是和主方法一样放在ClassTest里,这就导致了我在面临错题重做阶段的问题时,我设置的关于错题题目以及对应答案的数组arrTest和arrAnswer都不能成功地得到其已经在其他字方法中获得的值,而是只能维持初始化时的空值。
· 我认为其中的原因是:我在主方法中使用这些数组的时候都需要通过实例化对象的方法去做,而当我实例化对象之后得到的是一个新对象,并不会直接得到我通过子方法获得的值,也就导致了这种情况。
解决的方法也很简单:那就是把除了子方法之外所有的方法和属性都移植到ClassTest2类中,并定义新方法去完成上述操作,让它去当一个纯纯的工具人!有了工具人之后,ClassTest类中的主方法就可以直接通过调用ClassTest2中的方法实现想到达成的目标, 非~常~好用。
源代码在下面了:
ClassTest类(只存放主方法):
package pers.yan.classTest; import java.util.Random; import java.util.Scanner; import pers.yan.classTest2.ClassTest2; public class ClassTest { Scanner sc = new Scanner(System.in); public static void main(String[] args) { ClassTest2 B = new ClassTest2(); boolean bexit = true; while(bexit) { ClassTest A = new ClassTest(); B.enterMenu(); Scanner sc = new Scanner(System.in); int iSure = sc.nextInt(); if(iSure == 1) { System.out.println("---------------开始练习-----------------"); System.out.println("请输入生成四则运算题目的个数:"); int iControl = sc.nextInt(); //iControl用于控制生成题目总数 System.out.println("请输入操作数的个数:"); int iControl2 = sc.nextInt(); //iControl2用于控制生成操作数的个数 System.out.println("请输入操作数的生成范围:"); int iField = sc.nextInt(); //iField用于控制操作数的生成范围 System.out.println("请输入是否有乘除法(有:1;没有:0)"); int iWay = sc.nextInt(); //iWay用于控制是否有乘除法 if(iControl < 1 || iControl2 < 2 || iField < 0 || (iWay != 1 && iWay != 0)) { System.out.println("输入错误,请重新输入!"); return; } else { B.show(iControl,iWay,iControl2,iField); } } else if(iSure == 2) { B.reTest(); } else { System.out.println("已退出!"); bexit = false; } } } }
ClassTest2类(存放各种工具方法):
package pers.yan.classTest2; import java.util.Random; import java.util.Scanner; public class ClassTest2 { Scanner sc = new Scanner(System.in); public double[] str; //str数组用于判断表达式与之前的是否相同(假设最多重复20个式子) public double[][] arrNum; //arrNum[i]用于存放第i个式子的数据和运算符 public int Flag; //iFlag为重复式子的个数 public double[] ending; //ending数组用于存储用户输入的运算结果 public double[] results; //results数组为计算机计算出的的答案 public String[] arrWrong = new String[1000]; //arrWrong数组用于把所有题目存储成字符串数组 public String[] arrTest = new String[1000]; //arrTest数组用于存储错题 public double[] arrAnswer = new double[1000]; //arrAnswer数组用于存储错题的答案 public static int ControlFlag = 0; //ControlFlag用于移动arrWrong数组的行数 public boolean bsame(double[] str,int j) { for(int m = 0 ; m < j ;m++) { if(str[m] == str[j]) { return true; } } return false; } public void reTest() //错题重做 { System.out.println("---------------错题重做-----------------"); System.out.println("您当前错题的总个数为:" + ControlFlag); for(int i = 0;arrTest[i] != null;i++) { System.out.println((i+1) + ". " +arrTest[i]); } System.out.println("下面依次给出正确答案,请重做并校对答案:"); for(int i = 0;arrAnswer[i] != 0;i++) { System.out.println((i+1) + ". " + arrAnswer[i]); } //System.out.println(ControlFlag); } public void setarrWrong(double Answer,int j) { //arrWrong[ControlFlag] = arrNum; arrTest[ControlFlag] = arrWrong[j]; //System.out.println("arrWrong[j]" + arrWrong[j]); //System.out.println("arrTest[j]" + arrTest[ControlFlag]); arrAnswer[ControlFlag] = Answer; ControlFlag++; //System.out.println("总错题的个数为:" + ControlFlag); //System.out.println("当前错题为:" + arrTest[ControlFlag]); //System.out.println("正确答案为:" + arrAnswer[ControlFlag]); } public void enterMenu() { System.out.println("----------欢迎来到四则运算计算系统-----------"); System.out.println("请选择:"); System.out.println(" 1.开始练习"); System.out.println(" 2.错题重做"); System.out.println(" 3.退出系统"); System.out.println("-------------------------------------"); } public double calcu(int iWay,int iChoose,int ilength,double[] calculuse)//calcu方法用于计算四则运算表达式的答案 { int i = 0; int k = 0; double sum = 0; //double[] calculate = calculuse; //for(int m = 0;m < ilength;m++) { System.out.println(calculuse[m]); } //无括号 if(iWay == 1) //有乘除 { //System.out.println("有乘除法"); for(k = 0;k < ilength;k++) { if(k % 2 == 1) //奇数坐标是运算符 { if(calculuse[k] % 4 == 3) //乘法 { calculuse[k-1] *= calculuse[k+1]; calculuse[k+1] = 0; calculuse[k] = 0; //清零 //System.out.println("当前乘法运算符已被清零!"); //System.out.println("k-1位置的数变为了:" +calculuse[k-1]); //System.out.println("k+1位置的数变为了:" +calculuse[k+1]); } else if(calculuse[k] % 4 == 0) //除法 { calculuse[k-1] /= calculuse[k+1]; calculuse[k+1] = 0; calculuse[k] = 0; //清零 //System.out.println("当前除法运算符已被清零!"); //System.out.println("k-1位置的数变为了:" +calculuse[k-1]); //System.out.println("k+1位置的数变为了:" +calculuse[k+1]); } } //System.out.println("k= "+ k); } for(i = 0;i < ilength;i++) { if(i % 2 == 1) //运算符位置 { if(calculuse[i] % 2 == 0) //减号 { calculuse[i+1] = -calculuse[i+1]; } calculuse[i] = 0; } sum += calculuse[i]; } } else if(iWay == 0) //无乘除 { for(i = 0;i < ilength;i++) { if(i % 2 == 1) //运算符位置 { if(calculuse[i]%2 == 0) //减号 { calculuse[i+1] = -calculuse[i+1]; } calculuse[i] = 0; } sum += calculuse[i]; } } //System.out.println(sum); return sum; } public void show(int iControl,int iWay,int iControl2,int iField) { int WrongTime = 0; Random random = new Random(); double WrongTime2 = 0; double[] calculuse = new double[iControl2*2-1+100]; //calculuse数组用于给calcu方法使用,计算表达式结果 double[] str = new double[iControl+20]; //str数组用于判断表达式与之前的是否相同(假设最多重复20个式子) double[][] arrNum = new double[iControl+20][iControl2*2-1]; //arrNum[i]用于存放第i个式子的数据和运算符 double[] ending = new double[iControl+20]; //ending数组用于存储用户输入的运算结果 double[] results = new double [iControl*2]; //results数组为计算机计算出的的答案 for(int j = 0;j < iControl;) //j为第几个式子的下标 { arrWrong[j] = ""; boolean test = true; int iNumc = random.nextInt(iControl2 - 1); //iNumc为前括号的位置 int iNumd = random.nextInt(iControl2 - iNumc) + iNumc + 1; //iNumd为后括号的位置 for(int i = 0;i < iControl2*2-1 ;i++) //生成四则运算表达式 { arrNum[j][i] = random.nextInt(iField); calculuse[i] = arrNum[j][i]; } for(int t = 0; t < iControl2;t++) //通过这种方法把这个式子的值放到这个str数组中去 { str[j] += arrNum[j][t]*t*t; } for(int k = 0;k <= j && test != false;k++) //判断是否重复 { if(bsame(str,j)) { test = false; } } if(test) //没重复就输出 { for(int t = 0;t < iControl2 * 2 - 1 ;t++) //t为数组的下标 { if(t%2 == 0 && t!= iControl2*2-2) //偶数下标输出数 { System.out.print(arrNum[j][t] + " "); arrWrong[j] += arrNum[j][t] + " "; } else if(t == iControl2*2-2) //偶数下标且为最后一个数时在末尾输出等号 { System.out.println(arrNum[j][t] + " ="); arrWrong[j] += arrNum[j][t] + " ="; //System.out.println("arrWrong[j]= " + arrWrong[j]); results[j] = calcu(iWay,0,iControl2*2-1,calculuse); //计算机得到正确答案 ending[j] = sc.nextDouble(); //用户输入他的计算结果 if(ending[j] - results[j] > 0.01 || results[j] - ending[j] > 0.01 ) //如果出错 { WrongTime++; WrongTime2++; System.out.println("这道题你做错啦!"); System.out.print("正确答案是:"); System.out.println(String.format("%.2f",results[j])); setarrWrong( results[j],j); } } else if(t % 2 == 1) //奇数下标输出运算符 { if(iWay == 1) //有乘除法 { if(arrNum[j][t]%4 == 1) { System.out.print("+ "); arrWrong[j] += "+ "; } else if(arrNum[j][t]%4 == 2) { System.out.print("- "); arrWrong[j] += "- "; } else if(arrNum[j][t]%4 == 3) { System.out.print("* "); arrWrong[j] += "* "; } else if(arrNum[j][t]%4 == 0) { System.out.print("/ "); arrWrong[j] += "/ "; } } else if(iWay == 0) //无乘除法 { if(arrNum[j][t]%2 == 1) { System.out.print("+ "); arrWrong[j] += "+ "; } else if(arrNum[j][t]%2 == 0) { System.out.print("- "); arrWrong[j] += "- "; } } } //} } j++; //System.out.println("当前j是:" + j); //System.out.println("当前iControl是:" + iControl); } } double end2 = (double)iControl; //System.out.println(WrongTime2 + " " +iControl); System.out.print("错误率为:"); System.out.println(String.format("%.2f",(WrongTime/end2))); } /* * public static void main(String[] args) { } */ }