结对编程项目评论
一.总体评价
改项目代码总体上层次分明,对象明确,概念抽象良好,重用性高,但是存在代码冗余部分,且没有设置账号的数据库,仅仅把账户数据放入缓存中,在对象消失数据也会消失,不够严谨,在拓展上不能实现用户注册与注销
二.代码结构分析
五个文件一个对象类文件,三个方法文件,分别用于匹配账户所在年级及转换,产出试卷,和试卷存储入文件夹,最后是一个main文件进行运行
1.User
package individualProject;
public class User {
private String account;
private String password;
private String grade;
public User() {}
public User(User U)
{
this.account = U.account;
this.password = U.password;
this.grade = U.grade;
}
public User(String account,String password,String grade)
{
this.account = account;
this.password = password;
this.grade = grade;
}
public void setAccount(String account) {
this.account = account;
}
public void setPassword(String password) {
this.password = password;
}
public void setGrade(String grade) {
this.grade = grade;
}
public String getAccount() {
return account;
}
public String getGrade() {
return grade;
}
public String getPassword() {
return password;
}
}
定义了一个User类,设置了account,password,grade私有成员,然后通过get,set等函数对私有成员进行获取,封装性良好
2.MatchGradeObj
public class MatchGradeObj {
public static int MatchGrade(String InputCommand)
{
/*
匹配输入对应的功能
返回值为10-30就是该生成的题目数量
-1就是退出登录
0,1,2为切换到的年级的索引
*/
if(InputCommand.matches("^[+-]?[0-9]+"))
{
int num = Integer.parseInt(InputCommand);
if(num == -1)
{
System.out.println("即将退出登录");
return -1;
}
else if(num >= 10 && num <= 30)
{
return num;
}
else
{
System.out.println("输入的题目数量应该在10-30,请重新输入");
return 4;
}
}
else if(InputCommand.equals("切换为小学"))
{
System.out.println("切换到小学年级成功");
return 0;
}
else if(InputCommand.equals("切换为初中"))
{
System.out.println("切换到初中年级成功");
return 1;
}
else if(InputCommand.equals("切换为高中"))
{
System.out.println("切换到高中年级成功");
return 2;
}
else
{
System.out.println("请输入'切换为xx',其中xx为小学,初中,高中中的一个,或者输入正确的题目数量");
return 4;
}
}
}
采用match函数,来匹配是否为数字与字符串,如果为数字,则生成对应的题目数量或者退出登录 如果为文字类,可以进行账户切换,只需对inputcommand进行if else判断即可
3.ProduceExamObj
public class ProduceExamObj {
public static String ProduceExam (int Num,int model)
{
/*
根据传入的model判断生成相应的试卷
*/
//返回最终试卷
String product = "";
//符号表
String []Signs = {"=","+","-","*","/","√","²","sin","cos","tan"};
Random ran = new Random();
//current为当前生成题目的数目
for(int current = 0; current < Num; current++)
{
product += "第"+(current+1)+"题为:";
//operationNum为题目的操作数
int operationNum = ran.nextInt(2,6);
//fBracket为首括号位置,lBracket为尾括号位置
int fBracket = ran=.nextInt(0,operationNum-1);
int lBracket = ran.nextInt(fBracket+1,operationNum);
//radical为最大根号数目,square为最大平方跟号数目
int radical = ran.nextInt(1,operationNum/2+1);
int square = ran.nextInt(1,operationNum/2+1);
//mustSign在该操作数必定有对应的操作符
int mustSign = ran.nextInt(0,operationNum);
//判断这次题目有没有括号
int hasBracket = ran.nextInt(0,2);
for(int now = 0; now < operationNum; now++ )
{
//判断这个数是否有根号
int has = ran.nextInt(0,3);
//判断是否添加高中数学符号
int hasHighSign = ran.nextInt(0,4);
int hasSign = ran.nextInt(7,10);
//添加首括号,且保证括号不在首尾出现
if(hasBracket > 0 && (lBracket-fBracket+1 < operationNum ))
{
if(fBracket == now) {
product+='(';
}
}
//添加高中符号
if(model >=3 )
{
if(mustSign==now)
{
product+=Signs[hasSign];
}
else if(hasHighSign>2)
{
product+=Signs[hasSign];
}
else;
}
//添加开根号
if(model >=2) {
if(mustSign==now && square > 0 && has > 1)
{
product+=Signs[5];
square--;
}
else if(has > 1 && square>0)
{
product+=Signs[5];
square--;
}
else;
}
//增加操作数
product += ran.nextInt(1,101);
//添加平方
if(model==2) {
if (mustSign == now && radical > 0 && has <= 1) {
product += Signs[6];
radical--;
} else if (has > 1 && square > 0) {
product += Signs[6];
radical--;
} else ;
}
//添加末括号,且保证括号不在首尾出现
if(hasBracket > 0 && (lBracket-fBracket+1 < operationNum ))
{
if(lBracket == now) {
product += ')';
}
}
//增加操作符号
if(now != operationNum -1)
{
product += Signs[ran.nextInt(1,5)];
}
}
//最后添加等号
product = product+Signs[0]+'\n';
}
return product;
}
}
创建random随机对象,用于产生随机数,对根号数量,平方数量,是否有括号,括号位置进行随机生成,之后采用for循环对操作数进行依次遍历,根据随机数与判断标志以及账户类型来生成相应的题目
4.CreateFileObj
public class CreateFileObj {
public static void CreateFile(User nowUser,int Num) throws IOException
{
/*
创建文件和文件夹并像其中写入文件数据
*/
//文件夹路径
String path1 = "./"+nowUser.getAccount();
File file = new File(path1);
//格式化时间,获取创建的.txt的文件名字
Date date = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
//生成的txt文件路径
String path2 = path1+"\\"+formatter.format(date)+".txt";
File TxtFile = new File(path2);
//判断是否存在当前用户的文件夹,不存在则创建
if(!file.exists())
{
file.mkdirs();
}
//创建txt文件
try {
TxtFile.createNewFile();
} catch (IOException e) {
System.out.println("生成作业文件txt创建失败");
e.printStackTrace();
}
//存放最终的试卷
String product = "";
//小学出题
if(nowUser.getGrade().equals("小学"))
{
product = ProduceExamObj.ProduceExam(Num,1);
}
else if(nowUser.getGrade().equals("初中"))
{
product = ProduceExamObj.ProduceExam(Num,2);
}
else if(nowUser.getGrade().equals("高中"))
{
product = ProduceExamObj.ProduceExam(Num,3);
}
else;
//往txt文件写入数据
try {
BufferedOutputStream bout= new BufferedOutputStream(new FileOutputStream(TxtFile));
byte [] bytes = product.getBytes();
bout.write(bytes);
bout.flush();
bout.close();
}
catch (FileNotFoundException e) {
System.out.println("文件未找到");
e.printStackTrace();
}
}
}
该文件主要用于对文件进行IO操作,第一步设置格式,对文件名采用formatter设置格式,用字符串操作配置路径,之后if else判断如果不存在创建文件夹,如果存在,在文件下IO,要对小初高进行判断,放入不同的文件夹
5.main
public class Main {
//用户输入的账户和密码
public static String account = null;
public static String password = null;
//匹配相应的年级
public static void LogIN() {
/*
用户登录输入函数
*/
Scanner in = new Scanner(System.in);
System.out.println("请输入用户名和密码:");
account = in.next();
password = in.next();
}
public static void main(String[] args) throws IOException {
Scanner in = new Scanner(System.in);
//判断用户输入是否正确
boolean flag = false;
//所以的年级
String[] Grade = new String[3];
Grade[0] = "小学";
Grade[1] = "初中";
Grade[2] = "高中";
//获取正确的用户
User nowUer = new User();
//用户数据全部存入uerList中
ArrayList<User> userList = new ArrayList<>();
userList.add(new User("张三1", "123", "小学"));
userList.add(new User("张三2", "123", "小学"));
userList.add(new User("张三3", "123", "小学"));
userList.add(new User("李四1", "123", "初中"));
userList.add(new User("李四2", "123", "初中"));
userList.add(new User("李四3", "123", "初中"));
userList.add(new User("王五1", "123", "高中"));
userList.add(new User("王五2", "123", "高中"));
userList.add(new User("王五3", "123", "高中"));
//headEqualLine为多个‘-’字符,美化一下界面
String headEqualLine = new String(new char[70]).replace("\0", "-");
System.out.println(headEqualLine + "中小学数学卷子自动生成程序");
while (true) {
//用户输入
LogIN();
System.out.println(headEqualLine);
//遍历用户,判断该用户是否存在
Iterator<User> it = userList.iterator();
while ((it.hasNext())) {
nowUer = it.next();
if (account.equals(nowUer.getAccount()) && password.equals(nowUer.getPassword())) {
flag = true;
break;
}
}
//当flag为真时,表示当前用户一直在进行操作
if (flag) {
System.out.println("当前为" + nowUer.getGrade() + "出题:");
while (true) {
System.out.println("准备生成" + nowUer.getGrade() + "数学题目,请输入生成题目的数量(输入-1将退出当前用户重新登录)," +
"或者选择切换题目的适用年级,输入'切换为xx',xx为小学,初中,高中中的一个");
System.out.println(headEqualLine);
String InputCommand = in.next();
//获取返回值判断下一步功能
int option = MatchGradeObj.MatchGrade(InputCommand);
if (option >= 0 && option <= 2) {
//匹配到切换的年级
nowUer.setGrade(Grade[option]);
} else if (option >= 10 && option <= 30) {
System.out.println("准备出题,出题数目为:" + option);
System.out.println(headEqualLine);
//生成文件和文件夹
CreateFileObj.CreateFile(nowUer, option);
System.out.println("出题完成请到当前目录下的" + nowUer.getAccount() + "文件夹中查看");
} else if (option == -1) {
System.out.println(headEqualLine + '\n' + '\n');
break;
} else ;
System.out.println(headEqualLine + '\n' + '\n');
}
} else {
System.out.println("用户名或者密码错误,请输入正确的用户名、密码");
flag = false;
}
}
}
}
先是一个login函数获取账户与密码,在运行函数里面,设置年级数组,创建UserList对容器内依次添加账户数据,while循环遍历,寻找登录的用户,如果发现调用MatchGradeObj匹配年级,在判断之后调用CreatFile,创建文件夹,之后再次在CreateFile调用ProduceExam依据账户类型生成试卷
三.代码优缺点分析
1.优点
整体抽象良好,把整个试卷的生成分为三部,匹配年级,创建文件夹,生成试卷,在代码调试时,可以快速定位问题所在,在细节的处理方面也很优秀,例如设置数字索引,可以提升程序效率,随机数生成括号,平方等保证题目的随机性,代码书写规范,注释清楚
2.缺点
ArrayList<User> userList = new ArrayList<>();
userList.add(new User("张三1", "123", "小学"));
userList.add(new User("张三2", "123", "小学"));
userList.add(new User("张三3", "123", "小学"));
userList.add(new User("李四1", "123", "初中"));
userList.add(new User("李四2", "123", "初中"));
userList.add(new User("李四3", "123", "初中"));
userList.add(new User("王五1", "123", "高中"));
userList.add(new User("王五2", "123", "高中"));
userList.add(new User("王五3", "123", "高中"));
在main函数内不建议这样写,建议新建用户数据库,这样做用户数据存在了缓存内,建议后面增添文件IO读写