软件工程综合实践第二次作业
Partner:1759230茅杭斌
作业要求:随机择出两个运算符,进行100以内的运算,不要求给出答案。
深入延展:1.题目不能重复
2.可定制、可扩展
前言:
本以为这么一个简单的小程序,一个小时足够拿下了,两个小时那是最多了,可谁想一编就编了一下午。这其中一讨论实在是多出了很多的开发空间,并且注意起了相应的小细节,来实现程序功能的多样化以及对特定用户的适应程度,但是这其中依旧有着许多坎坷。
开发过程:(附上实现代码)
版本1.0------实现了程序的基础功能,能随机地产生算式,但是并不会产生答案,并且保证了题目的不重复性。程序很简单,这就是我们一开始以为的版本,编写起来的确也没发去我们多少时间,但是对于小学老师的要求,这其中还是存在一些漏洞的。
#include<stdio.h> #include<stdlib.h> #include<time.h> int main() { int x, y, m, i, t; srand(time(NULL)); for (i = 0; i < 300; i++) { x = rand() % 100; //0~99 y = rand() % 100; m = rand() % 4; switch (m) { case 0: printf("%d+%d=\n", x, y); break; case 1: if (x < y) { t = x; x = y; y = t; } printf("%d-%d=\n", x, y); case 2: printf("%d*%d=\n", x, y); case 3: if (y != 0) printf("%d/%d=\n", x, y); else i--; } } system("pause"); return 0; }
运行截图:随机100以内的二则运算,无结果
版本2.0------在考虑到小学可能未必对负数有一定的了解,对于阅卷老师来说,可以及时地进行答案的显示,于是在第一版的基础上对是否实现负数计算以及系统的出题量进行了定制,用户可根据自身水平来选择是否需要进行负数运算。
#include<stdio.h> #include<stdlib.h> #include<time.h> int main() { int x, y, m, i, t, n, z; printf("请输入需要的题目数:"); scanf_s("%d", &z); printf("是否加入负数运算?(是:1;否:2)"); scanf_s("%d", &t); printf("是否显示答案?(是:1;否:0)"); scanf_s("%d", &n); srand(time(NULL)); switch (t) { case 1: { if (n == 1) { for (i = 0; i < z;) { x = rand() % 200 - 100; //-100~100 y = rand() % 200 - 100; m = rand() % 4; switch (m) { case 0: if (((x + y)) < 100 && ((x + y) > 0)) { printf("%d+%d=%d\n", x, y, x + y); i++; } break; case 1: if (x < y) { t = x; x = y; y = t; } if (((x - y)) < 100 && ((x - y) > 0)) { printf("%d-%d=%d\n", x, y, x - y); i++; } case 2: if (((x * y)) < 100 && ((x * y) > 0)) { printf("%d*%d=%d\n", x, y, x*y); i++; } case 3: if (y != 0) { if (((x / y)) < 100 && ((x / y) > 0)) { printf("%d/%d=%d\n", x, y, x / y); printf("余数为=%d\n", x%y); i++; } } else i--; } } } else { for (i = 0; i < z; ) { x = rand() % 200 - 100; //-100~100 y = rand() % 200 - 100; m = rand() % 4; switch (m) { case 0: if (((x + y)) < 100 && ((x + y) > 0)) { printf("%d+%d=\n", x, y); i++; } break; case 1: if (x < y) { t = x; x = y; y = t; } if (((x - y)) < 100 && ((x - y) > 0)) { printf("%d-%d=\n", x, y); i++; } case 2: if (((x * y)) < 100 && ((x * y) > 0)) { printf("%d*%d=\n", x, y); i++; } case 3: if (y != 0) { if (((x / y)) < 100 && ((x / y) > 0)) { printf("%d/%d=\n", x, y); i++; } } else i--; } } } }break; case 2: { if (n == 1) { for (i = 0; i < z; ) { x = rand() % 100; // 0~99 y = rand() % 100; m = rand() % 4; switch (m) { case 0: if (((x + y)) < 100 && ((x + y) > 0)) { printf("%d+%d=%d\n", x, y, x + y); i++; } break; case 1: if (x < y) { t = x; x = y; y = t; } if (((x - y)) < 100 && ((x - y) > 0)) { printf("%d-%d=%d\n", x, y, x - y); i++; } case 2: if (((x * y)) < 100 && ((x * y) > 0)) { printf("%d*%d=%d\n", x, y, x*y); i++; } case 3: if (y != 0) { if (((x / y)) < 100 && ((x / y) > 0)) { printf("%d/%d=%d\n", x, y, x / y); printf("余数为=%d\n", x%y); i++; } } else i--; } } } else { for (i = 0; i < z;) { x = rand() % 100; //0~99 y = rand() % 100; m = rand() % 4; switch (m) { case 0: if (((x + y)) < 100 && ((x + y) > 0)) { printf("%d+%d=\n", x, y); i++; } break; case 1: if (x < y) { t = x; x = y; y = t; } if (((x - y)) < 100 && ((x - y) > 0)) { printf("%d-%d=\n", x, y); i++; } case 2: if (((x * y)) < 100 && ((x * y) > 0)) { printf("%d*%d=\n", x, y); i++; } case 3: if (y != 0) { if (((x - y)) < 100 && ((x - y) > 0)) { printf("%d/%d=\n", x, y); i++; } } else i--; } } } }break; } system("pause"); return 0; }
运行结果:只出10题,有负数运算,不显示结果
运行结果:无负数,显示结果
c++版本错误总结:1.循环的执行次数不匹配。一开始总是控制不好出题量,在经过反复的测试后终于发现问题出在循环身上,于是对症下药,顺利解决。
2.选择显示答案后,算式并不能进行运算。在与其它组进行经验交流后发现问题出在运算符不能识别,于是采用字符类型的匹配,来做到运算符的识别与算式的计算。
版本3.0------因考虑到c++的可视化程度并不友好,转而寻求Java的帮助(但随之而来的是项目所需的时间超出了预期),希望通过Java的窗口化编程实现用户登陆,在线练习,成绩记录以及用户的排名情况(此处为设想的系统方案,实际版本依旧处于开发状态)
下方截图为Java版本1.0,附上不完整代码
Example.java package work; public class Example { public static void main(String args[]) { WindowOperation win=new WindowOperation(); win.setBounds(100,100,390,360); win.setTitle("随机计算"); } } ComputerListener.java package work; import java.awt.event.*; import javax.swing.*; public class ComputerListener implements ActionListener { JTextField inputNumberOne,inputNumberTwo; JTextArea textShow; JTextField inputNumberThree; public void setJTextFieldOne(JTextField t) { inputNumberOne = t; } public void setJTextFieldTwo(JTextField t) { inputNumberTwo = t; } public void setJTextArea(JTextArea area) { textShow = area; } public void actionPerformed(ActionEvent e) { try { double number1=Double.parseDouble(inputNumberOne.getText()); double number2=Double.parseDouble(inputNumberTwo.getText()); double number3=Double.parseDouble(inputNumberThree.getText()); double result = 0; if(number3=='+') { result = number1+number2; } else if(number3=='-') { result = number1-number2; } else if(number3=='*') { result = number1*number2; } else if(number3=='/') { result = number1/number2; } textShow.append(number1+" "+number3+" "+number2+" = "+result+"\n"); } catch(Exception exp) { textShow.append("\n请输入数字字符\n"); } } } WindowOperation.java package work; import java.awt.*; import javax.swing.*; import java.io.*; public class WindowOperation extends JFrame { JTextField inputNumberOne,inputNumberTwo,inputNumberThree; JTextArea textShow; JButton button1,button2; OperatorListener operator; //监视ItemEvent事件的监视器 ComputerListener computer; //监视ActionEvent事件的监视器 public WindowOperation() { init(); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } void init() { setLayout(new FlowLayout()); inputNumberOne = new JTextField(5); inputNumberTwo = new JTextField(5); inputNumberThree=new JTextField(3); button1 = new JButton("来一题"); button2 = new JButton("提交"); textShow = new JTextArea(9,30); operator = new OperatorListener(); computer = new ComputerListener(); operator.setWorkTogether(computer); computer.setJTextFieldOne(inputNumberOne); computer.setJTextFieldTwo(inputNumberTwo); computer.setJTextFieldTwo(inputNumberThree); computer.setJTextArea(textShow); button1.addActionListener(computer);//button是事件源,computer是监视器 button2.addActionListener(computer); add(inputNumberOne); add(inputNumberThree); add(inputNumberTwo); add(button1); add(new JScrollPane(textShow)); add(button2); } }
心得体会:
partner:
这次结对编程实验,说实话我刚接到这个课题时我是很懵的。一开始的想法就是感觉结对编程会变得很麻烦,无论是两个人的代码风格上还是对问题的理解上,这都让这次的实验上升了一个难度。相比于单人编程,结对编程更考验两人间的理解和认同。在刚开始的编程的时候,我们很难适应对方的思考方式,对这个运算题的解答有不同的、自认为完美的独一无二的方法。最后发现那都是不符合实际的情况后,我们便静下来重新思考,从最低级的开始一步步进行编程。在代码选择方面,我们选择了我们比较熟悉的c++以及之后的Java。当第一个小功能实现时,我们的激情就被点燃了,找到了继续下去的希望,同时也慢慢感受到了结对编程让我们对对方观点的反驳的作用在程序上体现了出来。在之后的编程中,我们遇到了一些问题,比如在控制答案大小和题目数方面,我们发现不能仅仅在for语句上做功夫,而是转而在每个case条件的代码中加入答案大小约束和题目数的增减,就能达到预期的效果。还有又比如说一个小问题,在从键盘输入方面,由于我们之前一直用的vc++6.0,所以输入一直使用scanf()语句,而这次使用的vs却不支持scanf()语句,在查阅资料后了解到需要改成scanf_s()才能执行。同时,不知为何vs执行程序后总是会自动关闭窗口,导致无法查看生成的题目,后得知需在末尾的return前加上system("pause")便可以防止窗口自动关闭。这些小问题都是我们共同解决的,我想如果没有结对编程,我也就没这个心思去查找问题所在并解决问题了。结对编程确确实实让我们减少了犯错误的几率,减轻了单人编程的负担,提高了编写代码的效率,同时也让我们了解到了不同思想碰撞的重要性,让我结识了强力的工作伙伴。这次结对编程是非常有意义的,也希望以后能有更多这样的机会。
我:
对于项目所开展的设计并非是一成不变的,需求往往会随着讨论而多次变动。就比如本次实验,c++版本1.0 编完后发现功能实在是很单一,进而去寻求更针对于用户的定制化需求,于是开发了 c++版本2.0 ,待到实现了相应需求后,又觉得利用Java可以实现更美观的程序界面,同时对于用户的交互又有比较好的体验,转而开发项目3.0版本(Java版),从而导致项目实现的时间大大延长。
这是我们一开始并未有仔细考虑的地方,最初只将眼光着眼于项目内容的实现,对于其更深层次的延展并没有深入讨论,导致项目进行了二次重复开发,费时又费力。总的来说就是对于问题思考地依旧太浅显,没有足够的大局观。
但是也不能说这次结对编程是一次失败的体验,它让我学会了多人编程中应该注意的地方。比如想法的统一,因为平常都是单人编程,想到什么就编什么,很随性,而在本次实验中与队友的交流使得我发现了平常思考问题中范围更广的方面,以及最后在合理的沟通下两人达成的思想统一。