实验二 结对编程(阶段二)
一、实验目标:
1)体验敏捷开发中的两人合作。
2)进一步提高个人编程技巧与实践。
二 、实验内容:
1)根据以下问题描述,练习结对编程(pair programming)实践;
2)要求学生两人一组,自由组合。每组使用一台计算机,二人共同编码,完成实验要求。
3)要求在结对编程工作期间,两人的角色至少切换 4 次;
4)编程语言不限,版本不限。建议使用 Python 或 JAVA 进行编程。
三、问题描述
开发一个自动生成小学四则运算题目的命令行 “软件”。实现 输入你要出题的个数,随机产生四则运算,然后用户回答,并且进行打分。
规则:用随机数实现100以内的加、减、乘、除运算,其中和与积不能超过100,差不为负(即须大减小),商不为小数或分数(即必须整除)。要求总计输出10个运算式,每输出一个运算式,等待输入结果,然后进行对错判断并输出。最后输出统计答对的题数与分。
阶段一
1)查阅相关资料加深对敏捷开发和结对编程的理解;
2)组队情况,各队博客地址,github仓库地址,所选择的课题;
3)针对课题查阅的资料,对课题的理解;
4)二个人商量后,采用开发平台和技术工具
5)其他,如二人讨论的记录
1)
敏捷开发的特点:敏捷开发是一种基于更紧密的团队协作、能够有效应对快速变化需求、快速交付高质量软件的迭代和增量的新型软件开发方法。更关注协作更关注质量更关注可工作的产品基于实践而非基于理论。
结对编程:(Pair programming)是一种敏捷软件开发的方法,两个程序员在一个计算机上共同工作。一个人输入代码,而另一个人审查他输入的每一行代码。输入代码的人称作驾驶员,审查代码的人称作观察员。两个程序员经常互换角色。在结对编程中,观察员同时考虑工作的战略性方向,提出改进的意见,或将来可能出现的问题以便处理。这样使得驾驶者可以集中全部注意力在完成当前任务的“战术”方面。观察员当作安全网和指南。结对编程对开发程序有很多好处。比如增加纪律性,写出更好的代码等。
2)
组队情况:58/江苏电视台 方振响 https://www.cnblogs.com/fangzhenxiang/ 王宁 https://home.cnblogs.com/u/wangningshark/ 四则运算 https://github.com/bigApple00/four-types-compute
3)课题难度不是很大,采用模块化Java GUI编程。
4)eclipse GUI编程
5)选择四则运算题目和eclipse开发工具,掌握了git基本操作,采用GitHub托管。
阶段二
1.代码规范
变量名应遵循见名知意的命名原则
名称只能由字母、数字、下划线、$符号组成
不能以数字开头
名称不能使用Java中的关键字
不允许出现中文及拼音命名
项目名全部小写
包名全部小写
方法采用小驼峰式命名
对方法和变量名加上一定的注释
代码缩进要一致
变量在声明时,同时进行初始化。
同一行只声明一个变量。
勿把不同类型的变量声明放在同一行。
方法和方法之间空一行。
让一切东西都尽可能地"私有"--private。可使库的某一部分"公共化"(一个方法、类或者一个字段等等),就永远不能把它拿出。若强行拿出,就可能破坏其他人现有的代码,使他们不得不重新编写和设计。
2.程序的总体设计
随机生成两个数和运算符,用不同的方法实现不同的限制条件,把数字和运算符加到Jframe上面
用事件方法做出评分功能,方法均在构造界面时实现。
程序总体设计图
3.程序结对编程过程
这是用QQ屏幕分享,编写一些程序中的方法。我是驾驶员,他是领航员。
这是在操作git命令进行pull request。他是驾驶员,我是领航员。
这是在GitHub里进行merge。
4.功能实现情况
基本的功能都可以实现,大减小,整除,加法乘法小于一百,随机生成整数和运算符。输入之后答案之后点击按钮进行提交,评分结果显示在屏幕上。可重复答题和评分。
以下是代码,这是最初的未模块化的
package package1; import java.awt.*; import javax.swing.*; import java.awt.event.*; import java.util.Random; import java.util.regex.Matcher; import java.util.regex.Pattern; public class UI extends JFrame implements ActionListener{ public int x; //x为被除数,y为除数,z为暂存x,y的商 float z,y; JLabel[][] lab=new JLabel[10][4]; //存放四则运算的数和运算符 JTextField[] text=new JTextField[10]; //存放输入结果 Random random =new Random(); JButton b1=new JButton("提交"); public int produceNumber1() { //产生被除数 int random_number_x; random_number_x=random.nextInt(50)+1; return random_number_x; } public float produceNumber2() { //产生除数 int random_number_y; random_number_y=random.nextInt(50)+1; return random_number_y; } public void underHundred() { //使加法结果小于一百 while(x+y>100) { y--; if(x+y<100) break; } } public void underHundred2() { //使乘积结果小于一百 while(x*y>100) { y--; if(x*y<100) break; } } public void bigSubtractsmall() { //完成大减小 while(x-y<0) { x++; if(x-y>0) break; } } public void exactDivide() { //使整除 try { z=x/y; } catch (ArithmeticException e) { e.printStackTrace(); } Pattern pattern=Pattern.compile("\\.0$"); //若不是以.0结尾,就没有整除 String s = String.valueOf(z); Matcher matcher=pattern.matcher(s); while(!matcher.find()) { //改变被除数y的值 y=1f; y++; z=x/y; s = String.valueOf(z); matcher=pattern.matcher(s); if(matcher.find()) break; } } public String chooseCharacter() { //随机选择四种运算符的一个 char[] a={'+','-','*','/'}; String charString=String.valueOf(a[random.nextInt(a.length)]); return charString; } public void actionPerformed(ActionEvent a) { int right_count=0; //记录正确的个数 String char_string; if(a.getSource()==b1) { for(int i=0;i<10;i++) { int j=0; char_string=lab[i][j+1].getText(); switch (char_string) { //判断是哪一个运算符对应的算式 case "+": try { //Integer.parseInt该方法会抛出异常 if(Integer.parseInt(lab[i][j].getText().trim())+Integer.parseInt(lab[i][j+2].getText().trim())==Integer.parseInt(text[i].getText().trim())) right_count++; }catch (NumberFormatException e) { e.printStackTrace(); } break; case "-": try { if(Integer.parseInt(lab[i][j].getText().trim())-Integer.parseInt(lab[i][j+2].getText().trim())==Integer.parseInt(text[i].getText().trim())) right_count++; }catch (NumberFormatException e) { e.printStackTrace(); } break; case "*": try { if(Integer.parseInt(lab[i][j].getText().trim())*Integer.parseInt(lab[i][j+2].getText().trim())==Integer.parseInt(text[i].getText().trim())) right_count++; }catch (NumberFormatException e) { e.printStackTrace(); } break; case "/": try { if(Integer.parseInt(lab[i][j].getText().trim())/Integer.parseInt(lab[i][j+2].getText().trim())==Integer.parseInt(text[i].getText().trim())) right_count++; }catch (NumberFormatException e) { e.printStackTrace(); } break; } } b1.setText("你答对了"+right_count+"题"); //最后评分输出到button上 } } UI(){ int j=0; String ch; for(int i=0;i<10;i++) { x=produceNumber1(); y=produceNumber2(); bigSubtractsmall(); ch=chooseCharacter(); switch(ch) { //判断产生的是哪个运算符 case "+" : underHundred(); lab[i][j]=new JLabel(" "+x); add(lab[i][j]); lab[i][j+1]=new JLabel("+"); add(lab[i][j+1]); lab[i][j+2]=new JLabel(" "+(int)y); //被除数y为float型转为int型 add(lab[i][j+2]); lab[i][j+3]=new JLabel("="); add(lab[i][j+3]); text[i] =new JTextField(" "); add(text[i]); break; case "-": lab[i][j]=new JLabel(" "+x); add(lab[i][j]); lab[i][j+1]=new JLabel("-"); add(lab[i][j+1]); lab[i][j+2]=new JLabel(" "+(int)y); add(lab[i][j+2]); lab[i][j+3]=new JLabel("="); add(lab[i][j+3]); text[i] =new JTextField(" "); add(text[i]); break; case "*": underHundred2(); lab[i][j]=new JLabel(" "+x); add(lab[i][j]); lab[i][j+1]=new JLabel("*"); add(lab[i][j+1]); lab[i][j+2]=new JLabel(" "+(int)y); add(lab[i][j+2]); lab[i][j+3]=new JLabel("="); add(lab[i][j+3]); text[i] =new JTextField(" "); add(text[i]); break; case "/": exactDivide(); lab[i][j]=new JLabel(" "+x); add(lab[i][j]); lab[i][j+1]=new JLabel("/"); add(lab[i][j+1]); lab[i][j+2]=new JLabel(" "+(int)y); add(lab[i][j+2]); lab[i][j+3]=new JLabel("="); add(lab[i][j+3]); text[i] =new JTextField(" "); add(text[i]); break; } } b1.addActionListener(this); //添加按钮做出应答 add(b1); } public static void main(String[] args) { UI g=new UI(); g.setLayout(new FlowLayout(1,10,3)); g.setTitle("四则运算"); g.setLocation(1000, 100); g.setSize(500,300); g.setVisible(true); g.setResizable(false); g.setDefaultCloseOperation(EXIT_ON_CLOSE); } }
这是后来修老师上课讲到划分和权限问题,我把代码分为了逻辑层和应用层。
package package2; import java.awt.*; import javax.swing.*; import java.awt.event.*; import java.util.Random; public class UI extends JFrame implements ActionListener{ protected static int x; protected static float y; protected static float z; //x为被除数,y为除数,z为暂存x,y的商 JLabel[][] lab=new JLabel[10][4]; //存放四则运算的数和运算符 JTextField[] text=new JTextField[10]; //存放输入结果 Random random =new Random(); JButton b1=new JButton("提交"); public void actionPerformed(ActionEvent a) { int right_count=0; //记录正确的个数 String char_string; if(a.getSource()==b1) { for(int i=0;i<10;i++) { int j=0; char_string=lab[i][j+1].getText(); switch (char_string) { //判断是哪一个运算符对应的算式 case "+": try { //Integer.parseInt该方法会抛出异常 if(Integer.parseInt(lab[i][j].getText().trim())+Integer.parseInt(lab[i][j+2].getText().trim())==Integer.parseInt(text[i].getText().trim())) right_count++; }catch (NumberFormatException e) { e.printStackTrace(); } break; case "-": try { if(Integer.parseInt(lab[i][j].getText().trim())-Integer.parseInt(lab[i][j+2].getText().trim())==Integer.parseInt(text[i].getText().trim())) right_count++; }catch (NumberFormatException e) { e.printStackTrace(); } break; case "*": try { if(Integer.parseInt(lab[i][j].getText().trim())*Integer.parseInt(lab[i][j+2].getText().trim())==Integer.parseInt(text[i].getText().trim())) right_count++; }catch (NumberFormatException e) { e.printStackTrace(); } break; case "/": try { if(Integer.parseInt(lab[i][j].getText().trim())/Integer.parseInt(lab[i][j+2].getText().trim())==Integer.parseInt(text[i].getText().trim())) right_count++; }catch (NumberFormatException e) { e.printStackTrace(); } break; } } b1.setText("你答对了"+right_count+"题"); //最后评分输出到button上 } } UI(){ int j=0; String ch; for(int i=0;i<10;i++) { x=Logic.produceNumber1(); y=Logic.produceNumber2(); Logic.bigSubtractsmall(); ch=Logic.chooseCharacter(); switch(ch) { //判断产生的是哪个运算符 case "+" : Logic.underHundred(); lab[i][j]=new JLabel(" "+x); add(lab[i][j]); lab[i][j+1]=new JLabel("+"); add(lab[i][j+1]); lab[i][j+2]=new JLabel(" "+(int)y); //被除数y为float型转为int型 add(lab[i][j+2]); lab[i][j+3]=new JLabel("="); add(lab[i][j+3]); text[i] =new JTextField(" "); add(text[i]); break; case "-": lab[i][j]=new JLabel(" "+x); add(lab[i][j]); lab[i][j+1]=new JLabel("-"); add(lab[i][j+1]); lab[i][j+2]=new JLabel(" "+(int)y); add(lab[i][j+2]); lab[i][j+3]=new JLabel("="); add(lab[i][j+3]); text[i] =new JTextField(" "); add(text[i]); break; case "*": Logic.underHundred2(); lab[i][j]=new JLabel(" "+x); add(lab[i][j]); lab[i][j+1]=new JLabel("*"); add(lab[i][j+1]); lab[i][j+2]=new JLabel(" "+(int)y); add(lab[i][j+2]); lab[i][j+3]=new JLabel("="); add(lab[i][j+3]); text[i] =new JTextField(" "); add(text[i]); break; case "/": Logic.exactDivide(); lab[i][j]=new JLabel(" "+x); add(lab[i][j]); lab[i][j+1]=new JLabel("/"); add(lab[i][j+1]); lab[i][j+2]=new JLabel(" "+(int)y); add(lab[i][j+2]); lab[i][j+3]=new JLabel("="); add(lab[i][j+3]); text[i] =new JTextField(" "); add(text[i]); break; } } b1.addActionListener(this); //添加按钮做出应答 add(b1); setLayout(new FlowLayout(1,10,3)); setTitle("四则运算"); setLocation(1000, 100); setSize(500,300); setVisible(true); setResizable(false); setDefaultCloseOperation(EXIT_ON_CLOSE); } public static void main(String[] args) { UI g=new UI(); g.setResizable(false); } }
package package2; import java.util.Random; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Logic { static Random random =new Random(); public static int produceNumber1() { //产生被除数 int random_number_x; random_number_x=random.nextInt(50)+1; return random_number_x; } public static float produceNumber2() { //产生除数 int random_number_y; random_number_y=random.nextInt(50)+1; return random_number_y; } public static void underHundred() { //使加法结果小于一百 while(UI.x+UI.y>100) { UI.y--; if(UI.x+UI.y<100) break; } } public static void underHundred2() { //使乘积结果小于一百 while(UI.x*UI.y>100) { UI.y--; if(UI.x*UI.y<100) break; } } public static void bigSubtractsmall() { //完成大减小 while(UI.x-UI.y<0) { UI.x++; if(UI.x-UI.y>0) break; } } public static void exactDivide() { //使整除 try { UI.z=UI.x/UI.y; } catch (ArithmeticException e) { e.printStackTrace(); } Pattern pattern=Pattern.compile("\\.0$"); //若不是以.0结尾,就没有整除 String s = String.valueOf(UI.z); Matcher matcher=pattern.matcher(s); while(!matcher.find()) { //改变被除数y的值 UI.y=1f; UI.y++; UI.z=UI.x/UI.y; s = String.valueOf(UI.z); matcher=pattern.matcher(s); if(matcher.find()) break; } } public static String chooseCharacter() { //随机选择四种运算符的一个 char[] a={'+','-','*','/'}; String charString=String.valueOf(a[random.nextInt(a.length)]); return charString; } }
这是分开之后的运行结果,仍然可以正常运行。
5.项目github地址
https://github.com/bigApple00/four-types-compute
直接看图,package1中是未划分的版本,package2是划分为用户和算法层。
这是push 、pull request 和merge的过程。
实验总结
之前没做过Java的项目,这次用Java和队友一起写了这个小程序,进一步熟悉了Java语言。在编程过程中遇到很多问题,就比如说正则表达式的使用,GUI的构造函数,都是不太熟悉。只能一点一点去查资料去学习,不断探索,发现问题,寻找解决办法,修改,调试,发现问题....就这样循环下去,直到消除大部分bug能基本运行。还有button和label的布局,用了流式布局显得不是很美观。整数的范围由于为了实现一些要求限制,整除什么的,范围不是很大,这是一方面的不足。
这个小项目虽然不是很起眼,但是包含了我很多的学习探索的过程,勉强说得上增加了项目经验。
进一步掌握了git的命令,GitHub的操作,Java语言,eclipse的debug操作,结对编程的合作经历。
完