用Java实现一个简单的考试系统

  • 需求分析
  • 设计思路
  • 编码实现

需求分析

该考试系统可以实现的功能和系统要求应该包括:

  • 学生:登录、考试、考试后查看成绩
  • 老师:出题目(往题库中添加新题目)、批阅卷子(同时打分)
  • 考试系统:学生的登录校验、存储学生的账号和密码、存储题库、去除题库中重复题目、随机抽取一定数目的题目组合成一张卷子、卷子中题目的选项是随机打乱的

设计思路

首先,最关键的是想好怎么去存储题目,题目由题干、选项以及正确答案3部分组成。
数组、Collection集合,Map集合其实都能实现。

其中,我们很自然想到,使用HashMap去存储可能比较简单,它可以用key-value的形式让题目和答案产生一一对应的关系,题干存储为key,选项和答案存储为value,或者题干和选项存储为key,答案存储为value。其实都行,都可以实现,问题是这样设计真的合理吗?

如果把题目存储为Map集合,看起来也许题目和答案的对应关系很强,但是实际上操作起来可能不是那么方便。map集合的get方法,根据一个键找寻对应的值,这样可读性不是很好,而且map集合的遍历,查找也不是那么方便。

除了变量,数组,集合可以用来存储数据,可不要忘了Java当中还有一个,那就是对象,这才是我们首先要想到的。正所谓万物皆对象,数据封装在对象,可读性也会大大增强。

我们不妨使用一个Question对象,来存储单个的题目。把所有的题目存储到HashSet集合里,理由是HashSet集合可以自动帮我们自动去除重复元素,也就是去除重复的题目。

我们假设只要题干相同,这两个题目就是相同的题目。

为了更方便地操作题目中题干、选项、答案这3部分,我们把这3个内容当作属性来处理。

但是可不要忘了想要让HashSet帮我们去除重复元素,我们得先重写hashCode()方法和equals()方法,也就是告诉HashSet,什么样的两个元素可以认定是重复的。

然后,实现学生的登录,系统里需要存储学生的信息,即账号和密码。账号我们存储为String,密码存储为Integer。账号和密码作为键值对可以存储在HashMap里,这样在登录校验的时候不用通过循环来判断账号是否存在以及密码是否正确。

关于类和类之间的关系:学生和系统应该是依赖关系。即学生要考试,考试之前需要先登录。登录以后,才可以进行考试。登录的时候可以把考试系统作为一个对象传入学生的login方法里,使学生和系统建立依赖关系。

老师和系统的关系,也必须是依赖关系,因为老师可以往题库中添加新的题目,而添加题目就要知道往哪个系统的题库中添加。系统中的题库(questionRepository),我们考虑设计为static的,因为它在整个系统中有且仅有一份。

编码实现

Question类:

