结对编程第二次作业
结对编程第二次作业
1.题目要求
题目1:
我们在刚开始上课的时候介绍过一个小学四则运算自动生成程序的例子,请实现它,要求:
- 能够自动生成四则运算练习题
- 可以定制题目数量
- 用户可以选择运算符
- 用户设置最大数(如十以内、百以内等)
- 用户选择是否有括号、是否有小数
- 用户选择输出方式(如输出到文件、打印机等)
- 最好能提供图形用户界面(根据自己能力选做,以完成上述功能为主)
2.分工
本次我的结对对象是杨子昕,在作业的完成过程中,我们交换领航员和驾驶员的角色。本次作业的主要整体设计思路由杨子昕提出;在图形界面的部分,杨子昕作为领航员,我作为驾驶员;在算式生成的部分,我作为领航员,杨子昕作为驾驶员;在文件操作部分,杨子昕作为领航员,我作为驾驶员。
3.我所负责的部分代码的思路
3.1图形界面部分
在该部分,我采用了Javad的swing工具来构建页面,主要运用了JFrame,JPanel,JButton,JComboBox,JDialog,JLabel,JTextArea,JTextField类。该部分负责收集用户输入的信息,将必要信息传给算式生成类的实例对象,在生成完毕之后选择算式的输出方式。
代码如下:
package ppp;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.WindowConstants;
public class Frame extends JFrame{
private final String[] COMMAND = new String[] {"加减","乘除","小数","括号","输出方式","最大值","题目数量"};
private final String[] KEY = new String[] {"开始","退出"};
private final String[] ITEMS = new String[] {"yes","no"};
private final String[] ITEMS1 = new String[] {"输出到文件","输出到屏幕"};
private final String[] ITEMS2 = new String[] {"10","100","1000"};
private final String[] TIPSINFOR = new String[] {"正在出题,请稍候","出题完毕,请到文件中查看","出题完毕,请到控制台查看"};
private JDialog jd;
private JTextArea jta;
private String[] infor = new String[6];//收集页面信息,供生成类调用
private int numOfEquation = 20;
private JButton[] button = new JButton[KEY.length];//开始与退出按键
@SuppressWarnings("rawtypes")
private JComboBox[] combobox = new JComboBox[6];//复选
private JDialog[] dialog = new JDialog[3];//题目生成过程中的提示弹窗
private JLabel[] tips = new JLabel[3];//题目生成过程中的提示弹窗内容
private JTextField jt;//输入题目生成数量
private JLabel[] label = new JLabel[COMMAND.length];//为每个选项创建标签
private JPanel[] panel = new JPanel[16];//创建面板
public void creatJFrame() {
JFrame jf = new JFrame("四则运算生成器");
Container container = jf.getContentPane();
container.setLayout(new GridLayout(8,2,10,10));//8行2列
this.dialog = creatJDialog();
for(int i = 0; i < 16; ++i)
panel[i] = new JPanel(new GridLayout(1,1,10,10));//布局
for(int i = 0; i < COMMAND.length; ++i){
label[i] = new JLabel(COMMAND[i]);
label[i].setHorizontalAlignment(SwingConstants.CENTER);
panel[i*2].add(label[i]);
if(i<4) {
combobox[i] = new JComboBox<String>(ITEMS);
panel[i*2+1].add(combobox[i]);
}else if(i == 4) {
combobox[i] = new JComboBox<String>(ITEMS1);
panel[i*2+1].add(combobox[i]);
}else if(i == 5) {
combobox[i] = new JComboBox<String>(ITEMS2);
panel[i*2+1].add(combobox[i]);
}else {
jt = new JTextField("20",20);
panel[i*2+1].add(jt);
}
}
for(int i = 0; i < KEY.length; ++i){//按键加入面板
button[i] = new JButton(KEY[i]);
panel[14+i].add(button[i]);
}
button[0].addActionListener(new ActionListener() {//开始按键监听器
public void actionPerformed(ActionEvent e) {
//读信息
dialog[0].setVisible(true);
for(int i=0;i<6;++i)
infor[i] = (String) combobox[i].getSelectedItem();
numOfEquation = Integer.parseInt(jt.getText());//题目数量
//1 2 3 5
//生成"乘除","小数","括号","最大值"
//"加减","乘除","小数","括号","输出方式","最大值","题目数量"
CreateList cl = new CreateList();
OutputFile of = null;
try {
of = new OutputFile();
} catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
jta = new JTextArea(10,10);
jta.setVisible(false);
jd = new JDialog();
jd.add(jta);
jd.setSize(200, 5000);
jd.setVisible(false);
for(int i=0; i<numOfEquation; ++i) {
ArrayList<StringBuffer> arr = cl.create(infor[1],infor[2],infor[3],infor[5]);
if(infor[4] == "输出到文件") {
try {
of.write(arr);
} catch (IOException e1) {
e1.printStackTrace();
}
} else {
String str = new String();
for(StringBuffer sb:arr)
str += sb.toString();
jta.append(str);
jta.append("\r\n");
jd.setVisible(true);
jta.setVisible(true);
}
}
try {
of.close();
} catch (IOException e1) {
e1.printStackTrace();
}
//生成完毕
dialog[0].setVisible(false);//生成完毕,关闭进行时提示标签
if(infor[4]=="输出到文件") {
dialog[1].setVisible(true);
}else {
dialog[2].setVisible(true);
}
}
});
//退出按键监听器
button[1].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(-1);
}
});
//面板添加到容器
for(int i = 0; i < 16; ++i)
container.add(panel[i]);
//JFrame属性
jf.setLocation(100, 100);
jf.setSize(500,300);
jf.setVisible(true);
jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public JDialog[] creatJDialog() {
for(int i=0;i<3;++i) {
this.dialog[i] = new JDialog(this,"提示");
this.dialog[i].setSize(200, 100);
tips[i]=new JLabel(TIPSINFOR[i]);
tips[i].setHorizontalAlignment(SwingConstants.CENTER);
this.dialog[i].add(tips[i]);
}
return dialog;
}
public static void main(String[] args) {
new Frame().creatJFrame();
}
}
功能界面:
-
初始界面:
-
输出到文件
-
输出到屏幕
遇到的问题及解决方法:
由于先前对Java的swing界面部分的学习不够以及对程序功能的理解不够透彻,使得在添加在各个组件的监听器造成了浪费。在杨子昕的纠正下,我改用两个监听器,分别负责监听开始按键和退出按键。由于程序运行需要全部的信息并且提供了默认值,所以只需在用户触发开始按键后再接受信息即可。
3.2文件操作部分
在该部分,主要提供一个输出流供主类将生成的算式写入到文件。
代码如下:
package ppp;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
public class OutputFile {
private File file = null;
private FileWriter fw = null;
public OutputFile() throws IOException {
file = new File("C:\\Users\\dell\\Desktop\\1.txt");
boolean b = file.exists();
if(!b) {
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
fw = new FileWriter(file);
}
public void close() throws IOException {
fw.close();
}
public void write(ArrayList<StringBuffer> arr) throws IOException {
for(StringBuffer sb:arr)
fw.write(sb.toString());
fw.write("\r\n");
}
}
遇到的问题及解决方法:
在对输出结果的检查时发现每个算式不能单独成行,在杨子昕的提醒下,我了解到Windows系统下,回车由"\r\n"表示,在Linux系统中,回车由"\n"表示。
4.代码地址
https://github.com/users/wangxnxn/projects/1
5.自我总结
在本次任务中由杨子昕负责指导,在组件的选择和使用,异常的处理方面给予了我很多的宝贵意见,使我学到了很多平常不了解或并未重视的知识。使我体会到了结对编程的优势,也体会到了Java的类库的多样性和使用的便捷性。
6.算式生成类的代码审查表
7.总结与评价
杨子昕负责的部分是算式生成,这也是整个工程中的最难的部分。在杨子昕的代码中灵活运用了计算机的数据处理能力,在容器的选择,字符串与数字的转换,括号的添加,小数的生成上别出心裁,降低了运算次数,提高了效率。
代码作者 |
杨子昕 | 代码名称 | 算式生成 |
审查人 |
王肖男 | 审查时间 | 2019.5.3 |
重要性 |
激活 |
级别 |
检查项 |
重要 |
Y |
20 |
命名规则是否与所采用的规范保持一致? |
Y |
20 |
是否遵循了最小长度最多信息原则? |
|
重要 |
Y |
50 |
has/can/is前缀的函数是否返回布尔型? |
注释 |
|||
重要 |
Y |
10 |
注释是否较清晰且必要? |
重要 |
Y |
10 |
复杂的分支流程是否已经被注释? |
Y |
10 |
距离较远的}是否已经被注释? |
|
Y |
10 |
非通用变量是否全部被注释? |
|
重要 |
Y |
50 |
函数是否已经有文档注释?(功能、输入、返回及其他可选) |
Y |
10 |
特殊用法是否被注释? |
|
声明、空白、缩进 |
|||
Y |
20 |
每行是否只声明了一个变量?(特别是那些可能出错的类型) |
|
重要 |
Y |
40 |
变量是否已经在定义的同时初始化? |
重要 |
Y |
40 |
类属性是否都执行了初始化? |
Y |
20 |
代码段落是否被合适地以空行分隔? |
|
Y |
20 |
是否合理地使用了空格使程序更清晰? |
|
Y |
20 |
代码行长度是否在要求之内? |
|
N |
20 |
折行是否恰当? |
|
语句/功能分布/规模 |
|||
Y |
20 |
包含复合语句的{}是否成对出现并符合规范? |
|
Y |
20 |
是否给单个的循环、条件语句也加了{}? |
|
Y |
20 |
if/if-else/if-else if-else/do-while/switch-case语句的格式是否符合规范? |
|
Y |
40 |
单个变量是否只做单个用途? |
|
重要 |
Y |
20 |
单行是否只有单个功能?(不要使用;进行多行合并) |
重要 |
Y |
40 |
单个函数是否执行了单个功能并与其命名相符? |
Y |
20 |
操作符++和——操作符的应用是否复合规范? |
|
规模 |
|||
重要 |
Y |
20 |
单个函数不超过规定行数? |
重要 |
Y |
100 |
缩进层数是否不超过规定? |
重要 |
Y |
100 |
是否已经消除了所有警告? |
重要 |
Y |
40 |
常数变量是否声明为final? |
重要 |
N |
80 |
对象使用前是否进行了检查? |
重要 |
N |
80 |
局部对象变量使用后是否被复位为NULL? |
重要 |
N |
70 |
对数组的访问是否是安全的?(合法的index取值为[0, MAX_SIZE-1])。 |
重要 |
N |
20 |
是否确认没有同名变量局部重复定义问题? |
Y |
20 |
程序中是否只使用了简单的表达式? |
|
重要 |
Y |
20 |
是否已经用()使操作符优先级明确化? |
重要 |
Y |
20 |
所有判断是否都使用了(常量==变量)的形式? |
N |
80 |
是否消除了流程悬挂? |
|
重要 |
N |
80 |
是否每个if-else if-else语句都有最后一个else以确保处理了全集? |
重要 |
N |
80 |
是否每个switch-case语句都有最后一个default以确保处理了全集? |
Y |
80 |
for循环是否都使用了包含下限不包含上限的形式?(k=0; k<MAX) |
|
重要 |
Y |
40 |
XML标记书写是否完整,字符串的拼写是否正确? |
N |
40 |
对于流操作代码的异常捕获是否有finally操作以关闭流对象? |
|
N |
20 |
退出代码段时是否对临时对象做了释放处理? |
|
重要 |
N |
40 |
对浮点数值的相等判断是否是恰当的?(严禁使用==直接判断) |
可靠性(函数) |
|||
重要 |
Y |
60 |
入口对象是否都被进行了判断不为空? |
重要 |
Y |
60 |
入口数据的合法范围是否都被进行了判断?(尤其是数组) |
重要 |
Y |
20 |
是否对有异常抛出的方法都执行了try...catch保护? |
重要 |
Y |
80 |
是否函数的所有分支都有返回值? |
重要 |
Y |
50 |
int的返回值是否合理?(负值为失败,非负值成功) |
Y |
20 |
对于反复进行了int返回值判断是否定义了函数来处理? |
|
Y |
60 |
关键代码是否做了捕获异常处理? |
|
重要 |
N |
60 |
是否确保函数返回CORBA对象的任何一个属性都不能为null? |
重要 |
N |
60 |
是否对方法返回值对象做了null检查,该返回值定义时是否被初始化? |
重要 |
Y |
60 |
是否对同步对象的遍历访问做了代码同步? |
重要 |
N |
80 |
是否确认在对Map对象使用迭代遍历过程中没有做增减元素操作? |
重要 |
N |
60 |
线程处理函数循环内部是否有异常捕获处理,防止线程抛出异常而退出? |
N |
20 |
原子操作代码异常中断,使用的相关外部变量是否恢复先前状态? |
|
重要 |
Y |
100 |
函数对错误的处理是恰当的? |
可维护性 |
|||
重要 |
N |
100 |
实现代码中是否消除了直接常量?(用于计数起点的简单常数例外) |
Y |
20 |
是否消除了导致结构模糊的连续赋值?(如a= (b=d+c )) |
|
Y |
20 |
是否每个return前都要有日志记录? |
|
N |
20 |
是否有冗余判断语句?(如:if (b) return true; else return false;) |
|
Y |
20 |
是否把方法中的重复代码抽象成私有函数? |