GIthub项目地址:
项目要求:
实现一个自动生成小学四则运算题目的命令行程序。
1. 使用 -n 参数控制生成题目的个数。(实现)
2. 使用 -r 参数控制题目中数值(自然数、真分数和真分数分母)的范围。(未实现真分数运算)
3. 生成的题目中计算过程不能产生负数。(实现)
4. 生成的题目中如果存在形如e1 ÷ e2的子表达式,那么其结果应是真分数。(未实现)
5. 每道题目中出现的运算符个数不超过3个。(实现)
6. 程序一次运行生成的题目不能重复,生成的题目存入执行程序的当前目录下的Exercises.txt文件。(实现)
7. 在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件。(实现)
8. 程序应能支持一万道题目的生成。(实现)
9. 程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计。(实现)
PSP
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 60 |
· Estimate | · 估计这个任务需要多少时间 | 30 | 40 |
Development | 开发 | 1500 | 1600 |
· Analysis | · 需求分析 (包括学习新技术) | 300 | 400 |
· Design Spec | · 生成设计文档 | 60 | 60 |
· Design Review | · 设计复审 (和同事审核设计文档) | 60 | 60 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 30 | 40 |
· Design | · 具体设计 | 90 | 120 |
· Coding | · 具体编码 | 800 | 1000 |
· Code Review | · 代码复审 | 70 | 70 |
· Test | · 测试(自我测试,修改代码,提交修改) | 90 | 90 |
Reporting | 报告 | 130 | 130 |
· Test Report | · 测试报告 | 60 | 60 |
· Size Measurement | · 计算工作量 | 10 | 20 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 60 | 60 |
合计 | 1690 | 2150 |
解题思路
一开始对于式子的运算这一部分有点拿不准主意,不知道用生成树方法计算还是逆波兰表达式计算好,最后两人一番考虑后决定用逆波兰表达式解决式子的运算。在生成式子的这一部分采用控制符号位来限定随机生成的式子,含括号的式子采用手动添加的方式,既当运算符为两个和三个时随机挑几个式子手动为其加上括号。至于分数部分的算法至今还未想好如何解决。最后的作答部分用以前做的文件编辑器嵌套进去,省去了许多繁杂的工作,直接在文本编辑器里面作答,识别内容比对得到对错情况。
设计实现过程
首先,将需要控制的变量生成好,然后随机生成1~3个符号位,再随机生成数字,位数为符号位+1,然后将符号和数字放入一个数组表中,再利用逆波兰表达式计算结果。接着用文件输入输出流将式子和答案分别存入test.txt和answer.txt中,作答时将弹出一个文本编辑器,在里面作答完毕后可以统计对错情况并且在底部生成结果。
代码说明
主函数:
1 public class MainTest { 2 3 public static void main(String[] args) throws IOException { 4 // TODO 自动生成的方法存根 5 System.out.println("请输入生成题目数:-n"); 6 Scanner input = new Scanner(System.in); 7 int n = input.nextInt(); 8 System.out.println("请输入数值范围:-r"); 9 Scanner in = new Scanner(System.in);10 int r =in.nextInt();11 Random rand = new Random(); 12 ArrayListlist = new ArrayList ();13 ArrayList answerlist = new ArrayList ();14 char[] symbol =new char[]{'+','-','*','÷'};15 File test=new File(".\\test.txt");16 test.delete();17 test.createNewFile();18 File answer=new File(".\\answer.txt");19 test.delete();20 test.createNewFile();
随机生成一条式子:
1 int SymNum = rand.nextInt(3)+1; 2 int[] Num=new int[SymNum+1]; 3 String formula=new String(); 4 for(int j=0;j
逆波兰表达式计算结果:
1 //逆波兰表达式处理式子运算 2 Stacksavenumber = new Stack (); // 保存数字 3 Stack savesymbol = new Stack (); // 保存操作符 4 int memory = 0; // 保存每一个数字 5 char[] cs = formula.toCharArray(); 6 for (int k1=0;k1 0) {30 if (savesymbol.isEmpty()) { // 栈为空直接入栈31 savesymbol.push(temp);32 } else {33 if (priority(savesymbol.peek())>= priority(temp)) {34 int t = calculator(savenumber.pop(), savenumber.pop(), savesymbol.pop());35 savenumber.push(t);36 }37 savesymbol.push(temp);38 }39 }40 }41 }42 if (memory!= 0) {43 savenumber.push(memory);44 }45 while (!savesymbol.isEmpty()) {46 int t = calculator(savenumber.pop(), savenumber.pop(), savesymbol.pop());47 if(t==10001) {48 stop=1;49 break;50 }51 savenumber.push(t);52 }53 if(!savenumber.isEmpty()&&savenumber.peek()<0) { //负数54 n=n+1;55 int len=list.size();56 list.remove(len-1);57 continue;58 }59 else if(stop==1) {60 n=n+1;61 int len=list.size();62 list.remove(len-1);63 continue;64 }65 else if(stop1==1) {66 n=n+1;67 int len=list.size();68 list.remove(len-1);69 continue;70 }71 answerlist.add(savenumber.pop());72 }
生成test.txt和answer.txt文件:
1 BufferedWriter out=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(test))); 2 int Titlenumber=1; 3 for (String tmp : list) { 4 out.write(Titlenumber+". "+tmp+"="); 5 out.newLine(); 6 Titlenumber++; 7 } 8 out.flush(); 9 out.close();10 11 BufferedWriter answerout=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(answer)));12 BufferedReader fis=new BufferedReader(new FileReader(".\\test.txt"));13 String testtmp;14 for (int answertmp : answerlist) {15 testtmp=fis.readLine();16 answerout.write(testtmp+answertmp);17 answerout.newLine();18 }19 answerout.flush();20 answerout.close();
作答界面实现函数:
1 public class Exercise extends JFrame implements ActionListener{ 2 JLabel welcome=new JLabel("Weclome Back!",JLabel.CENTER); 3 JLabel none1=new JLabel(" "); 4 JLabel none2=new JLabel(" "); 5 JTextArea write=new JTextArea(60,60); 6 JScrollPane sp=new JScrollPane(write); 7 JButton begin; 8 JButton check; 9 JButton confirm; 10 Color color=new Color(0,0,0); 11 Exercise(){ 12 setTitle("Exercise"); 13 setBounds(0,0,1400,900); 14 Dimension screen=Toolkit.getDefaultToolkit().getScreenSize(); 15 setLocation((screen.width-1400)/2,(screen.height-900)/2); 16 JPanel p=new JPanel(); 17 this.add(p); 18 p.setBackground(Color.DARK_GRAY); 19 p.setLayout(new BorderLayout()); 20 begin=new JButton("开始答题"); 21 check=new JButton("参考答案"); 22 confirm=new JButton("提交"); 23 JPanel p1=new JPanel(); 24 p1.setLayout(new GridLayout(1,3,200,0)); 25 p1.add(begin); 26 p1.add(confirm); 27 p1.add(check); 28 JMenuBar mb=new JMenuBar(); 29 setJMenuBar(mb); 30 JMenu m=new JMenu("开始"); 31 mb.add(m); 32 JMenuItem m1=new JMenuItem("新建"); 33 JMenuItem m2=new JMenuItem("保存"); 34 JMenuItem m3=new JMenuItem("打开"); 35 JMenuItem m4=new JMenuItem("退出"); 36 m.setFont(new Font("幼圆",Font.BOLD,35)); 37 m1.setFont(new Font("幼圆",Font.BOLD,25)); 38 m2.setFont(new Font("幼圆",Font.BOLD,25)); 39 m3.setFont(new Font("幼圆",Font.BOLD,25)); 40 m4.setFont(new Font("幼圆",Font.BOLD,25)); 41 m.add(m1); 42 m.add(m2); 43 m.add(m3); 44 m.add(m4); 45 JMenu help=new JMenu("帮助"); 46 help.setFont(new Font("幼圆",Font.BOLD,35)); 47 mb.add(help); 48 JMenu about=new JMenu("关于"); 49 about.setFont(new Font("幼圆",Font.BOLD,35)); 50 JMenu setting=new JMenu("设置"); 51 setting.setFont(new Font("幼圆",Font.BOLD,35)); 52 JMenuItem m5=new JMenuItem("字体颜色"); 53 JMenuItem m6=new JMenuItem("文本颜色"); 54 m5.setFont(new Font("幼圆",Font.BOLD,25)); 55 m6.setFont(new Font("幼圆",Font.BOLD,25)); 56 setting.add(m5); 57 setting.add(m6); 58 mb.add(about); 59 mb.add(setting); 60 JPopupMenu po=new JPopupMenu(); 61 write.add(po); 62 welcome.setFont(new Font("Script MT Bold",Font.BOLD,50)); 63 welcome.setForeground(Color.WHITE); 64 p.add(welcome,BorderLayout.NORTH); 65 p.add(sp,BorderLayout.CENTER); 66 p.add(none1,BorderLayout.WEST); 67 p.add(none2,BorderLayout.EAST); 68 p.add(p1,BorderLayout.SOUTH); 69 m1.addActionListener(this); 70 m2.addActionListener(this); 71 m3.addActionListener(this); 72 m4.addActionListener(this); 73 m5.addActionListener(this); 74 m6.addActionListener(this); 75 begin.addActionListener(this); 76 check.addActionListener(this); 77 confirm.addActionListener(this); 78 this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 79 this.setVisible(true); 80 } 81 public void actionPerformed(ActionEvent e){ 82 if(e.getActionCommand()=="清空") { 83 write.setText(""); 84 } 85 else if(e.getActionCommand()=="保存") { 86 FileDialog save=new FileDialog(this,"save",FileDialog.SAVE); 87 save.setVisible(true); 88 try { 89 String savefile=save.getDirectory()+save.getFile(); 90 BufferedReader in=new BufferedReader(new StringReader(write.getText())); 91 BufferedWriter fos=new BufferedWriter(new FileWriter(savefile)); 92 String str; 93 while((str=in.readLine())!=null) { 94 fos.write(str); 95 fos.newLine(); 96 } 97 fos.flush(); 98 fos.close(); 99 }catch(IOException ioe) {100 System.out.println("ERROR");101 }102 }103 else if(e.getActionCommand()=="打开") {104 FileDialog open=new FileDialog(this,"open",FileDialog.LOAD);105 open.setVisible(true);106 try {107 String openfile=open.getDirectory()+open.getFile();108 BufferedReader fis=new BufferedReader(new FileReader(openfile));109 String s;110 while((s=fis.readLine())!=null) {111 write.append(s);112 write.append("\n");113 }114 fis.close();115 }catch(IOException ioe) {116 System.out.println("ERROR");117 }118 }119 else if(e.getActionCommand()=="退出") {120 dispose();}121 else if(e.getSource()==begin) { //答题122 write.setText("");123 write.setFont(new Font("Tekton Pro",Font.BOLD,40));124 try {125 BufferedReader fis=new BufferedReader(new FileReader(".\\test.txt"));126 String s;127 while((s=fis.readLine())!=null) {128 write.append(s);129 write.append("\n");130 }131 fis.close();132 }catch(IOException ioe) {133 System.out.println("ERROR");134 }135 }136 else if(e.getSource()==check) { //参考答案137 write.setFont(new Font("Tekton Pro",Font.BOLD,40));138 try {139 BufferedReader fis=new BufferedReader(new FileReader(".\\answer.txt"));140 String s;141 while((s=fis.readLine())!=null) {142 write.append(s);143 write.append("\n");144 }145 fis.close();146 }catch(IOException ioe) {147 System.out.println("ERROR");148 }149 }150 else if(e.getSource()==confirm) { //提交151 try {152 BufferedReader fis=new BufferedReader(new FileReader(".\\answer.txt"));153 BufferedReader in=new BufferedReader(new StringReader(write.getText()));154 String s;155 String comp;156 int correct=0;157 int wrong=0;158 int col=write.getLineCount()-1;159 int testnum=1;160 int i=0;161 int j=0;162 int[] correctnum=new int[col];163 int[] wrongnum=new int[col];164 while((s=fis.readLine())!=null&&(comp=in.readLine())!=null) {165 if(s.equals(comp)) {166 correctnum[i]=testnum;167 correct++;168 i++;169 }170 else {171 wrongnum[j]=testnum;172 wrong++;173 j++;174 }175 testnum++;176 }177 write.append("\n\nCorrect: "+correct);178 write.append(" (");179 for(int k=0;k
测试运行
运行界面:
做题界面:
答案界面:
代码覆盖率:
项目小结
这次结对编程对我们收获很大,一开始做这个项目的时候讨论设计如何实现功能,在经过一番讨论后便很快总结出了设计过程,比一个人研究效率高了很多,其次,在一起打代码时,一个人打一个人看,有什么错的地方很快就能被指正,有些不懂的地方旁边的人也能快速提出意见,彼此互通有无,分享彼此的经验,也为枯燥的打代码时间充实了一些乐趣。最后,大家分工合作,执行效率远远高于独自完成,可能这就是所谓的1+1>2吧,这种方式很值得以后借鉴。