public class Question {private Integer orderNum;//题号private String title;//题干private String[] option;//选项private String answer;//答案//不包含题号的构造方法,题号的后期生成卷子的时候赋予的public Question(String title, String[] option, String answer) {this.title = title;this.option = option;this.answer = answer;}@Overridepublic boolean equals(Object obj){if (this==obj){//两对象地址相同,那快别比了,肯定相同的对象return true;}if (obj instanceof Question){//首先造型Question anotherQue = (Question)obj;if(this.title.equals(anotherQue.title)){//题目的题干相同,则认为是同一道题,返回truereturn true;}}//obj不是Question类型的,那还比啥呀,肯定不相同return false;}@Overridepublic int hashCode(){//返回题干字符串的 hashcodereturn this.title.hashCode();}//get和set······}

ExamMachine类:

public class ExamMachine {private static Map<String,Integer> userBox = new HashMap<>();//用户信息private static Set<Question> questionRepository = new HashSet<>();//总的题库public ExamMachine(){try {System.out.println("系统正在启动,请稍等····");Thread.sleep(2000);System.out.println("正在加载题库····");Thread.sleep(2000);System.out.println("系统初始化完毕,您可以登录了");} catch (InterruptedException e) {e.printStackTrace();}}{userBox.put("admin",123);userBox.put("java",666);}{questionRepository.add(new Question("假设web应用的文档根目录为MyApp,那么可以从哪里找到database.jar文件",new String[]{"MyApp目录下","MyApp\\images目录下","MyApp\\WEB-INF目录下","MyApp\\WEB-INF\\lib目录下"},"MyApp\\WEB-INF\\lib目录下"));questionRepository.add(new Question("从以下哪一个选项中可以获得Servlet的初始化参数",new String[]{"Servlet","ServletContext","ServletConfig","GenericServlet"},"ServletConfig"));questionRepository.add(new Question("哪一个对象可以用于获得浏览器发送的请求。",new String[]{"HttpServletRequest","HttpServletResponse","HttpServlet","Http"},"HttpServletRequest"));questionRepository.add(new Question("运行jsp需要安装_______Web服务器",new String[]{"Apache","tomcat","都要安装","IIS"},"tomcat"));questionRepository.add(new Question("如何取得数据源",new String[]{"通过Http","通过ftp","JNDI","通过Connection对象"},"JNDI"));questionRepository.add(new Question("下列哪一个接口定义了用于查找、创建和删除EJB实例",new String[]{"Home","Remote","Local","Message"},"Home"));questionRepository.add(new Question("下列哪个为JSP的隐含对象",new String[]{"env","page","jspinfo","context"},"page"));questionRepository.add(new Question("下列哪一个是String类下的方法",new String[]{"add","put","compareTo","string"},"compareTo"));questionRepository.add(new Question("下列哪一个是java.util包下的类",new String[]{"Math","Object","Enum","Scanner"},"Scanner"));questionRepository.add(new Question("下列哪一个不是Java当中的包装类",new String[]{"Integer","Char","Long","Short"},"Char"));}//学生的登录校验public boolean loginCheck(String name,Integer pwd){if(this.userBox.get(name)!=null && this.userBox.get(name).equals(pwd)){return true;}else return false;}//添加题目的方法按理说我们只让老师使用,这里就先不做权限控制了public boolean addQuestion(String title,String[] options,String answer){Question question = new Question(title,options,answer);return this.questionRepository.add(question);}//生成一张卷子,题目随机public ArrayList<Question> generatePaper(){int num = 5;ArrayList<Question> paper = generatePaper(num);return paper;}//可以指定出几道题目public ArrayList<Question> generatePaper(int num){System.out.println("系统正在随机抽取题目生成试卷,这可能需要一段时间,请耐心等候···");try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}ArrayList<Question> questionRepository = new ArrayList<>(this.questionRepository);//把set集合暂时转化为list集合,为的是利用索引来随机HashSet<Question> paper = new HashSet<>();//用来存储题目,set集合去重复//这个while循环用来生成不重复的一套题目while (paper.size()!=num){Question question = questionRepository.get(new Random().nextInt(questionRepository.size()));paper.add(question);}ArrayList<Question> newPaper = new ArrayList<>(paper);ArrayList<Question> finalPaper = new ArrayList<>();//空的ArrayList,用来存放有打乱顺序的,有带选项号的答案的,没有题号的试题。//这个for循环用来给题目中的选项打乱顺序for(int i = 0;i<paper.size();i++){Question question = newPaper.get(i);//选项随机调换顺序,每次生成的选项顺序都不一样//生成随机不重复的索引号,用来生成顺序随机的选项int[] indexs = this.generateRandomIndexs(4, 4);String[] oldOptions = question.getOption();String[] newOptions = new String[oldOptions.length];char firstOrder = 'A';//设置选项的内容,选项的顺序随机for (int j = 0;j<oldOptions.length;j++){String optionOrder = String.valueOf((char)(firstOrder+j));//将char字符转化为StringString option = oldOptions[indexs[j]];newOptions[j] = optionOrder+"."+option;if (option.equals(question.getAnswer())){question.setAnswer(newOptions[j]);}}question.setOption(newOptions);finalPaper.add(question);}return finalPaper;}//将试卷打印到控制台上,不是自己调用,等着学生的startExam方法里面调用public String[] printPaper(ArrayList<Question> paper){Scanner input = new Scanner(System.in);String[] answers = new String[paper.size()];for (int i = 0;i<paper.size();i++){Question question = paper.get(i);question.setOrderNum(i+1);//设置题号System.out.println(question.getOrderNum()+"."+question.getTitle());String[] options = question.getOption();for (int j = 0;j<options.length;j++){System.out.println("\t"+options[j]);}System.out.println("请输入您认为的正确答案:");answers[i] = input.nextLine();//学生的选项}System.out.println("考试结束,请考生停止作答\n监考老师收取试卷中····");try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}return answers;}//==============================================================================================//生成乱序随机索引号(难),生成随机选项的时候要用它private int[] generateRandomIndexs(int num, int bound){//num生成几个,bound是边界int[] indexs = new int[num];for(int i = 0;i<indexs.length;i++){indexs[i] = -1;//初始化数组的每个元素为-1}HashSet<Integer> set = new HashSet<>();//使用Hashset的原因是使用它的不重复规则控制while循环结束的条件int i = 0;//数组的索引号boolean isUse = false;//标记这个数组是否使用过while (set.size()<num){if (isUse==false){int randomIndex = new Random().nextInt(bound);indexs[0] = randomIndex;i++;set.add(randomIndex);isUse = true;}else {int random = new Random().nextInt(bound);boolean isAllNotSame = true;//是否全部不相同for (int j = 0;j<i;j++){if (random == indexs[j]){isAllNotSame = false;//只要有一个重复,就置为false,不存}}if (isAllNotSame){//生成的索引与数组存储的索引不相同,存储它indexs[i] = random;i++;set.add(random);}}}return indexs;}
}

Student类:

public class Student {private String name;private Integer password;private String examNum;//考号,没有登录系统则为nullpublic Student() {}public Student(String name, Integer password) {this.name = name;this.password = password;}//学生登录public String login(ExamMachine em){boolean checkResult = em.loginCheck(this.name, this.password);if (checkResult){examNum = UUID.randomUUID().toString().replace("-","");//登录成功,实例化考生考号System.out.println("登录成功!\n请考生"+this.getName()+"凭借考号"+examNum+"开始作答.\n不要作弊,一旦发现严肃处理!!!");}else {System.err.println("登录失败,用户名或密码错误");}return examNum;}//学生开始考试public String[] startExam(ExamMachine em,ArrayList<Question> paper){if (this.examNum.isEmpty()){System.err.println("您还没有登录,请您先登录系统!");return null;}String[] answers = em.printPaper(paper);return answers;}//get以及set方法····}

Teacher类:

public class Teacher {//往题库里添加新的题目public boolean addQuestion(ExamMachine em,String title,String[] options,String answer){Question question = new Question(title,options,answer);return em.addQuestion(title,options,answer);}//批阅卷子,打分数public float checkPaper(ArrayList<Question> paper,String[] answer){try {System.out.println("系统正在提交答案···");Thread.sleep(2000);System.out.println("老师们正在批阅,请耐心等候····");Thread.sleep(4000);} catch (InterruptedException e) {e.printStackTrace();}float oneQueScore = 100F/paper.size();//一道题的分数float finalScore = 0;for (int i = 0;i<paper.size();i++){String trueAnswer = paper.get(i).getAnswer().substring(0,1);//把选项提取出来,charAt也可以if(trueAnswer.equalsIgnoreCase(answer[i])){finalScore+=oneQueScore;}}return finalScore;}
}

测试函数:

public class TestMain {public static void main(String[] args) {ExamMachine examMachine = new ExamMachine();Teacher teacher = new Teacher();Scanner input = new Scanner(System.in);System.out.println("请输入用户名");String name = input.nextLine();System.out.println("请输入密码");Integer password = input.nextInt();Student student = new Student(name,password);student.login(examMachine);ArrayList<Question> paper = examMachine.generatePaper(5);String[] answers = student.startExam(examMachine, paper);float score = teacher.checkPaper(paper, answers);System.out.println(student.getName()+"的最终成绩为:"+score+"分,(满分为100分)");}
}

补充:该系统的运行截图:




源码补充:
https://gitee.com/luminescent-asphyxia/simple-exam-system.git

用Java实现一个简单的考试系统相关推荐

