此作业要求参见:https://edu.cnblogs.com/campus/nenu/2020Fall/homework/11245
结对伙伴:花名(朱航序)
仓库地址:https://e.coding.net/ayuyu/software-engineering-coursework/se-homework-20200924.git
国庆节你去探望初中数学老师,她感叹你当年真是个优秀学生啊,从来不报怨作业多,然后关切地问,“你现在学啥呢?”你说学计算机呢,她要求你举个例子证明你学的知识有用。你的回答她一直不懂。
你回家后连夜编了个程序,展示你的水平。程序准备帮助她给初中生出四则运算题目,学生答题后,自动判断对错。你第二天去找老师献宝。
功能1. 四则运算
支持出题4个数的四则运算题目,所有题目要求作者有能力正确回答 (提示:1/3 != 0.33333333333333333333333333333333,而是无限长)。
为了快出成果,你快速造个控制台的版本,包括以后改版成更优秀界面的核心功能,并考虑到扩展。
你在老师面前作如下表演 (数字你用excel验算过了,UI的卖萌部分你还没有想好) 。
> f4
1+2*3+4=
?11
答对啦,你真是个天才!
1+2*3+5=
?11
再想想吧,答案似乎是12喔!
1+2/4-5=
?-3.5
答对啦,你真是个天才!
...(一共20道题)
你一共答对4道题,共20道题。
功能2. 支持括号
老师看了你的表演,大大赞赏了你。然后她说,"你的题库里怎么都是没有括号的题呢,我记得你当初括号就掌握得不好啊。"你的脸红了,对老师说,"给我2个小时时间,我给你一个新版本,有括号的。"
你拿出笔记本,偷偷微信你们《构建之法》班的学霸,她说肯定能行,但是细节信号不好你听不清,只捕捉到隐约几个词"逆波兰""后缀表达式""堆栈""我看好你""数据结构"。
两小时后,在老师面前你在控制台下输入f4,然后回车。
> f4
1+2*(3+4)=
?15
答对啦,你真是个天才!
(1+2)*3+5=
?11
再想想吧,答案似乎是14喔!
((1/2)-4)*5=
?-17.5
答对啦,你真是个天才!
...(一共20道题)
你一共答对4道题,共20道题。
功能3. 限定题目数量,"精美"打印输出,避免重复
"就这点儿题,像你当年做得那么快,一会儿就完成啦!"老师说,"另外,我想打印出来,上课也不能带台机器。又另外,你把答案也打出来呗,我把答案剪掉,题目给学生做。"
一看需求这么多,你生怕她会说,"这都是很简单的功能,你一定能完成吧"。你知道如果承诺今晚,明早交工的时候她一定想出了更多可怕的需求,你赶紧说,"老师我现在就做。"
你忘记怎么调用打印机了,就把答案与题目横向对齐,输出在文件的右边。告诉老师txt文件可以用WORD打开,也能打印。她满意而意味深长地笑了,表示同意。
你输入命令执行的时候,脑袋比手指头还疼。
>f4 -c 3
1+2*(3+4)= 15
(1+2)*3+5= 14
((1/2)-4)*5= 17.5
你指着屏幕对老师说,">"是提示符,实际运行时可能是"C:UsersYoung>","f4"是程序的名字,它真正的名字是"f4.exe","-c 3"是命令行参数。按下回车,此时程序开始执行。"-c"这个参数后面输入多少,就生成多少题目。老师输入
>f4 -c -200
题目数量必须是 正整数。
>f4 -c 3.5
题目数量必须是 正整数。
>f4 -c test
题目数量必须是 正整数。
老师欣慰的笑了。你怔怔地看着她,心下怀疑她真的是教初中数学的那位么。
老师在你的指导下试用了一下,打印出来的题目堪称精美。老师让你做一次试试看能得多少分。你不敢借口四则运算忘光了,只好提起笑来开始答。刚做一半,你发现有几道题目是相同的,心中暗骂随机数不靠谱。又有几道虽然不完全相同,但是可以通过交换律、结合律、分配律变换为同一道题。比如
1*2+3*2
2*(1+3)+0
你暗叫惭愧,说有个小错误修正一下,调试了半晌,终于解决。
功能4. 支持分数出题和运算
国庆节后,你终于又回到美丽优雅并且正常的东北师范大学净月校区,在去食堂的路上偶遇你心目中的女神 (或男神,请自行替换)。她说,"哎呀,这跟我们《构建之法》课上的题目要求一样啊,真是巧合。"
"不要客气,代码拿去!反正我也没用。"你说,"如果有需求变更或扩展,尽管找我。"
你伏笔埋得不错。女神马上说,"对啊,有一点儿点儿不一样,你午饭时间加加班帮我改出来吧。"
她的题目还要求支持分数运算,你不禁想到了功能1中你特意规避了一些题目不出。她想要的是下面的样子:
>f4 -c 3
1/3+2/3+1+1= 3
1/2+2/3+1+2= 4 1/6
7/5+3/4*2-3 -1/10
你想到越难的题目就越能表现你的能力,欣然应允了,转身跑向实验室,路上就开始给师兄打电话。背后传来女神的声音,"提示1:别忘了约分。提示2:带分数,即 一又二分之一 表示 1 1/2。"
完成这个功能,女神对你的青睐+200。
这个题目太难了,接电话的师兄说他一点思路也没有。你提出有好酒肉一顿,他幽幽地说,又回忆起点什么,传说去年还是前年有位姓张的大神完成了,如果你求助于他或他的博客 (但不是抄袭,而是学习后独立实现) ,请主动说明,女神的青睐改为+150。他还回忆道,有本神书缩写名为SICP,中文名《计算机程序的构造和解释》第2.1.1节 实例:有理数算术运算,就是以此为例,不过,是scheme语言的,他也没有听说过。参考此书,请主动说明,女神的青睐改为+180。
(在你的心中,女神的要求并不像昔日的老师那么重要。此题选作,不完成此题不倒扣分。)
功能5 未来
还有可能把程序改造成GUI版,把程序改造为web版,把程序移植为android/ios版。今天留好接口,明天就不发愁。 (0分)
要求1 参考《构建之法》第4章两人合作,结对编程上述功能,要求每人发布随笔1篇 (代码是共同完成的,随笔有以下两种方式:(①允许两人写一份,得一份分数,二人均分;②如果每人写一份,内容不得抄袭,体会需要是自己的,分别得到自己博客的分数)。 (1) 给出每个功能的重点、难点、编程收获。(2)给出结对编程的体会,以及 (3) 至少5项在编码、争论、复审等活动中花费时间较长,给你较大收获的事件。 (10分)
要求2 给出结对开发的截图证据,要求截图能够证明你们是在结对编程。 (5分)
要求3 使用coding.net做版本控制。checkin 前要求清理 临时文件、可执行程序,通常执行 build-clean可以达到效果。(25分)
虽然只有5分,但此题如果做错,因为教师得不到你的代码,所以会导致“功能实现”为负分。
代码要求在 coding.net 做版本控制。要求push&pull时使用git客户端,不允许使用web页面。
要求频繁checkin。要求在PSP中记录的每次离开键盘30分钟以上,需要checkin。如果你持续长达4小时不离开键盘,教师要求展示此项能力。量化的可考核的指标要求: 每个功能,要求有4次以上 checkin,展示(1)逐步实现功能和(2)修复bug时的过程; 每次checkin都要求可以成功编译。
推荐git客户端tortoisgit。
题目要求随机生成4个数的带括号的四则运算,并计算其结果。我们没有采用常用的逆波兰表达式来计算,而是采用深度为2的满二叉树来生成和计算四则运算。
二叉树的叶子结点存储数字,父节点用来存储运算符。中序遍历的结果(1*2+3/4)就是四则运算的式子。当父节点返回的时候对运算式进行计算。
父节点返回的时候将左右括号带上,这样四则运算就带括号了。
生成四则运算主要代码:
public void createBTree() {
TreeNode lchild, rchild, lnode, rnode;
if (num == 1) {
lchild = new TreeNode(String.valueOf(Utils.getNumber(10)), null, null);
rchild = new TreeNode(String.valueOf(Utils.getNumber(10)), null, null);
root = new TreeNode(String.valueOf(Utils.getOperator()), lchild, rchild);
} else {
int num1 = 0;
int n = getDeep() - 3;
boolean[] place = Utils.getChildPlace(num);
root = new TreeNode(String.valueOf(Utils.getOperator()), null, null);
opeList.add(root);
for (int i = 0; i < n; i++) {
for (int j = 0; j < (int) Math.pow(2, i); j++, num1++) {
lchild = new TreeNode(String.valueOf(Utils.getOperator()), null, null);
rchild = new TreeNode(String.valueOf(Utils.getOperator()), null, null);
opeList.get(j + num1).setChild(lchild, rchild);
opeList.add(lchild);
opeList.add(rchild);
}
}
for (int i = 0; i < place.length; i++) {
if (place[i]) {
lnode = new TreeNode(String.valueOf(Utils.getNumber(10)), null, null);
rnode = new TreeNode(String.valueOf(Utils.getNumber(10)), null, null);
if (i % 2 == 0) {
lchild = new TreeNode(String.valueOf(Utils.getOperator()), lnode, rnode);
opeList.add(lchild);
opeList.get(num1).setLchild(lchild);
} else {
rchild = new TreeNode(String.valueOf(Utils.getOperator()), lnode, rnode);
opeList.add(rchild);
opeList.get(num1).setRchild(rchild);
}
} else {
if (i % 2 == 0) {
lchild = new TreeNode(String.valueOf(Utils.getNumber(10)), null, null);
opeList.get(num1).setLchild(lchild);
} else {
rchild = new TreeNode(String.valueOf(Utils.getNumber(10)), null, null);
opeList.get(num1).setRchild(rchild);
}
}
num1 = num1 + i % 2;
}
}
}
计算主要代码:
public String getResult() {
if (hasChild()) {
switch (str) {
case "+":
return String.valueOf(Integer.parseInt(getLchild().getResult()) + Integer.parseInt(getRchild().getResult()));
case "-":
return String.valueOf(Integer.parseInt(getLchild().getResult()) - Integer.parseInt(getRchild().getResult()));
case "*":
return String.valueOf(Integer.parseInt(getLchild().getResult()) * Integer.parseInt(getRchild().getResult()));
case "/":
if (getRchild().getResult().equals("0")) {
while (str.equals("/")) {
str = String.valueOf(Utils.getOperator());
}
return this.getResult();
} else if (Integer.parseInt(getLchild().getResult()) % Integer.parseInt(getRchild().getResult()) != 0) {
while (str.equals("/")) {
str = String.valueOf(Utils.getOperator());
}
return this.getResult();
} else
return String.valueOf(Integer.parseInt(getLchild().getResult()) / Integer.parseInt(getRchild().getResult()));
}
}
return str;
}
功能一和功能二运行截图:
功能三运行截图:
功能一难点:二叉树的生成和父节点的运算
功能二的难点:中序遍历二叉树,返回父节点是带上左右括号
功能三难点:对命令行参数进行判断,文件格式化输出
编程收获:复习了二叉树的知识点,复习了文件格式化输出,对面对对象编程有了更深的理解
结对编程体会:
- 编程思路:1+1>2,两个人一起想问题比一个人快很多
- 两个人找bug效率很高,更容易找到对方写的bug
- 思想碰撞使人进步,以后要多进行技术上的交流