首页 > 编程语言 >【HNU 个人项目互评】结对编程互评-Java

【HNU 个人项目互评】结对编程互评-Java

时间:2023-09-19 20:57:51浏览次数:48  
标签:Java String 题目 int tempTitle 互评 HNU new append

【结对编程互评-Java】中小学数学卷子自动生成程序


项目名称:中小学数学卷子自动生成程序
编程语言:Java
代码作者:张钉
评价人:张诗泉


目录


1. 项目要求

1.1 目标用户:

小学、初中和高中数学老师。

1.2 实现功能:

1、命令行输入用户名和密码,两者之间用空格隔开(程序预设小学、初中和高中各三个账号,具体见附表),如果用户名和密码都正确,将根据账户类型显示“当前选择为XX出题”,XX为小学、初中和高中三个选项中的一个。否则提示“请输入正确的用户名、密码”,重新输入用户名、密码;
2、登录后,系统提示“准备生成XX数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):”,XX为小学、初中和高中三个选项中的一个,用户输入所需出的卷子的题目数量,系统默认将根据账号类型进行出题。每道题目的操作数在1-5个之间,操作数取值范围为1-100;
3、题目数量的有效输入范围是“10-30”(含10,30,或-1退出登录),程序根据输入的题目数量生成符合小学、初中和高中难度的题目的卷子(具体要求见附表)。同一个老师的卷子中的题目不能与以前的已生成的卷子中的题目重复(以指定文件夹下存在的文件为准,见5);
4、在登录状态下,如果用户需要切换类型选项,命令行输入“切换为XX”,XX为小学、初中和高中三个选项中的一个,输入项不符合要求时,程序控制台提示“请输入小学、初中和高中三个选项中的一个”;输入正确后,显示“”系统提示“准备生成XX数学题目,请输入生成题目数量”,用户输入所需出的卷子的题目数量,系统新设置的类型进行出题;
5、生成的题目将以“年-月-日-时-分-秒.txt”的形式保存,每个账号一个文件夹。每道题目有题号,每题之间空一行;

附表-1:账户、密码

账户类型 账户 密码
小学 张三1 123
小学 张三2 123
小学 张三3 123
初中 李四1 123
初中 李四2 123
初中 李四3 123
高中 王五1 123
高中 王五2 123
高中 王五3 123

附表-2:小学、初中、高中题目难度要求

阶段 小学 初中 高中
难度要求 +,-,*./ 平方,开根号 sin,cos,tan
备注 只能有+,-,*./和() 题目中至少有一个平方或开根号的运算1=符 题目中至少有一个sin,cos或tan的运算符

2. 代码分析

main方法:

public class AutoTestPaper{
	public static void main(String args[]) {
	    Scanner input = new Scanner(System.in);
            UserOperate loginUser = new UserOperate();
            while(true) {
        	System.out.println("请输入用户名、密码");
        	loginUser.userLogin(input.next(), input.next().trim());
	    }
    }
}

分析:调用scanner对呼出的登陆界面传参,简洁明了。

PaperMaker类:

interface ProduceRandom{
	public abstract boolean fun();
}

class PaperMake implements ProduceRandom {
	List<String> primaryMathSign = new ArrayList<>();
	// 存储高中特殊运算符
	List<String> juniorMathSign = new ArrayList<>();
	// 存储初中特殊运算符
	List<String> highMathSign = new ArrayList<>();
	// 存储基础运算符
	
	public PaperMake() {
		highMathSign.add("sin");
		highMathSign.add("cos");
		highMathSign.add("tan");
		// 高中难度题目特殊运算符
		juniorMathSign.add("√");
		juniorMathSign.add("^2");
		// 初中难度题目特殊运算符
		primaryMathSign.add("+");
		primaryMathSign.add("-");
		primaryMathSign.add("*");
		primaryMathSign.add("/");
		// 题目基础运算符
	}
	
	@Override
	public boolean fun() {
		boolean sign=false;
		Random random=new Random();
		int cnt=random.nextInt(2);
		if(cnt == 0) {
			sign = false;
		}
		else {
			sign = true;
		}
		return sign;
	}
	//重写fun方法用于括号,特殊符号随机生成
	