  1. python中列表和字典的应用-一个简单的考试系统

    1 之前我们学习了列表,知道列表可以用来存储一组数据,可以增删改查,可以遍历 2 之前我们学习了字典,知道字典可以用来存储键值对,与列表类似,字典也可以进行增删改查,同样也可以遍历 这节课我们利用学到 ...

  2. 用python selenium实现一个简单的考试系统的自动做题

    xuefa考试,很实用的东西,不需要废话,直接上代码: # encoding:utf-8 import sys reload(sys) sys.setdefaultencoding('utf8') f ...

  3. 用JSP/Servlet应用开发一个简单的考试报名系统

    用JSP/Servlet实现一个简单的考试报名系统 背景 一.任务/要求 二.对项目需求进行简要的建模概括分析. 2.项目实现. 2.1项目结构. 2.1.1层次结构 2.1.1数据表结构. 2.2项 ...

  4. Java选择题简单的考试系统

    Java选择题简单的考试系统 做前声明: 此系统包括了Java中:面向对象-封装.String-StringBuilder.ArrayList集合.继承-抽象-final.static-接口-多态.四 ...

  5. 山东大学软件学院高级语言课程设计JAVA课程设计-学生在线考试系统平台

    说明:blog 不全面而且也不是上交实验报告的最终版本(是自己实验过程中简单记录的笔记),完整内容(含代码+实验报告)可以通过(山东大学软件学院高级语言课程设计JAVA课程设计-学生在线考试系统平台) ...

