Java数学考试程序--在线等20c悬赏

实现一个数学考试程序(使用异常处理机制处理可能出现的异常)。要求如下:
1、设计图形界面程序;
2、随机出题,进行100以内的四则运算,每次考试限时5分钟;
3、每次出10题,回答后提交,显示出错题目及回答正确率;
4、可以保存考试历史记录,并能调出查看。

package mathtest;
import java.awt.Color;

import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;
/**

  • @author xxx [hushaorei@163.com]
    */
    public class MathTest implements ActionListener {
    private int totalTime = 5 * 60;//考试总用时,单位秒(可修改)
    private Font defaltFont = new Font("微软雅黑",0,13);//(可修改)
    private int questionCount = 10;//题目的数量(可修改)
    private int TestLimit = 100;//限制在100以内运算(可修改)
    private String gradeFileUrl = "classpath:/grade.txt";//成绩打印地址(可修改,可以为绝对路径)
    private boolean canSubmit;//未答完能否提交,默认false不可提交(可修改)
    private JFrame frame;
    private Container contentPane;
    private JLabel timeLabel;//显示时间
    private Timer timer;//计时器
    private String[] operators = new String[]{"+","-","×","÷"};
    private int testStatus = 0;//考试状态 0:未开始,1:正在考试,2结束
    private Date startTime;//开始答题时间
    private Date submitTime;//提交时间
    private List questions = new ArrayList();
    private Question currentQuestion;//当前显示试题
    private JPanel panel;//显示运算区
    private JLabel questionSort;//显示第几题
    private JTextField firstNumField;//显示第一个数
    private JLabel signLabel;//显示运算符
    private JTextField secondNumField;//显示第二个数
    private JLabel equalLabel;//显示等号
    private JTextField resultNumField;//显示结果
    private JPanel btnPanel;//显示按钮
    private JButton preBtn;//上一题(或开始)
    private JButton nextBtn;//下一题(或提交)
    public MathTest() {
    int width = 400;//界面宽度
    int height = 200;//界面高度
    frame = new JFrame("数学考试");
    Toolkit toolkit = Toolkit.getDefaultToolkit();
    int x = (toolkit.getScreenSize().width - width) / 2;
    int y = (toolkit.getScreenSize().height - height) / 2;
    frame.setBounds(x, y, width, height);
    frame.setResizable(false);
    contentPane = frame.getContentPane();
    contentPane.setLayout(new GridLayout(3, 1, 0, 0));
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    init();
    }
    //获得显示剩余时间的字符串
    public String getTimeString(int currentTime) {
    int minute = currentTime / 60;
    int second = currentTime % 60;
    return (minute==0?"":minute+"分")+(second<10?("0"+second):second)+"秒";
    }

    private void init() {
    timeLabel = new JLabel("剩余时间:" + getTimeString(totalTime), JLabel.CENTER);
    panel = new JPanel();
    questionSort = new JLabel("");
    firstNumField = new JTextField();
    firstNumField.setHorizontalAlignment(JTextField.CENTER);
    firstNumField.setPreferredSize(new Dimension(90, 30));
    firstNumField.setEditable(false);
    firstNumField.setBackground(Color.WHITE);
    signLabel = new JLabel("+");
    secondNumField = new JTextField();
    secondNumField.setHorizontalAlignment(JTextField.CENTER);
    secondNumField.setPreferredSize(new Dimension(90, 30));
    secondNumField.setEditable(false);
    secondNumField.setBackground(Color.WHITE);
    equalLabel = new JLabel("=");
    resultNumField = new JTextField();
    resultNumField.setHorizontalAlignment(JTextField.CENTER);
    resultNumField.setPreferredSize(new Dimension(90, 30));
    resultNumField.addKeyListener(new KeyAdapter() {
    public void keyTyped(KeyEvent e) {
    int temp = e.getKeyChar();
    if (temp > 57 || temp < 48 || resultNumField.getText().length()>1) {
    e.consume();
    }
    }
    });
    btnPanel = new JPanel();
    btnPanel.setLayout(new GridLayout(1, 2, 0, 0));
    preBtn = new JButton("开始考试");
    preBtn.addActionListener(this);
    preBtn.setFocusable(false);
    nextBtn = new JButton("提交");
    nextBtn.setFocusable(false);
    nextBtn.addActionListener(this);
    timer = new Timer(1000, this);
    panel.add(questionSort);
    panel.add(firstNumField);
    panel.add(signLabel);
    panel.add(secondNumField);
    panel.add(equalLabel);
    panel.add(resultNumField);
    panel.setVisible(false);
    btnPanel.add(preBtn);
    btnPanel.add(nextBtn);
    contentPane.add(timeLabel);
    contentPane.add(panel);
    contentPane.add(btnPanel);
    setDefaultFont(defaltFont);
    }
    //设置默认字体样式
    private void setDefaultFont(Font defaltFont) {
    Field[] fields = this.getClass().getDeclaredFields();
    for (Field field : fields) {
    try {
    Container container = null;
    field.setAccessible(true);
    if (field.get(this) instanceof Container) {
    container = (Container) field.get(this);
    container.setFont(defaltFont);
    }
    field.setAccessible(false);
    } catch (IllegalArgumentException e) {
    e.printStackTrace();
    } catch (IllegalAccessException e) {
    e.printStackTrace();
    }
    }
    }
    public void show() {
    frame.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
    Object obj = e.getSource();
    if (obj == preBtn) {
    if (testStatus == 0) {
    startTest();
    } else if (testStatus == 1) {
    int sort = currentQuestion.getSort();
    if (sort == 10) {
    nextBtn.setText("下一题");
    }
    if (sort == 1) {
    JOptionPane.showMessageDialog(null, "已经是第一题了!");
    } else {
    setResult();
    currentQuestion = questions.get(sort - 2);
    changeQuestion();//上一题
    }
    } else if (testStatus == 2) {
    int confirm = JOptionPane.showConfirmDialog(null, "是否进行下一场考试?");
    if (confirm == JOptionPane.YES_OPTION) {
    questions.clear();
    startTest();
    }
    }
    } else if (obj == nextBtn) {
    if (testStatus == 1) {
    int sort = currentQuestion.getSort();
    if (sort == 9) {
    nextBtn.setText("提交");
    } else if (sort == 10) {
    setResult();
    int count = 0;//未答的题目数量
    for (Question question : questions) {
    if (question.getResult() == null) {
    count ++;
    }
    }
    if (count > 0) {
    JOptionPane.showMessageDialog(null, "您还有"+ count + "道题未答!");
    if (! canSubmit) {
    return;
    }
    }
    int confirm = JOptionPane.showConfirmDialog(null, "是否提交试卷?");
    if (confirm == JOptionPane.YES_OPTION) {
    submitAndPrintGrade();//提交打印成绩
    }
    return;
    }
    setResult();
    currentQuestion = questions.get(sort);
    changeQuestion();//下一题
    } else if (testStatus == 0) {
    JOptionPane.showMessageDialog(null, "考试还未开始!");
    } else if (testStatus == 2) {
    JOptionPane.showMessageDialog(null, "考试已经结束!");
    }
    } else if (obj == timer) {
    timeLabel.setText("剩余时间:" + getTimeString(-- totalTime));
    if (totalTime == 0) {
    submitAndPrintGrade();
    JOptionPane.showMessageDialog(null, "时间到,自动提交!");
    }
    }
    }
    private void submitAndPrintGrade() {
    preBtn.setText("开始考试");
    testStatus = 2;
    submitTime = new Date();
    timer.stop();
    String fileUrl = null;
    if (gradeFileUrl.startsWith("classpath:/")) {
    String classPathUrl = this.getClass().getResource("/").getPath();
    classPathUrl = classPathUrl.substring(1, classPathUrl.length());//去除第一个'/'
    fileUrl = gradeFileUrl.replaceAll("classpath:", classPathUrl);
    if (classPathUrl.contains("%")) {
    System.err.println("路径中可能存在中文或空格!");
    }
    } else {
    fileUrl = gradeFileUrl;
    }
    File gradeFile = new File(fileUrl);
    if (! gradeFile.exists()) {
    try {
    gradeFile.createNewFile();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    PrintWriter writer = null;
    try {
    FileWriter fw = new FileWriter(gradeFile,true);
    writer = new PrintWriter(fw);
    String text = "------------------------------------------------------";
    writer.println(text);
    DateFormat df = new SimpleDateFormat("YYYY年MM月dd日 HH时mm分ss秒");
    text = "开始答题时间:" + df.format(startTime);
    writer.println(text);
    text = "结束答题时间:" + df.format(submitTime);
    writer.println(text);
    long usedTime = submitTime.getTime() - startTime.getTime();
    long minutes = usedTime / 1000 / 60;
    long seconds = (usedTime - minutes * 1000 * 60) / 1000;
    long mseconds = usedTime - minutes * 1000 * 60 - seconds * 1000;
    text = "总共用时:" + minutes + "分" + seconds + "秒" + mseconds + "毫秒";
    writer.println(text);
    int count = 0;//答对题目数
    for (Question question : questions) {
    if (question.getResult()!=null&&question.getResult()==question.getRealResult()) {
    count++;
    }
    }
    String accuracy = (int)(count*100/questionCount) + "%";//正确率
    text = "共"+questionCount+"题,答对"+count+"道,答错"+(questionCount-count)
    +"道,正确率:"+ accuracy;
    writer.println(text);
    writer.println();
    text = "序号\t题目\t\t正确答案\t批改";
    writer.println(text);
    for (int i = 1; i < questions.size()+1; i ++) {
    Question q = questions.get(i-1);
    String correct = (q.getResult()!=null&&q.getRealResult()==q.getResult())?"√":"×";
    text = "第"+numStr(i)+"道:\t"+numStr(q.getFirstNum())+q.getOperator()
    +numStr(q.getSecondNum())+" = "+(q.getResult()==null?"未答":numStr(q.getResult()))+"\t"+
    numStr(q.getRealResult())+"\t"+correct;
    writer.println(text);
    }
    text = "------------------------------------------------------";
    writer.println(text);
    writer.println();
    writer.flush();
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    if (writer != null)writer.close();
    }
    }
    private String numStr(int number) {
    return number }
    //开始考试
    private void startTest() {
    //先初始化题目
    for (int i = 0; i //随机0-3,得到运算符
    String operator = operators[(int)(Math.random()*4)];
    //随机第一个数0-99
    int firstNum = (int)(Math.random()*TestLimit);
    //随机第二个数0-99
    int secondNum = (int)(Math.random()*TestLimit);
    Integer result = null;
    if ("+".equals(operator)) {
    result = firstNum + secondNum;
    while (result >= 100) {
    firstNum = (int)(Math.random()*TestLimit);
    secondNum = (int)(Math.random()*TestLimit);
    result = firstNum + secondNum;
    }
    } else if ("-".equals(operator)) {
    if (firstNum < secondNum) {
    int temp = firstNum;
    firstNum = secondNum;
    secondNum = temp;
    }
    result = firstNum - secondNum;
    } else if ("×".equals(operator)) {
    result = firstNum * secondNum;
    while (result >= 100) {
    firstNum = (int)(Math.random()*TestLimit);
    secondNum = (int)(Math.random()*TestLimit);
    result = firstNum * secondNum;
    }
    } else if ("÷".equals(operator)) {
    while (secondNum == 0) {
    secondNum = (int)(Math.random()*(TestLimit-1)+1);
    }
    result = firstNum % secondNum;
    while (result != 0) {
    firstNum = (int)(Math.random()*(TestLimit-1)+1);
    secondNum = (int)(Math.random()*(TestLimit-1)+1);
    result = firstNum % secondNum;
    }
    result = firstNum / secondNum;
    } else {
    throw new RuntimeException("不支持的运算符:" + operator);
    }
    Question question = new Question();
    question.setSort(i + 1);
    question.setFirstNum(firstNum);
    question.setSecondNum(secondNum);
    question.setOperator(operator);
    question.setRealResult(result);
    questions.add(question);
    }
    testStatus = 1;//状态改为正在考试
    currentQuestion = questions.get(0);
    changeQuestion();
    panel.setVisible(true);
    preBtn.setText("上一题");
    nextBtn.setText("下一题");
    timer.start();//计时器开始
    startTime = new Date();//开始时间
    }
    //设置显示题目
    private void changeQuestion() {
    int sort = currentQuestion.getSort();
    questionSort.setText("第"+(sort<10?("0"+sort):(sort+""))+"题:");
    firstNumField.setText(currentQuestion.getFirstNum()+"");
    signLabel.setText(currentQuestion.getOperator());
    Integer result = currentQuestion.getResult();
    if (result == null) {
    resultNumField.setText("");
    } else {
    resultNumField.setText(result.toString());
    }
    secondNumField.setText(currentQuestion.getSecondNum()+"");
    }
    //将输入框的结果设置进question
    private void setResult() {
    if (!"".equals(resultNumField.getText().trim())) {
    currentQuestion.setResult(Integer.parseInt(resultNumField.getText().trim()));
    } else {
    currentQuestion.setResult(null);
    }
    }
    public static void main(String[] args) {
    new MathTest().show();
    }
    }
    class Question {
    private int sort;//第几道题
    private int firstNum;
    private int secondNum;
    private String operator;//运算符
    private Integer result;//输入的答案
    private int realResult;//真正答案
    public int getSort() {
    return sort;
    }
    public void setSort(int sort) {
    this.sort = sort;
    }
    public int getFirstNum() {
    return firstNum;
    }
    public void setFirstNum(int firstNum) {
    this.firstNum = firstNum;
    }
    public int getSecondNum() {
    return secondNum;
    }
    public void setSecondNum(int secondNum) {
    this.secondNum = secondNum;
    }
    public String getOperator() {
    return operator;
    }
    public void setOperator(String operator) {
    this.operator = operator;
    }
    public Integer getResult() {
    return result;
    }
    public void setResult(Integer result) {
    this.result = result;
    }
    public int getRealResult() {
    return realResult;
    }
    public void setRealResult(int realResult) {
    this.realResult = realResult;
    }
    }
    无聊花了半天写的,不涉及客户端服务端,数据库就更没有了,就写个文件记录,太费劲,不值当,总共就两个类。
    小伙伴可以自己修改一些参数,本来想弄个配置文件,想想就这么点东西,还是不弄了。

这道题目有点难,在假定我有必需有的资源条件下(服务器at least),我需要三天时间完成。项目大致分为三部分,client端的实现,数据库索引的实现,如果用户人数为一人,则使用并行机制处理,如果用户人数为多人,则使用并发机制处理。

参考下这个:https://blog.csdn.net/yogima/article/details/80552982
稍微修改下应该就能满足你的要求了。你遇到问题再问。