结对子实验——小学生四则运算
实验开始时间:4月7日~4月9日
本次实验的组员分别是:郑泽成http://www.cnblogs.com/Oliver-zzc/,李天麟http://www.cnblogs.com/talent-demonic/;
1.代码是在Eclipse环境下开发的
2.在这次实验中我负责了写四则运算的算术代码和检查算法
同伴负责面板的设计和监听事件的实现
3.实现扩展方向有:用户在第一次答题时,需要用户输入用户名;程序可以设置答题时间,时间设置为整数,单位为秒;答题结束可以显示用户答错的题目个数和答对的题目个数;PS:部分扩展功能能力有限不能全部实现,以后会进行改进。
总结:在本次实验当中,我觉得我们的java学习还不是太过于精通,需要以后的学习过程中好好增强。还有也让我感受到了,两个人写代码其实并不是想象中的轻松。因为每个人的思路不一样,懂得东西也不同,需要在编码过程中相互合作,相互协调和交流才能一起编出一个程序来。当中也有许多困难和疑惑,通过和宿舍的同学一起讨论和上网查找方法,解决了问题
package main; import java.util.*; import java.io.*; import javax.swing.*; import java.awt.*; import javax.swing.event.*; import java.awt.event.*; class Expression//表达式类,存放表达式 { int a;//第一个数 int b;//第二个数 int c;//正确答案 int d;//输入答案 char operator;//运算符 boolean is_right; public Expression() { a=b=c=0; d = -1; is_right = false; operator = '+'; } } class NumberTooBigException extends Exception { String message; public NumberTooBigException(String ErrorMessage) { message = ErrorMessage; } public String getMessage() { return message; } } public class Test { Vector<Expression> v; public Test() { v = new Vector<Expression>(); } public void produceExpression(int bit,char operator) { Expression temp = new Expression(); temp.operator = operator; temp.a = (int)(Math.random() * Math.pow(10,bit)); temp.b = (int)(Math.random() * Math.pow(10,bit)); switch (operator) { case '+': temp.c = temp.a + temp.b;break; case '-': temp.c = temp.a - temp.b;break; case '*': temp.c = temp.a * temp.b;break; case '/': temp.b = (temp.b == 0 ? //排除除法被除数为0的情况 temp.b = 1 +(int)(Math.random() * Math.pow(10,bit)-1): temp.b); temp.c = temp.a / temp.b;break; default : mixExpression(temp,bit);//混合运算 } v.add(temp); } //混合运算,产生随机数 public void mixExpression(Expression temp,int bit) { int rand = (int)(Math.random()*4); switch(rand) { case 1: temp.c = temp.a + temp.b;temp.operator = '+';break; case 2: temp.c = temp.a - temp.b;temp.operator = '-';break; case 3: temp.c = temp.a * temp.b;temp.operator = '*';break; case 0: temp.b = (temp.b == 0 ? //排除除法被除数为0的情况 temp.b = 1 +(int)(Math.random() * Math.pow(10,bit)-1): temp.b); temp.c = temp.a / temp.b;temp.operator = '/';break; default : } } public void writeInfo(int num,String userName) { File myFile = new File(userName + ".his"); FileOutputStream fos; File saveUserNameAndScore = new File("UserNameAndScore.data"); try { fos = new FileOutputStream(myFile,true); PrintStream ps = new PrintStream(fos); double score = 0; ps.println(String.format("%5s%5s%5s%5s%5s%10s%5s","","","","","正确答案","你的答案","判断")); ps.println(); for(int i = 0 ;i < num ;i++) { ps.println(String.format("%5d%5s%5d%5s%10d%10d%10s",v.get(i).a,"+", v.get(i).b,"=",v.get(i).c,v.get(i).d,(v.get(i).is_right ? "正确":"错误"))); ps.println(); if(v.get(i).is_right) { score += 100.0/num; } } ps.println("你的总分:" + score); ps.close(); fos.close(); //下面保存用户名和得分到UserNameAndScore.data文件; fos = new FileOutputStream(saveUserNameAndScore,true); ps = new PrintStream(fos); ps.println(userName); ps.println(score); ps.close(); fos.close(); } catch (Exception ex) { System.out.println (ex.getMessage()); } } public static void main(String[] s) { OverAllFrame oaf = new OverAllFrame("小学生四则运算练习器:"); } } //主体框架 class OverAllFrame extends JFrame { TimeThread timer; //计时器线程 Test ar ;//内部算法 JPanel headPanel;//头面板 JLabel welcomeLabel;//欢迎信息 JLabel timeUse; //用时信息 StartPanel st; String userName; RunningPanel rp; EndPanel ep; Vector<Expression> v;//存放算式 public OverAllFrame(String s) { super(s); userName = JOptionPane.showInputDialog("请输入用户名",""); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.initialize(); setHeadPanel(); this.setLayout(new BorderLayout()); this.add(headPanel,BorderLayout.NORTH); this.add(st,BorderLayout.CENTER); this.setSize(500,400); this.setVisible(true); setLocationRelativeTo(null); } public void initialize()//初始化控件(主要面板) { ar = new Test(); headPanel= new JPanel(); welcomeLabel = new JLabel("欢迎! 学生:" + userName); st = new StartPanel(); rp = new RunningPanel(); ep = new EndPanel(); timeUse = new JLabel(); } public void setHeadPanel() { headPanel.setLayout(new FlowLayout()); headPanel.add(welcomeLabel); headPanel.add(timeUse); } //开始面板 class TimeThread extends Thread //计时器线程 { int min; int sec; int millis; long oldTime; long timeUsed; long timeSeted; JLabel display; boolean stop = false; public TimeThread(long timeSeted,JLabel display) { oldTime = System.currentTimeMillis(); this.display = display; this.timeSeted = timeSeted; // TODO Auto-generated constructor stub } @Override public void run() { // TODO Auto-generated method stub super.run(); do { timeUsed = System.currentTimeMillis() - oldTime; min = (int)(timeUsed/60000L); sec = (int)((timeUsed%60000L)/1000L); millis = (int)((timeUsed%60000L)%1000L); try { sleep(11); } catch (InterruptedException e) { // TODO: handle exception } display.setText("已用时:" + min+ ":" + sec +":" + millis ); display.setVisible(true); }while(timeUsed <= timeSeted && !stop); if(!stop)//如果不是手动停止的就运行complete rp.complete(); } public void setStop() { stop = true; } } class StartPanel extends JPanel { JPanel inputOptionPanel; //输入选项面板① JPanel selectOperatorOptionPanel;//选择运算符面板② JPanel bottomPanel; //底部面板③ JLabel inputBitLabel; //输入位数提示①-1 //输入位数区域①-2 JLabel inputNumLabel; //输入题目个数提示①-3 //输入题目个数区域①-4 JLabel inputTimeLabel; //输入做题时间提示①-5 JPanel inputTimePanel; //输入做题时间区域①-6 ButtonGroup operatorGroup; JRadioButton addButton ; //加法按钮②-1 JRadioButton minusButton ; //减法按钮②-2 JRadioButton multiplyButton ; //乘法按钮②-3 JRadioButton divideButton ; //除法按钮②-4 JRadioButton mixButton ; //混合运算按钮②-5 JLabel errorInfo; //错误信息③-1 JButton startButton; //开始按钮③-2 JTextField inputByminutes; //输入分钟区域①-6-1 JLabel printMinute; //打印提示“分”①-6-2 JTextField inputByseconds; //输入秒钟区域①-6-3 JLabel printSecond; //打印提示“秒”①-6-4 public StartPanel() { //this.setLayout(new GridLayout(0,1)); this.setLayout(new BoxLayout(this,BoxLayout.Y_AXIS)); this.initialize(); this.setInputOptionPanel(); this.setSelectOperatorOptionPanel(); this.setBottomPanel(); this.addStartEvent(); this.add(inputOptionPanel); this.add(selectOperatorOptionPanel); this.add(bottomPanel); } public void initialize() //初始化所有控件 { inputOptionPanel = new JPanel(); selectOperatorOptionPanel = new JPanel(); bottomPanel = new JPanel(); inputBitLabel = new JLabel("进行2位或两位以下运算:"); inputNumLabel = new JLabel("将会产生4道题目"); operatorGroup = new ButtonGroup(); addButton = new JRadioButton("加法"); minusButton = new JRadioButton("减法"); multiplyButton = new JRadioButton("乘法"); divideButton = new JRadioButton("除法"); mixButton = new JRadioButton("混合"); errorInfo = new JLabel(); startButton = new JButton("开始做题!"); inputTimeLabel = new JLabel("输入做题时间:"); inputTimePanel = new JPanel(); inputByminutes = new JTextField(); printMinute = new JLabel("分"); inputByseconds = new JTextField(); printSecond = new JLabel("秒"); } //设置做题时间面板 public void setInputTimePanel() { inputTimePanel.setLayout(new GridLayout(1,0)); printMinute.setHorizontalAlignment(SwingConstants.CENTER); printSecond.setHorizontalAlignment(SwingConstants.CENTER); inputTimePanel.add(inputByminutes); inputTimePanel.add(printMinute); inputTimePanel.add(inputByseconds); inputTimePanel.add(printSecond); } //设置输入选项面板 public void setInputOptionPanel() { inputOptionPanel.setLayout(new GridLayout(3,2)); inputBitLabel.setHorizontalAlignment(SwingConstants.CENTER); inputNumLabel.setHorizontalAlignment(SwingConstants.CENTER); inputTimeLabel.setHorizontalAlignment(SwingConstants.CENTER); inputOptionPanel.add(inputBitLabel); inputOptionPanel.add(inputNumLabel); inputOptionPanel.add(inputTimeLabel); setInputTimePanel(); inputOptionPanel.add(inputTimePanel); } //设置选择运算符面板 public void setSelectOperatorOptionPanel() { //selectOperatorOptionPanel.setLayout(new GridLayout(1,0)); selectOperatorOptionPanel.setLayout(new BoxLayout(selectOperatorOptionPanel,BoxLayout.X_AXIS)); operatorGroup.add(addButton); operatorGroup.add(minusButton); operatorGroup.add(multiplyButton); operatorGroup.add(divideButton); operatorGroup.add(mixButton); selectOperatorOptionPanel.add(addButton); selectOperatorOptionPanel.add(minusButton); selectOperatorOptionPanel.add(multiplyButton); selectOperatorOptionPanel.add(divideButton); selectOperatorOptionPanel.add(mixButton); } public void setBottomPanel() { bottomPanel.setLayout(new GridLayout(0,1)); bottomPanel.add(errorInfo); bottomPanel.add(startButton); } //添加开始按钮处理事件 public void addStartEvent() { startButton.addActionListener(new StartButtonListener()); } //内部类,实现开始事件 class StartButtonListener implements ActionListener { public void actionPerformed(ActionEvent e) { ar.v.clear();//清空向量 char operator = '+';//默认加法 if(minusButton.isSelected()) { operator = '-'; } else if(multiplyButton.isSelected()) { operator = '*'; } else if (divideButton.isSelected()) { operator = '/'; } else if (mixButton.isSelected())//混合运算 { operator = '.'; } try { int numOfEquation = Integer.parseInt("4"); int bigOfEquation = Integer.parseInt("2"); int minSeted = Integer.parseInt(inputByminutes.getText()); int secSeted = Integer.parseInt(inputByseconds.getText()); long millisSeted = (minSeted *60 + secSeted) * 1000; timer = new TimeThread(millisSeted,timeUse); timer.start(); while(ar.v.size() < numOfEquation) { ar.produceExpression(bigOfEquation,operator); } OverAllFrame.this.v = ar.v; rp.writeEquationToLabel(); OverAllFrame.this.st.setVisible(false);//开始面板调为不可见 OverAllFrame.this.add(rp,BorderLayout.CENTER); OverAllFrame.this.setVisible(true);//更新窗口 OverAllFrame.this.rp.setVisible(true);//显示做题面板 } catch(NumberFormatException ex) { errorInfo.setText("输入数据类型错误!你必须输入数值数据!,请重新输入:"); } catch(Exception ex) { } } } } //做题中的面板 class RunningPanel extends JPanel { JPanel contentPanel;//存放题目和答案① JPanel buttonsPanel;//存放按钮② Vector<JLabel> expressionGroup;//显示题目①-1 Vector<JTextField> answerGroup;//存放答案①-2 JButton completeButton; //完成②-3 public RunningPanel() { this.setLayout(new BorderLayout()); this.initialize(); this.addItem(); this.setContentPanel(); this.setButtonsPanel(); } public void initialize()//初始化 { contentPanel = new JPanel(); buttonsPanel = new JPanel(); expressionGroup = new Vector<JLabel>(); answerGroup = new Vector<JTextField>(); for(int i = 0; i < 4 ;i++) { expressionGroup.add(new JLabel()); answerGroup.add(new JTextField()); } completeButton = new JButton("完成!"); completeButton.addActionListener(new CompleteButtonListener()); } public void setContentPanel() { contentPanel.setLayout(new GridLayout(6,2)); for(int i = 0; i < 4; i++) { contentPanel.add(expressionGroup.get(i)); contentPanel.add(answerGroup.get(i)); } } public void setButtonsPanel() { buttonsPanel.add(completeButton); } public void writeEquationToLabel()//写入算式 { for(int i = 0; i < 4 ; i++) { String temp = String.format("%5d%5s%5d%5s",v.get(i).a, v.get(i).operator, v.get(i).b,"="); expressionGroup.get(i).setText(temp); } } public void addItem()//添加控件 { this.add(contentPanel,BorderLayout.CENTER); this.add(buttonsPanel,BorderLayout.SOUTH); } public void writeInputToVector() throws NumberFormatException//写入答案进向量 { for (int i = 0; i < 4 ;i++) { try { if(!answerGroup.get(i).getText().equals(""))//如果不是啥也没写的话 { v.get(i).d = Integer.parseInt(answerGroup.get(i).getText()); if(v.get(i).d == v.get(i).c) v.get(i).is_right = true; } //否则就是默认的-1 } catch(NumberFormatException e) { answerGroup.get(i).setText("输入数据类型错误!请重新输入:"); throw e;//必须这么写才能终止。。 } catch(Exception e) { answerGroup.get(i).setText("未知错误!请重新输入:"); throw e;//必须这么写才能终止。。 } } } public void clearAnswer()//清空答案 { for (int i = 0; i < 4;i++) { answerGroup.get(i).setText(""); } } //写入答案进输入区,还原上下页做过的答案用 public void writeAnswerTofield() { for(int i = 0; i < 4; i ++) { if(v.get(i).d != -1)//说明有输入过值 { answerGroup.get(i).setText(Integer.toString(v.get(i).d)); } } } public void complete()//完成做题,用户点击完成或者 是时间到了 { try { //因为第一句可能会产生异常,不过在句中已经处理,这里加上 //try是让它停止进入下一页 timer.setStop();//计时器线程停止 OverAllFrame.this.rp.writeInputToVector();//写入答案进向量 OverAllFrame.this.ar.writeInfo(v.size(), userName); OverAllFrame.this.rp.setVisible(false);//设置做题界面不可见 OverAllFrame.this.ep.setDisplayAnswer(); //设置要显示的结果 OverAllFrame.this.add(ep,BorderLayout.CENTER); OverAllFrame.this.setVisible(true); OverAllFrame.this.ep.setVisible(true);//显示答案面板 } catch(Exception e) { //do nothing } } class CompleteButtonListener implements ActionListener { public void actionPerformed(ActionEvent ae) { complete(); } } } //显示结果面板 class EndPanel extends JPanel { JScrollPane displayArea;//显示区域 JPanel bottomArea; //底部区域,存放按钮 JTextArea displayAnswer;//显示答案和评分 Font answerFont ; //字体属性 public EndPanel() { this.setLayout(new BorderLayout());//边界布局 this.initialize(); this.addItem(); } public void initialize()//初始化 { answerFont = new Font("宋体",Font.PLAIN,15); displayAnswer = new JTextArea(); displayAnswer.setFont(answerFont);//设置字体 displayArea = new JScrollPane(displayAnswer); bottomArea = new JPanel(); } public void setDisplayAnswer()//添加答案 { displayAnswer.setEditable(false);//只显示答案,不可编辑 String temp ; temp = (String.format("%5s%5s%5s%5s%5s%10s%5s","","", "","","\t正确答案","你的答案","\t判断")) + "\r\n"; displayAnswer.append(temp); for(int i = 0 ;i < 4;i++) { temp = (String.format("%5d%5s%5d%5s%10d%10d%10s",v.get(i).a,v.get(i).operator, v.get(i).b,"=",v.get(i).c,v.get(i).d,(v.get (i).is_right ? "正确":"错误")))+ "\r\n"; displayAnswer.append(temp); } displayAnswer.append(temp); } public void addItem() { this.add(displayArea,BorderLayout.CENTER); } } }