	public void primaryPaper(User user, int amount) {
		for(int i = 0; i < amount; i++) {
			StringBuffer tempTitle = new StringBuffer();
			Random random = new Random();
			int signAmount = random.nextInt(4) + 2;
			// 操作数的数量,范围为2-5
			int bracket = 0;
			// 括号的数量
			
			while(signAmount-- > 0) {
				if(signAmount > 1 && this.fun()) {
					tempTitle.append("(");
					bracket++;
				}
				// 判断是否加左括号
				
				int number = random.nextInt(100) + 1;
				tempTitle.append(number);
				// 加入操作数,范围为1-100
				
				// 判断是否加右括号
				if(this.fun() && bracket > 0) {
					tempTitle.append(")");
					bracket--;
				}
				
				if(signAmount == 0) {
					while(bracket-- > 0) {
						tempTitle.append(")");
					}
				}
				// 如果出题结束,补齐右括号
				
				if(signAmount > 0) {
					tempTitle.append(primaryMathSign.get(random.nextInt(4)));
				}
				// 加入基础运算符
			}
			tempTitle.append(" = ");
			// 试题完成,加入等号
			
			IOTxt txtGenerate = new IOTxt();
			File newFile = txtGenerate.makeFile(user);
			// 创建试卷文件
			String titlePaper = tempTitle.toString();
			// 类型转换为String
			if(!txtGenerate.checkTitle(newFile, titlePaper)) {
				txtGenerate.writeIn(newFile, i + 1, titlePaper);
			} else {
				i--;
			}
			// 试卷查重并写入,当重复时不写入txt不增加题目数量并重新出题
	    }
		System.out.println("当前试卷已输出完毕");
	}
	
	public void juniorHighPaper(User user, int amount) {
		for(int i = 0; i < amount; i++) {
			StringBuffer tempTitle = new StringBuffer();
			Random random = new Random();
			int signAmount = random.nextInt(4) + 2;
			// 操作数的数量,范围为2-5
			int bracket = 0;
			// 括号的数量
			
			while(signAmount-->0) {
				if(this.fun() || signAmount == 0) {
					tempTitle.append(juniorMathSign.get(0));
				}
				// 判断是否加根号
				
				if(signAmount > 1 && this.fun()) {
					tempTitle.append("(");
					bracket++;
				}
				// 判断是否加左括号
				
				int number = random.nextInt(100) + 1;
				tempTitle.append(number);
				// 加入操作数,范围为1-100
				
				if(this.fun() && bracket > 0) {
					tempTitle.append(")");
					bracket--;
					//判断是否加右括号
				}
				
				if(signAmount == 0) {
					while(bracket-- > 0) {
						tempTitle.append(")");
					}
				}
				// 如果出题结束,补齐右括号
				
				if(this.fun()) {
					tempTitle.append(juniorMathSign.get(1));
				}
				// 判断是否加平方
				
				if(signAmount > 0) {
					tempTitle.append(primaryMathSign.get(random.nextInt(4)));
				}
				// 加入基础运算符	
			}
			tempTitle.append(" = ");
			// 试题完成,加入等号
			
			IOTxt txtGenerate = new IOTxt();
			File newFile = txtGenerate.makeFile(user);
			// 创建试卷文件
			String titlePaper = tempTitle.toString();
			// 类型转换为String
			if(!txtGenerate.checkTitle(newFile, titlePaper)) {
				txtGenerate.writeIn(newFile, i + 1, titlePaper);
			} else {
				i--;
			}
			// 试卷查重并写入,当重复时不写入txt不增加题目数量并重新出题
		}
		System.out.println("当前试卷已输出完毕");
	}
	
