20165217 结对编程项目-四则运算 整体总结
20165217 结对编程项目-四则运算 整体总结
一、需求分析
- 支持多运算符
- 支持真分数
- 用户可选择生成题目的等级
- 处理生成题目并输出到文件
- 完成题目后从文件读入并判题
- 多语言支持
二、设计思路
计算部分
- 中缀表达式转成后缀表达式
- 后缀表达式计算
题目部分
- 使用for循环生成题目
- 去重(将题目从中缀转成后缀,将其排序,判断是否有重复)(存在bug)
- 括号的生成(使用两个随机数代表括号的位置)(存在bug)
- 有意义的题目(使用list类中的subList)
- 生成分数与整数的混合运算
UML类图
三、实现过程中的关键代码
中缀转后缀表达式转换类:
通过观察和了解,对于运用栈的中缀转后缀方法,以及对后缀表达式的计算类同学们大都可以自己完成所以不属于我的主要代码,通过多位同学看完我的代码所给的反馈,我在这里对我的题目自动生成以及加括号的方法进行解释:
public void Ti(int number, int many,String language) {
if(language.equalsIgnoreCase("A"))
many = TiclassC(many);
else if(language.equalsIgnoreCase("B"))
many = TiclassE(many);
else many = TiclassF(many);
for (int j = 0; j < number; j++) {
String ti = "";
//开始进入题目生成
for (int i = 0; i < many; i++) {
int A = ran.nextInt(20) + 1;
int D = ran.nextInt(20) + 1;
int B = ran.nextInt(5);
int C = ran.nextInt(5);
RationalNumber si = new RationalNumber(A, D);
//正式进入生成题目
if (parity(i)) {
//判断前面是否有左括号
if (list1.indexOf("( ") == -1)
list1.add(getSym() + " ");
//判断将加的右括号和上一个左括号的距离
else if (list1.size() - list1.lastIndexOf("( ") > 4) {
//判断前面的左括号是否已经有了相对应的右括号了
if (list1.lastIndexOf(") ") - list1.lastIndexOf("( ") < 0 && B == 0) {
list1.add(") ");
list1.add(getSym() + " ");
} else list1.add(getSym() + " ");
} else list1.add(getSym() + " ");
} else if (i == many - 1) {
//循环结束时判断前面是否还有一个没有加右括号的左括号
if (list1.lastIndexOf("( ") - list1.lastIndexOf(") ") > 0) {
if (C == 0) {
list1.add(si.toString() + " ");
list1.add(") ");
} else {
list1.add(A + " ");
list1.add(") ");
}
} else if (C != 0)
list1.add(A + " ");
else list1.add(si.toString() + " ");
} else if (i == 0) {
if (C != 0)
list1.add(A + " ");
else list1.add(si.toString() + " ");
} else if (list1.lastIndexOf(") ") != -1) {
if (list1.lastIndexOf(") ") - list1.lastIndexOf("( ") > 0 && B == 0) {
list1.add("( ");
if (C != 0)
list1.add(A + " ");
else list1.add(si.toString() + " ");
} else if (C != 0)
list1.add(A + " ");
else list1.add(si.toString() + " ");
} else if (list1.indexOf("( ") == -1 && B == 0) {
list1.add("( ");
if (C != 0)
list1.add(A + " ");
else list1.add(si.toString() + " ");
} else if (C != 0)
list1.add(A + " ");
else list1.add(si.toString() + " ");
}
for (String i : list1)
ti += i;
list1.clear();
list.add(ti);
}
}
public String getSym() {
int A = ran.nextInt(4);
switch (A) {
case 0:
sym = "+";
break;
case 1:
sym = "-";
break;
case 2:
sym = "*";
break;
case 3:
sym = "/";
break;
}
return sym;
}
public boolean parity(int num) {
if (num % 2 == 1)
return true;
else
return false;
}
public int TiclassC(int many) {
Scanner scan = new Scanner(System.in);
int A = 1;
while (true) {
try {
if (many > 0) {
for (int i = 0; i < many; i++) {
A += 2;
}
break;
} else throw new Exception();
}
catch (Exception e) {
System.out.println("级别输入错误,请重新输入(要求级别至少为1)");
many = scan.nextInt();
}
}
return A;
}
以上是相关代码:
- 解释:首先在用户输入题目数量number和题目等级many后many会在Ticlass方法中转换为相应等级的长度,根据输入的两个参数建立两个循环,具体思路为:生成的题目都是在双数位为数字,但数位为符号,在此基础上,在加数字时可能会在数字的左边加一个“(”,在加符号时会在符号的左边加一个“)”,但在加“)”时需要进行判断1.前面是否存在一个“(” 2.前面的“(”后面是否已经有了“)” 3.前的“(”距离现在要加的“)”是否存在一定距离(以此保证括号中至少扩入一个两个数的计算)为解决这个问题,我使用了ArrayList中的Indexof和lastIndexof方法我将每一个生成的符号或数字都顺序加入到list中用最后一个“)”位置与最后一个“(”位置做差后所的数的大小来判断和保证括号生成都是一对的。
四、遇到的困难及解决方法
- 问题1:在题目生成过程中只能生成符带有号和数字的表达式却不能生成带有括号的混合运算。
解决办法:在查过文档后,我发现了一个列表(List)的很好用的方法,IndexOf(object o)和lastIndexOf(object o)分别是返回列表中首次出现某个对象的位置和最后一次出现某个对象的位置,利用左右括号的位置差进行判断,最终实现加多个括号的表达式生成。
五、对结对的小伙伴的评价
- 我们本周的任务是实现真分数类,和做成最终的用户界面。在这一周我和郭晶涛一起在图书馆学习了一个周末,虽然我们对Java学习的基础都不是特别好,但是在通过我们的不懈学习,我们感觉Java学习的收获非常大,同时我们培养了我们两个人的默契,在未来的结对学习中,我们会再接再厉,把学习落到实处,将学习做好!