  6. java完成一个学生信息调查程序_利用Java设计一个简单的学生信息管理程序

    利用Java设计一个简单的控制台学生信息管理程序 此程序可作为课设的参考,其中信息存储于文件中. 创建了学生类Student,用于存储学号等的信息.创建StudentFunction类,用于实现诸如学 ...

  7. php简单在线考试系统

    php简单在线考试系统 开始第一步 先新建一个文件:testSystem 然后在testSystem里面在新建文件文件名称; 建好以后开始在data里面建一个1.php文件然后开始写代码 <?p ...

  8. Java水果搬运问题_关于Java实现一个简单水果订购管理系统的几点问题

    关于Java实现一个简单水果订购管理系统的几点问题 关于Java实现一个简单水果订购管理系统的几点问题 这个周用java写了一个简单的水果订购系统.其中遇上了几个问题 一.在编写过程中,我试图输入订购 ...

  9. 编写一个简单的考试程序,在控制台完成出题、答题的交互。试题(Question)分为单选(SingleChoice)和多选( MultiChoice)两种。

    编写一个简单的考试程序,在控制台完成出题.答题的交互.试题(Question)分为单选(SingleChoice)和多选( MultiChoice)两种.其中,单选题和多选题继承试题类,如下图所示. ...

最新文章

  1. html代码闪烁的文字怎么打,HTML最简单的文字闪烁代码
  2. 用Zend Stuido 的WSDL编辑器
  3. 高等数学同济第七版课后答案下册
  4. springboot实现简单的文件上传与回显
  5. Catalysing food-tech: How the UK‘s EIT Food Accelerator Network can accelerate your journey
  6. HALCON示例程序measure_pump.hdev螺纹孔位置与尺寸测量
  7. python可以体现数学中映射概念的是_【课时27+集合+在我的世界里+你就是唯一】 - #1...
  8. iPhone在scrollview中双击定点放大的代码
  9. 角度与弧度的转换 C语言
  10. 百度富文本编辑器修改图片上传尺寸
  11. 小孩拉肚子不能吃什么?
  12. Linux 合并多个文件
  13. 关于图像分割的预处理 transform
  14. Windows10企业版 VS2017编译 MongoDB C++ Driver3.1.1 全过程
  15. JAVA面向对象(2)
  16. Linux SDIO WIFI Marvell8801/Marvell88w8801(五) --- Linux SDIO API介绍
  17. 软件测试工程师一定要参加软考吗?
  18. Linux 内存之vmstat
  19. kafka在Windows系统下的安装出现的错误汇总:
  20. 揭秘:女谍川岛芳子究竟是不是双性恋

热门文章

  1. mysql设置约束大于0_MySQL约束
  2. 为什么大家都喜欢买白色的汽车
  3. Eclipse 从SVN检出项目之《文件夹 “” 已不存在 》
  4. Linux和Windows命令行中使用命令的输出(删除几天前的日志)
  5. 主流电子地图API比较 google map api, mapabc ,yahoo地图
  6. GCC编译器与编译过程
  7. python常用数值处理函数_SciPy基础数据操作函数
  8. 空格键 还是 Tab键?
  9. 有赞下拉菜单html,python selenium自动上传有赞单号的操作方法
  10. GUI测试 东南大学 SEU 软件测试