	public void highSchoolPaper(User user, int amount) {
		for(int i = 0; i < amount; i++) {
			StringBuffer tempTitle = new StringBuffer();
			Random random = new Random();
			int signAmount = random.nextInt(4) + 2;
			// 操作数的数量,范围为2-5
			int bracket = 0;
			// 括号的数量
			
			while(signAmount-- > 0) {
				if(this.fun() || signAmount == 0) {
					tempTitle.append(highMathSign.get(random.nextInt(3)));
				}
				// 判断是否加三角函数
				
				if(this.fun()) {
					tempTitle.append(juniorMathSign.get(0));
				}
				// 判断是否加根号
				
				if(signAmount > 1 && this.fun()) {
					tempTitle.append("(");
					bracket++;
				}
				// 判断是否加左括号
				
				int number = random.nextInt(100) + 1;
				tempTitle.append(number);
				// 加入操作数,范围为1-100
				
				if(this.fun() && bracket > 0) {
					tempTitle.append(")");
					bracket--;
				}
				// 判断是否加右括号
				
				if(signAmount == 0) {
					while(bracket-- > 0) {
						tempTitle.append(")");
					}
				}
				// 如果出题结束,补齐右括号
				
				if(this.fun()) {
					tempTitle.append(juniorMathSign.get(1));
				}
				// 判断是否加平方
				
				if(signAmount>0) {
					tempTitle.append(primaryMathSign.get(random.nextInt(4)));
				}
				// 添加基础运算符
			}
			tempTitle.append(" = ");
			// 试题完成,加入等号
			IOTxt txtGenerate = new IOTxt();
			File newFile = txtGenerate.makeFile(user);
			// 创建试卷文件
			String titlePaper = tempTitle.toString();
			// 类型转换为String
			if(!txtGenerate.checkTitle(newFile, titlePaper)) {
				txtGenerate.writeIn(newFile, i + 1, titlePaper);
			} else {
				i--;
			}
			// 试卷查重并写入,当重复时不写入txt不增加题目数量并重新出题
		}
		System.out.println("当前试卷已输出完毕");
	}
}

分析:出题类实现随机数接口类。用列表来存储不同等级的运算符,可拓展性高。给不同等级做了不同的出题方法,同样增加了代码的灵活性。

IOTxt类:

class IOTxt {
	 
    // 生成用户文件夹和txt文件
    public File makeFile(User user) {
        String txtPath = "" + user.getName();
        // 相对路径,生成文件夹与src同级
        File file = new File(txtPath);
        Date date = new Date();
        // 处理时间用于txt文件的名称
        SimpleDateFormat dealwithDate = new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss");
        String title = dealwithDate.format(date) + ".txt";
        if (!file.exists()) {
            // 没有对应用户文件夹则生成
            file.mkdirs();
        }
        File paper = new File(txtPath, title);
        try {
            paper.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return paper;
    }
    
    // 写入txt文件
    public void writeIn(File file, Integer num, String title) {
        try {
            // 传入文件,设置为续写文件
            FileWriter fileWriter = new FileWriter(file, true);
            // 题目的序号
            fileWriter.append("第"+num+"道题" + ". " + title);
            // 题目间空一行
            fileWriter.append("\r\n");
            fileWriter.append("\r\n");
            // 刷新后关闭writer
            fileWriter.flush();
            fileWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
	
    // 题目查重
	public boolean checkTitle(File file, String title) {
		 // 定义变量 是否重复
        boolean sign = false;
        // txt文件的上一级目录路径
        String parentPath = file.getParent();
        File parent = new File(parentPath);
        // 遍历上一级目录,得到所有试卷
        File[] allFiles = parent.listFiles();
        // 逐个文件进行查重对比
        for (int i = 0; i < allFiles.length; i++) {
            try {
                FileReader fileReader = new FileReader(allFiles[i]);
                BufferedReader bufferedReader = new BufferedReader(fileReader);
                while (true) {
                    // 逐行读取数据
                    String usedTitle = bufferedReader.readLine();
                    // 跳过空行
                    if (usedTitle == null) {
                        break;
                    }
                    // 以空格为分隔符," "后面是题目
                    String[] realTitle = usedTitle.split(" ");
                    if (realTitle.length > 1) {
                        if (realTitle[1].equals(title)) {
                            System.out.println("题目重复");
                            sign = true;
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return sign;
	}
	
}

分析:将文件保存在相对路径下,用户文件夹在对应的用户有题目时才会生成。有一处命名不规范,变量"dealwhithDate"没有使用小驼峰命名法。

User类:

class  User {
	private String name;
	private String password;
	private String grade;

	public User(String name, String password, String grade) {
		this.name = name;
		this.password = password;
		this.grade = grade;
	}

	public String getName() {
		return this.name;
	}

	public String getPassword() {
		return this.password;
	}

	public String getGrade() {
		return this.grade;
	}

	public void setGrade(String grade) {
		this.grade = grade;
	}

	public void makePaper(User user, int num) {
        PaperMake paperMake = new PaperMake();
        if (this.grade.equals("小学")) {
            paperMake.primaryPaper(user, num);
        } else if (this.grade.equals("初中")) {
            paperMake.juniorHighPaper(user, num);
        } else if (this.grade.equals("高中")) {
            paperMake.highSchoolPaper(user, num);
        }
    }

}

分析:对用户类的三个属性都进行了封装,并且加入了根据当前用户类型生成题目的方法,符合要求。

UserOperate类:

class UserOperate {
    Map<String, User> userMap = new HashMap<>();
	// 存储账号
	public UserOperate() {
		userMap.put("张三1", new User("张三1", "123", "小学"));
		userMap.put("张三2", new User("张三2", "123", "小学"));
		userMap.put("张三3", new User("张三3", "123", "小学"));
		userMap.put("李四1", new User("李四1", "123", "初中"));
		userMap.put("李四2", new User("李四2", "123", "初中"));
		userMap.put("李四3", new User("李四3", "123", "初中"));
		userMap.put("王五1", new User("王五1", "123", "高中"));
		userMap.put("王五2", new User("王五2", "123", "高中"));
		userMap.put("王五3", new User("王五3", "123", "高中"));
	}
	
	public void userLogin(String userName, String userPassword) { 
		Scanner input = new Scanner(System.in);
		User tempUser = userMap.get(userName);
		if(tempUser.getPassword().equals(userPassword)) {
			boolean output = true;
			// 用于判断当输入不合法时不会要求输出题目数量
				while(true) {
					System.out.println("当前选择为" + tempUser.getGrade() + "出题");
					if(output == true) {
						System.out.println("准备生成" + tempUser.getGrade() + "数学题目,请输入生成题目数量(10-30)");
					}
					String str = input.next();
					// 判断输入为"切换为.."或者题目数量
					if(str.contains("切换为")) {
							String givenGrade = str.substring(3);
							if(givenGrade.equals("高中") || givenGrade.equals("初中") || givenGrade.equals("小学")) {
								tempUser.setGrade(givenGrade);
								output = true;
							}
							else {
								output = false;
								System.out.println("请输入小学、初中和高中三个选项中的一个");
							}
					}
					else {
						int number = Integer.parseInt(str);
						// String到int类型转换,得到题目数量
						if(number == -1) {
							System.out.println("已退出登录,请重新登录");
							break;
						}
						// 为-1时退出登录
						else {
							if(number >= 10 && number <= 30) {
								tempUser.makePaper(tempUser, number);
							}
							else {
								System.out.println("输入范围有误,请重新输入:");
							}
						}
					}
				}
		}
		else {
			System.out.println("请输入正确的用户名、密码");
		}
	}
}

分析:
用户的初始化放在了用户操作类中,调用userLogin()登录后直接进入了用户界面。可惜的是,在对输入的处理上用了大量的if-else,导致了对非法输入的处理缺失:
比如,此处用if语句对密码进行了校验,却没有对用户名进行校验,导致输入错误的用户名时,会因为缺少处理而报错;
再比如,切换等级时,缺少对不规范输入的处理,在这种情况下也会报错。
可以考虑使用switch中的default处理各种异常输入,来解决这个问题。

分析总结:

代码结构上,代码结构合理,使用到了接口类ProduceRadom。
代码规范上,除部分地方存在例如"while(true)"/"while (true)"这样小括号前是否有括号不统一与一处变量名不规范外,代码格式与变量命名基本符合规范。
代码功能上,除了在登录和切换时缺少异常输入的处理外,能够正常实现项目要求。


3. 功能测试

3.1 登录功能测试

可以正常登录与切出账号:

能够对密码进行校验,但缺少对用户名的校验:

3.2 出题功能测试:

可以正常进行切换与出题,有对出题数量进行约束:


有对切换难度不符合要求时做处理,但缺少对不规范输入的处理:

3.3 保存与查重功能测试:

能够正确生成用户文件夹与题目文件,经查验,题目进行了查重、无重复题目出现:


4. 优缺点分析及总结

优点:

  1. 代码逻辑清晰、注释明确、格式规范,可读性很高。
  2. 代码结构合理,使用了接口类与其实现,可拓展性很好。
  3. 文件读写操作设计合理,可适应性高。
  4. 用户界面提示清晰,功能完整。

缺点:

  1. 登录时未校验用户名。
  2. 切换难度时未处理异常输入。
  3. 一处变量命名不规范。

总结:

代码整体逻辑清晰、结构合理、格式规范,具有良好的可读性、可拓展性和可适应性,功能实现完整。但在部分细节方面尚缺考虑,在优化之后未来可期。

标签:Java,String,题目,int,tempTitle,互评,HNU,new,append
From: https://www.cnblogs.com/A-Banana/p/17715769.html

相关文章

  • 个人项目互评
    这两天完成了和谢文琛同学的个人项目作业互评。一.功能测试: 能够正常登录各用户且出题符合要求小学难度: 初中难度: 高中难度: 切换难度可以正常实现 输入-1后退出到登录界面 二.优点:1.首先非常完整地实现了系统所需要的功能,生成题目也符合要求。    ......
  • hnu个人编程项目评价
    一、简介1.项目名称:中小学数学卷子自动生成程序2.编程语言:JAVA3.完成情况:按照个人项目需求完成了要求的功能4.完成同学:朱智星,评价者:杨安然5.项目需求:5.1、命令行输入用户名和密码,两者之间用空格隔开(程序预设小学、初中和高中各三个账号,具体见附表),如果用户名和密码都正确,将根......
  • 中小学数学卷子生成程序-个人项目互评
    一、项目需求用户:小学、初中和高中数学老师。功能:命令行输入用户名和密码,两者之间用空格隔开(程序预设小学、初中和高中各三个账号,具体见附表),如果用户名和密码都正确,将根据账户类型显示“当前选择为XX出题”,XX为小学、初中和高中三个选项中的一个。否则提示“请输入正确的用户......
  • Javaweb(第一天)
    一、在网页中的一些基本操作(1)添加title 1<title>杭州亚运会开幕式将实现两个“首次”</title> (2)添加标题(h1---h6) 1<h1>杭州亚运会开幕式将实现两个“首次”</h1> (3)在网页中添加音频,图片,视频audioimgvideo对应三种添加方式(4)在网页中添加文本内容,以及首行缩进,居中,靠......
  • 无涯教程-JavaScript - SUMIF函数
    描述您可以使用SUMIF函数对满足指定条件的范围内的值求和。语法SUMIF(range,criteria,[sum_range])争论Argument描述Required/Optionalrange您要通过条件判断的单元格范围。每个范围中的单元格必须是数字或包含数字的名称,数组或引用。空白和文本值将被忽略。......
  • Python转换JavaScript
    将导入了第三方库的Python代码转换成JavaScript代码的几种方法包括: 1.使用Transcrypt进行转换 Transcrypt可以将Python代码转换为高效的JavaScript代码,并且支持导入使用其他Python库的代码。这意味着你可以使用Transcrypt将包含第三方库的Python代码转换为JavaScript代码。......
  • 湖南大学结对编程个人项目互评
    湖南大学结对编程个人项目互评分析对象:鲁旭同学的个人项目分析人:王明扬一、项目需求用户:小学、初中和高中数学老师。功能:1、命令行输入用户名和密码,两者之间用空格隔开(程序预设小学、初中和高中各三个账号,具体见附表),如果用户名和密码都正确,将根据账户类型显示“当前选择为X......
  • HNU软件工程导论个人项目互评
    湖南大学结对编程之个人项目互评本次博客主要内容是分析结对编程队友的个人项目分析代码作者:谢昶皓分析人:杨虎强目录湖南大学结对编程之个人项目互评本次博客主要内容是分析结对编程队友的个人项目一、分析项目需求中的“坑”1、出题之“坑”1)每个用户出的题目是否符合用......
  • 学习java五月计划
    第一月了解java,学习Java的基础语法,了解常用关键字的使用。搭建Java开发环境,熟练使用idea开发工具进行开发。掌握运算符、表达式、流程控制语句、数组等的使用。第二月面向对象编程,要掌握Java面向对象的基本知识。掌握一些常用类string、arraylist等的使用.掌握开发中......
  • java连接sql server2008 r2 错误Cannot create PoolableConnectionFactory 错误
    解决办法首先确认你的密码是不是对的。如果是对的:所有程序->MicrosoftSQLServer2005->配置工具->SQLServerConfigurationManager 选择:SQLServer2005网络配置,然后选择:MSSQLSERVER的协议,然后将TCP/IP右键启动,然后右键TCP/IP,选择属性,选择IP地址,在IP1下边的“已启用”......