四则运算出题器

一、需求分析

1.参与运算的操作数除了100以内的整数以外,还要支持真分数的四则运算,例如:1/6 + 1/8 = 7/24。且操作数随机生成;

2.运算符的种类和顺序随机生成;

3.能处理用户的输入,并实现判断对错,打分统计正确率等功能。

4.可控制生成题目的个数,或通过用户交互过程确定题目个数。

二、设计思想

1.设置菜单选择项,将一个大程序分为若干个功能模块的小程序,逐个实现;
2.为了防止随机生成的题目发生重复,先将已生成的算式保存,然后将下一条生成的式子进行判断是否要生成,
如果不生成则返回循环语句的上一条,重新生成四则运算式子。
3.针对“可处理用户的输入”的需求,可以申请动态存储内存,通过用户输入来完成定制。
4.针对“可控制生成题目的个数”的需求,每个菜单功能对应一个控制参数,每个参数功能对应一个函数通过switch语句判断。
5.为了使用界面更清晰好看,程序中涉及了简单的Java GUI框架,可将程序功能以更简洁的形式呈现。

三、设计实现

1.初步实现有菜单选项、可处理用户的输入并控制生成题目的个数功能的四则运算程序。

1.1功能实现的部分代码如下:

package com.minirisoft;
import java.util.*;

public class SiZeYunSuan {
    public static void main(String[] args){
        Scanner input=new Scanner(System.in);
        System.out.println("请输入要输出多少道运算题");
        int h=input.nextInt();
        String [] arr1=new String[h];
        System.out.println("请输入你要计算数的最大值");
        int g=input.nextInt();
        System.out.println("**************菜单选择程序****************");
        System.out.println("请选择要使用的功能:");
        System.out.println("1.   整数加减法运算!");
        System.out.println("2.   整数四则运算!");
        System.out.println("3.   分数的加减运算");
        System.out.println("4.   分数的四则运算");
        System.out.println(" *********************************************");
        Random random = new Random();
        char arr[] = {'+','-','*','/'};
        int a=input.nextInt();
        switch(a){ 
        case 1:{
            System.out.println("请选择减法是否有负数;0:无负数,1:有负数");
            int f=input.nextInt();
            int i;
            switch(f) {
            case 0:{
                 for(i=0;i<h;i++) {
                     String str=random.nextInt(g)+" "+arr[random.nextInt(2)]+" "+random.nextInt(g)+"=";
                     System.out.println(str);}
                 break;}
             case 1:{
                 for(i=0;i<h;i++) {
                    System.out.println(-random.nextInt()%g+" "+arr[random.nextInt(2)]+" "+(-random.nextInt())%g+"=");}
                 break;}
             default:
                 System.out.println("输入的数有误,请输入0或1");}
             break;}
        case 2:{
            System.out.println("**************四则运算菜单选择程序****************");
            System.out.println("请选择要使用的功能:");
            System.out.println("1.   正整数无余数四则运算!");
            System.out.println("2.   可负整数无余数四则运算!");
            System.out.println("3.   正整数可有余数四则运算");
            System.out.println("4.   可负整数可有余数四则运算");
            System.out.println(" *********************************************");
            int f=input.nextInt();
             switch(f) {
             case 1:{
                 for(int i=0;i<h;i++) {
                     int u=random.nextInt(g);
                     int v=random.nextInt(g)+1;
                     char w=arr[random.nextInt(4)];
                     if(u%v==0 && w=='/'){
                         System.out.println(u+" "+w+" "+v+"=");}
                    else
                        System.out.println(u+" "+arr[random.nextInt(3)]+" "+v+"=");}
                 break;}
             case 2:{
                 for(int i=0;i<h;i++) {
                     int u=-random.nextInt()%g;
                     int v=-random.nextInt()%g;
                     char w=arr[random.nextInt(4)];
                     if(v!=0 && u%v==0 && w=='/' )
                         System.out.println(u+" "+w+" "+v+"=");
                    else
                        System.out.println(u+" "+arr[random.nextInt(3)]+" "+v+"=");}
                 break;}
             case 3:{
                 for(int i=0;i<h;i++) {
                     int u=random.nextInt(g);
                     int v=random.nextInt(g)+1;
                     char w=arr[random.nextInt(4)];
                     System.out.println(u+" "+w+" "+v+"=");}
                 break;}
             case 4:{
                 for(int i=0;i<h;i++){
                 int u=-random.nextInt()%g;
                 int v=-random.nextInt()%g;
                 char w=arr[random.nextInt(4)];
                 System.out.println(u+" "+w+" "+v+"=");}
                 break;}
             default:
                 System.out.print("输入的数有误,请输入1--4的整数"); }}
        case 3:{
            System.out.println("请选择减法是否有负数;0:无负数,1:有负数");
             int f=input.nextInt();
             switch(f){
             case 0:{
                 for(int i=0;i<h;i++){
                    System.out.println(random.nextInt(g)+"/"+random.nextInt(g)+1+" "+arr[random.nextInt(2)]+" "+random.nextInt(g)+"/"+random.nextInt(g)+1+"="); }
                 break;}
             case 1:{
                 for(int i=0;i<h;i++){
                    System.out.println(-random.nextInt()%g+"/"+random.nextInt(g)+1+" "+arr[random.nextInt(2)]+" "+-random.nextInt()%g+"/"+random.nextInt(g)+1+"=");}
                 break;}
             default:
                 System.out.println("输入的数有误,请输入0或1");}
            break;}

1.2初步功能实现:

 2.功能完善,界面设计

2.1 输入用户名后可以点击开始做题按钮,为了界面简洁大方,出题时每次出十题,提交后会显示答案。可以选择重做或再次开始做不同的题;
2.2 输入用户名后可以点击查看记录按钮,查看自己历次做题记录(txt文档);
2.3 可以选择每次出题的运算类型和位数。运算类型可选+、-、*、/或混合,位数可选1、2、3、4位。默认运算类型为+,运算位数为0。其中,除数不能为0,减法结果不为负。
2.4 倒计时功能,为小学生合理设计答题时间,加快答题速度,设置在120s内做完,如果时间到了还没提交则会自动提交。

2.5 实现功能的具体代码:

(1)Begin.java(欢迎界面)

 1 package fourArithmetic;
 2 
 3     import java.awt.*;
 4     import java.awt.event.*;
 5     import javax.swing.*;
 6     import java.awt.image.BufferedImage;
 7     import javax.imageio.ImageIO;
 8     import java.io.IOException;
 9     import java.io.File;
10 
11     public class Begin{
12         JFrame w = new JFrame("四则运算练习软件");
13         JPanel p1 = new JPanel();
14         JPanel p2 = new JPanel();
15         JLabel l = new JLabel("欢迎开始进行四则运算练习!");
16         JButton b = new JButton("确定");
17         Begin(){
18             w.addWindowListener(new Wind());
19             b.addMouseListener(new Monitor2());
20             Font font = new Font("欢迎开始进行四则运算练习!",Font.PLAIN,40);
21             l.setFont(font);
22             w.add(p1,BorderLayout.CENTER);
23             w.add(p2,BorderLayout.SOUTH);
24             p1.add(l);
25             l.setBounds(p1.WIDTH/2,p1.HEIGHT/2,200,20);
26             p2.add(b);
27             b.setBounds(p2.WIDTH/2-10,p2.HEIGHT/2-6,20,12);
28             w.setBounds(100,200,1000,649);
29             w.setVisible(true);
30             BufferedImage img = null;
31             try {
32                 img = ImageIO.read(new File("5.jpg"));
33             }catch(IOException e) {
34                 e.printStackTrace();
35             }
36             JLabel label = new JLabel(new ImageIcon(img));
37             // 把标签的大小位置设置为图片刚好填充整个面板
38             label.setBounds(0,0,img.getWidth(),img.getHeight());
39             // 把内容窗格转化为JPanel,否则不能用方法setOpaque()来使内容窗格透明
40             JPanel imagePanel = (JPanel) w.getContentPane();
41             imagePanel.setOpaque(false);
42             //把背景图片添加到分层窗格的最底层作为背景
43             w.getLayeredPane().add(label, new Integer(Integer.MIN_VALUE));
44             p1.add(label);
45         }
46         private class Monitor2 extends MouseAdapter{
47             public void mousePressed(MouseEvent e) {
48                 new Gui();
49                 w.setVisible(false);
50             }
51         }
52         public static void main(String args[]) {
53             new Begin();
54         }
55         private class Wind extends WindowAdapter{
56             public void windowClosing(WindowEvent e) {
57                 w.setVisible(false);
58                 System.exit(0);
59             }
60         }
61     }
View Code

(2)Gui.java(答题界面布局、按钮事件的监听、倒计时线程)

  1 package fourArithmetic;
  2 
  3 import java.awt.*;
  4 import java.awt.event.*;
  5 import java.awt.image.BufferedImage;
  6 
  7 import javax.imageio.ImageIO;
  8 import javax.swing.*;
  9 import fourArithmetic.Operation;
 10 import java.io.File;
 11 import java.io.FileNotFoundException;
 12 import java.io.FileWriter;
 13 import java.io.IOException;
 14 import java.io.PrintWriter;
 15 
 16 public class Gui {
 17 
 18     private JFrame mainWindow = new JFrame("四则运算练习软件");
 19 
 20     //面板
 21     private JPanel selectPanel = new JPanel();
 22     private JPanel mainPanel = new JPanel();
 23     private JPanel commandP = new JPanel();
 24 
 25     private JButton JBRedo = new JButton("重做");
 26     private JButton JBStart = new JButton("开始做题");
 27 
 28     private JLabel JLUsersName = new JLabel("请输入你的用户名:");
 29     private JLabel JLChooseOp = new JLabel("请选择运算类型:");
 30     private JLabel JLNumberDigit = new JLabel("请选择运算位数:");
 31     private JLabel JLBAnsTip = new JLabel("输入答案");
 32     private JLabel JLBRemainTip = new JLabel("余数");
 33 
 34     private JTextField JTFUserName = new JTextField(8);//10的单位不是px 而是指定列数
 35     private String[] operationType = {"+","-","*","/","混合"};
 36     private String[] numberOfDigitType = {"1","2","3","4"};
 37     private JComboBox<String> JCBOperationSelect = new JComboBox<String>(operationType);//JComboBox 泛型 需要加上<E>
 38     private JComboBox<String> JCBNumberOfDigit = new JComboBox<String>(numberOfDigitType);
 39 
 40     //显示题目的JLabel
 41     private JLabel[] JLBQuestions= new JLabel[10];
 42     //显示正确答案的JLabel
 43     private JLabel[] JLBAnswers = new JLabel[10];
 44     //显示用户答案是否正确的JLabel
 45     private JLabel[] JLBIsTrue = new JLabel[10];
 46 
 47     private JTextField[] JTFUsersAnswer = new JTextField[10];//定义变量时需要赋初值,不然会出现空指针异常问题
 48     private JTextField[] JTFRemainder = new JTextField[10];
 49 
 50     //设置Font
 51     private Font buttonFont = new Font("微软雅黑",Font.PLAIN,16);
 52     private Font JLBFont = new Font("微软雅黑",Font.BOLD,18);
 53     private Font JTFFont = new Font("微软雅黑",Font.PLAIN,18);
 54     private Font JLBAnsFont = new Font("微软雅黑",Font.PLAIN,16);
 55 
 56     //类型为Operation的questions数组,只有这个才和Operation类等等那些类关联起来
 57     private Operation[] questions = new Operation[10];
 58     //用户答案数组
 59     private int[] userAnswer = new int[10];
 60     //用户余数数组
 61     private int[] remainder = new int[10];
 62 
 63     private int scores ,n = 1;
 64     private JLabel JLBScores = new JLabel("你的成绩为:");
 65     private JButton JBOpenFile = new JButton("查看记录");
 66     private String chara = "+";
 67     private File pFile = new File("四则运算记录");
 68 
 69     private int usedTime;
 70     boolean runFlag = false;//runFlag默认为false
 71     private JPanel PTime = new JPanel();
 72     private JLabel JLBRemainTime = new JLabel("剩余时间:");
 73     private JTextField JTFWtime = new JTextField("120");
 74     private JLabel JLBTime = new JLabel("用时:");
 75     //LimitTime t = new LimitTime();//线程不可以在这里new
 76 
 77     //倒计时线程
 78     class LimitTime extends Thread{
 79         public void run()
 80         {
 81             runFlag = true;
 82             int i = 120;
 83             usedTime = 0;
 84             while(runFlag && i >= 0)
 85             {
 86                 JTFWtime.setText(""+i);
 87                 try {
 88                     sleep(1000);
 89                     usedTime++;
 90                 } catch (InterruptedException e) {
 91                     JFrame jf = new JFrame();
 92                     JOptionPane.showMessageDialog(jf,"出现了未知问题,请重启程序");
 93                 }
 94                 i--;
 95             }
 96             //runFlag = false;
 97             for(int j = 0;j < 10;j++)
 98             {
 99                 if(JTFUsersAnswer[j].getText().equals(""))
100                 {
101                     JTFUsersAnswer[j].setText("0");
102                 }
103             }
104             printAnswer();//倒计时结束,则调用printAnswer()方法
105             JBStart.setText("开始做题");
106             JLBTime.setText("用时:"+usedTime);
107         }
108     }
109 
110     public Gui()
111     {
112         //布局用户名&选择面板
113         selectPanel.setPreferredSize(new Dimension(700,50));
114         //selectPanel.setLayout(new GridLayout(1,6,25,20));
115         JLUsersName.setFont(JLBFont);
116         selectPanel.add(JLUsersName);
117         JTFUserName.setFont(JLBFont);
118         selectPanel.add(JTFUserName);
119         JLChooseOp.setFont(JLBFont);
120         selectPanel.add(JLChooseOp);
121         JCBOperationSelect.setPreferredSize(new Dimension(50,25));       //当selectPanel.setLayout那句存在时,这里的设置无效
122         selectPanel.add(JCBOperationSelect);
123         JLNumberDigit.setFont(JLBFont);
124         selectPanel.add(JLNumberDigit);
125         JCBNumberOfDigit.setPreferredSize(new Dimension(50,25));
126         selectPanel.add(JCBNumberOfDigit);
127 
128         //布局主面板
129         mainPanel.setPreferredSize(new Dimension(700,400));
130         //mainPanel.setLayout(new GridLayout(10,3,5,10));
131         GridBagLayout gridbag = new GridBagLayout();
132         GridBagConstraints GBC = new GridBagConstraints();
133         GBC.weightx = 1;//加上这两行之后文本框的大小会和不加时不同 因为它描述的是随面板变化的情况 而现在面板的设定值是800*500 因此不同(不以设定大小为默认值)
134         GBC.weighty = 1;
135         //GBC.fill = GridBagConstraints.BOTH;//weightx描述的是网格的大小随面板大小变化,组件的大小并不会随之变化 要使组件随之变化需要控制它对所在位置的填充方式
136         //GBC.insets = new Insets(1,1,2,2);
137         GBC.gridx = 1;
138         GBC.gridy = 0;
139         GBC.anchor = GridBagConstraints.WEST;
140         gridbag.setConstraints(JLBAnsTip, GBC);
141         JLBAnsTip.setFont(JLBFont);
142         mainPanel.add(JLBAnsTip);
143 
144         GBC.gridx = 2;
145         gridbag.setConstraints(JLBRemainTip, GBC);
146         JLBRemainTip.setFont(JLBFont);
147         mainPanel.add(JLBRemainTip);
148 
149         GBC.gridx = 4;
150         GBC.gridwidth = 2;
151         GBC.anchor = GridBagConstraints.CENTER;
152         gridbag.setConstraints(JLBScores, GBC);
153         JLBScores.setFont(JLBFont);
154         mainPanel.add(JLBScores);
155 
156         for(int i = 0;i < 5;i++)
157         {
158             JLBQuestions[i] = new JLabel("点击开始做题显示题目");
159             JLBQuestions[i].setFont(JLBFont);
160             JTFUsersAnswer[i] = new JTextField(5);                      //一定要加这行 不然会出现空指针错误
161             JTFUsersAnswer[i].setFont(JTFFont);
162             JTFRemainder[i] = new JTextField(3);
163             JTFRemainder[i].setFont(JTFFont);
164             JLBAnswers[i] = new JLabel("");
165             JLBAnswers[i].setFont(JLBAnsFont);
166             JLBIsTrue[i] = new JLabel("");
167             JLBIsTrue[i].setFont(JLBAnsFont);
168 
169             //gridbag.setConstraints(JLBQuestions[i],new GridBagConstraints(i,0,5,10,1,1,GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets(2,2,2,2),0,0));
170             //gridbag.setConstraints(JTFUsersAnswer[i],new GridBagConstraints(i,1,5,10,1,1,GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets(2,2,2,2),0,0));
171             //gridbag.setConstraints(JTFRemainder[i],new GridBagConstraints(i,2,5,10,1,1,GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets(2,2,2,2),0,0));
172             GBC.gridwidth = 1;
173             GBC.gridx = 0;
174             GBC.gridy = 2*i+1;
175             GBC.anchor = GridBagConstraints.EAST;
176             gridbag.setConstraints(JLBQuestions[i], GBC);
177             mainPanel.add(JLBQuestions[i]);
178             GBC.anchor = GridBagConstraints.CENTER;
179             GBC.gridy = 2*i+2;
180             GBC.gridwidth = 2;
181             gridbag.setConstraints(JLBAnswers[i], GBC);
182             mainPanel.add(JLBAnswers[i]);
183 
184             GBC.gridwidth = 1;
185             GBC.gridx = 1;
186             GBC.gridy = 2*i+1;
187             GBC.anchor = GridBagConstraints.WEST;
188             gridbag.setConstraints(JTFUsersAnswer[i],GBC);
189             mainPanel.add(JTFUsersAnswer[i]);
190 
191             GBC.gridx = 2;
192             gridbag.setConstraints(JTFRemainder[i],GBC);
193             mainPanel.add(JTFRemainder[i]);
194             GBC.gridy = 2*i+2;
195             gridbag.setConstraints(JLBIsTrue[i], GBC);
196             mainPanel.add(JLBIsTrue[i]);
197         }
198 
199         for(int i = 5;i < 10;i++)
200         {
201             JLBQuestions[i] = new JLabel("点击开始做题显示题目");
202             JLBQuestions[i].setFont(JLBFont);
203             JTFUsersAnswer[i] = new JTextField(5);                      //一定要加这行 不然会出现空指针错误
204             JTFUsersAnswer[i].setFont(JTFFont);
205             JTFRemainder[i] = new JTextField(3);
206             JTFRemainder[i].setFont(JTFFont);
207             JLBAnswers[i] = new JLabel("");
208             JLBAnswers[i].setFont(JLBAnsFont);
209             JLBIsTrue[i] = new JLabel("");
210             JLBIsTrue[i].setFont(JLBAnsFont);
211 
212             GBC.gridx = 4;
213             GBC.gridy = 2*i-9;
214             GBC.anchor = GridBagConstraints.EAST;
215             gridbag.setConstraints(JLBQuestions[i], GBC);
216             mainPanel.add(JLBQuestions[i]);
217             GBC.anchor = GridBagConstraints.CENTER;
218             GBC.gridy = 2*i-8;
219             GBC.gridwidth = 2;
220             gridbag.setConstraints(JLBAnswers[i], GBC);
221             mainPanel.add(JLBAnswers[i]);
222 
223             GBC.gridwidth = 1;
224             GBC.gridx = 5;
225             GBC.gridy = 2*i-9;
226             GBC.anchor = GridBagConstraints.WEST;
227             gridbag.setConstraints(JTFUsersAnswer[i],GBC);
228             mainPanel.add(JTFUsersAnswer[i]);
229 
230             GBC.gridx = 6;
231             gridbag.setConstraints(JTFRemainder[i],GBC);
232             mainPanel.add(JTFRemainder[i]);
233             GBC.gridy = 2*i-8;
234             gridbag.setConstraints(JLBIsTrue[i], GBC);
235             mainPanel.add(JLBIsTrue[i]);
236 
237         }
238         mainPanel.setLayout(gridbag);
239 
240         //布局命令面板
241         commandP.setLayout(new FlowLayout(FlowLayout.CENTER,60,20)); 
242         JLBRemainTime.setFont(JLBFont);
243         JLBTime.setFont(JLBFont);
244         JTFWtime.setFont(JTFFont);
245         PTime.setLayout(new FlowLayout(FlowLayout.LEFT,10,20));
246         PTime.add(JLBRemainTime);
247         PTime.add(JTFWtime);
248         PTime.add(JLBTime);
249         commandP.add(PTime);
250         JBStart.setFont(buttonFont);
251         commandP.add(JBStart);
252         JBRedo.setFont(buttonFont);
253         commandP.add(JBRedo);
254         JBOpenFile.setFont(buttonFont);
255         commandP.add(JBOpenFile);
256 
257         //使用匿名嵌套类的方式注册开始按钮的事件处理监听器对象
258         JBStart.addActionListener(
259                 new ActionListener() {
260                     @Override
261                     public void actionPerformed(ActionEvent e) {
262                         if(JBStart.getText().equals("开始做题"))
263                         {
264                             if(JTFUserName.getText().trim().equals(""))
265                             {
266                                 JFrame nullNameWarning = new JFrame();
267                                 JOptionPane.showMessageDialog(nullNameWarning,"请输入用户名");//确保用户输入用户名
268                             }
269                             else{
270                                 start(); //如果按钮上面的文字是"开始做题",则调用start()方法出题
271                                 JBStart.setText("提交答案"); 
272                                 //倒计时线程开始
273                                 LimitTime t = new LimitTime();
274                                 t.start();
275                             } 
276                         }
277                         else
278                         {
279                             for(int i = 0;i < 10;i++)
280                             {
281                                 if(JTFUsersAnswer[i].getText().equals(""))
282                                 {
283                                     JTFUsersAnswer[i].setText("0");
284                                 }
285                             }
286                             runFlag = false;//将runFlag设置为false(线程就会不再执行while循环里的内容)
287                             //printAnswer();//这里不用再调用printWriter方法了,因为线程那边结束的时候会对它进行调用。
288                             JLBTime.setText("用时:"+usedTime);
289                             JBStart.setText("开始做题");
290 
291                             /*int flag = 1;//是否完成每道题
292                             for(int i = 0;i < 10;i++)
293                             {
294                                 if(JTFUsersAnswer[i].getText().equals(""))
295                                 {
296                                     JFrame nullAns = new JFrame();
297                                     JOptionPane.showMessageDialog(nullAns,"请确保已完成每道题");
298                                     flag = 0;//有题目没完成
299                                     break;
300                                 }
301                             }
302                             if(flag == 1)
303                             {
304                                 printAnswer();//如果按钮上面的文字是"提交答案",则调用printAnswer()方法
305                                 JBStart.setText("开始做题");
306                             }*/
307                             //使用计时器的话不需要完成每道题
308 
309                         }
310                     }
311                 }
312         );
313 
314         //监听重做按钮
315         JBRedo.addActionListener(new ActionListener(){
316             public void actionPerformed(ActionEvent e){
317                 if(JBStart.getText().equals("开始做题"))//若已提交答案 则可以进行重做
318                 {
319                     for(int i = 0;i < 10;i++)
320                     {
321                         JTFUsersAnswer[i].setText("");
322                         JTFRemainder[i].setText("");
323                         JLBAnswers[i].setText("");
324                         JLBIsTrue[i].setText("");
325                         JLBScores.setText("");
326                     }
327                     JLBTime.setText("用时:");
328                     LimitTime t = new LimitTime();
329                     t.start();
330                     JBStart.setText("提交答案"); 
331                 }
332                 else//答案未提交 不能重做
333                 {
334                     JFrame notSubmit = new JFrame();
335                     JOptionPane.showMessageDialog(notSubmit,"提交后才可以重做!提交前可以直接更改答案!");
336                 }
337             }
338         });
339 
340         //查看以往做题记录的按钮监听器
341         JBOpenFile.addActionListener(new ActionListener(){
342             public void actionPerformed(ActionEvent e){
343 
344                 if(JTFUserName.getText().trim().equals(""))
345                 {
346                     JFrame nullNameWarning = new JFrame();
347                     JOptionPane.showMessageDialog(nullNameWarning,"请输入用户名");//确保用户输入用户名
348                 }
349                 else{
350                     //一般不能实例化一个Runtime对象,应用程序也不能创建自己的Runtime 类实例,但可以通过getRuntime 方法获取当前Runtime运行时对象的引用。一旦得到了一个当前的Runtime对象的引用,就可以调用Runtime对象的方法去控制Java虚拟机的状态和行为。
351                      Runtime ce=Runtime.getRuntime();
352                      pFile.mkdirs();
353                      String filename = JTFUserName.getText()+".his";
354                      File aUserRec = new File(pFile,filename);
355                      if(aUserRec.exists())
356                      {
357                          try{
358                             //ce.exec("cmd   /c   start  "+aUserRec.getAbsolutePath());//这样是不能打开的 因为没有东西能打开.his文件 会跳出来搜索应用商店
359                          ce.exec("notepad.exe "+aUserRec.getAbsolutePath());
360                          }catch(IOException exc){
361                              exc.printStackTrace();
362                          }
363                      }else{
364                      JFrame nullFileWarning = new JFrame();
365                      JOptionPane.showMessageDialog(nullFileWarning,"该用户暂无记录!");
366                      }
367                 }   
368             }
369         });
370 
371         //尽量把主窗体的设置都放到最后
372         mainWindow.add(selectPanel,BorderLayout.NORTH);
373         mainWindow.add(mainPanel,BorderLayout.CENTER);
374         mainWindow.add(commandP, BorderLayout.SOUTH);
375         mainWindow.pack();
376         mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
377         mainWindow.setSize(800,500);//设置窗体大小
378         mainWindow.setLocationRelativeTo(null);//将窗口置于屏幕中间
379         mainWindow.setVisible(true);//设置为可见 要放在最后 放在前面则只能看见用户名和选择面板 主面板等需要拖动窗口大小才能看见
380     }
381 
382     public void start(){
383         //清除TextField和答案标签的内容
384         for(int i = 0;i < 10;i++)
385         {
386             JTFUsersAnswer[i].setText("");
387             JTFRemainder[i].setText("");
388             JLBAnswers[i].setText("");
389             JLBIsTrue[i].setText("");
390             JLBScores.setText("");
391             JLBTime.setText("用时:");
392         }
393 
394         //获取ComboBox的选中值
395         chara = (String) JCBOperationSelect.getSelectedItem();
396         n = Integer.valueOf((String)JCBNumberOfDigit.getSelectedItem());
397 
398          //根据选择的运算出题
399         int flag = 0;
400         if(chara.equals("混合"))
401             flag = 1;
402         for(int i = 0;i < 10;i++)
403         {
404             if(flag == 1)
405             {
406                 int tempCh = (int)(Math.random()*4+1);
407                 switch(tempCh)
408                 {
409                 case 1:
410                     chara = "+";
411                     break;
412                 case 2:
413                     chara = "-";
414                     break;
415                 case 3:
416                     chara = "*";
417                     break;
418                 case 4:
419                     chara = "/";
420                     break;
421                 }
422             }
423 
424             switch(chara)
425             {
426              case "+":
427                  questions[i] = new Addition(n);
428                  JLBQuestions[i].setText(questions[i].printQuestion());
429                  break;
430              case "-":
431                  questions[i] = new Subtraction(n);
432                  JLBQuestions[i].setText(questions[i].printQuestion());
433                  break;
434              case "*":
435                  questions[i] = new Multiplication(n);
436                  JLBQuestions[i].setText(questions[i].printQuestion());
437                  break;
438              case "/":
439                  questions[i] = new Division(n);
440                  JLBQuestions[i].setText(questions[i].printQuestion());
441                  break;
442              default:
443                     JFrame jf = new JFrame();
444                     JOptionPane.showMessageDialog(jf,"出现未知错误,请重启程序。");
445             }
446         }
447     }
448 
449     //在面板上显示每题的正确答案、得分和用时,并且将每次做题的记录写入文件
450     public void printAnswer()
451     {
452         //成绩初始值为100
453         scores = 100;
454 
455         //对于每道题
456         for(int i = 0; i < 10;i++)
457         {
458             //给用户的答案这一数组赋值(getText的结果为String)
459             userAnswer[i] = Integer.valueOf(JTFUsersAnswer[i].getText());
460 
461             //如果没有填余数,则默认用户认为余数为0,并给余数数组赋值
462             if(JTFRemainder[i].getText().equals(""))
463             {
464                 remainder[i] = 0;
465             }
466 
467             //否则用用户填的余数给余数数组赋值
468             else
469             {
470                 remainder[i] = Integer.valueOf(JTFRemainder[i].getText());
471             }
472 
473 
474             //questions的类型是operation,用答案和余数这两个数组给questions这个数组赋值
475             questions[i].setUsersAnswer(userAnswer[i],remainder[i]);
476 
477             //以下这种分开是否有余数的做法是错误的,因为在运算为混合时chara的值是看第十题的(第十题的chara会覆盖掉前面的)。 万一除法没有余数就会报错
478             /*if(chara.equals("/"))
479             {
480 
481                 remainder[i] = Integer.valueOf(JTFRemainder[i].getText());
482                 questions[i].setUsersAnswer(userAnswer[i],remainder[i]);
483             }
484             else
485             {
486                 questions[i].setUsersAnswer(userAnswer[i]);
487             }*/
488 
489             //使正确答案显示在面板上
490             JLBAnswers[i].setText(questions[i].ptintQA());
491 
492             //在面板上显示答案是否正确
493             JLBIsTrue[i].setText(questions[i].isCorrect());
494 
495             //如果错误则将答案和是否正确两个标签的字体颜色设置为红色
496             if(JLBIsTrue[i].getText().equals("回答错误"))
497             {
498                 JLBAnswers[i].setForeground(Color.RED);
499                 JLBIsTrue[i].setForeground(Color.RED);
500                 scores-=10;
501             }
502             //正确为黑色
503             else
504             {
505                 JLBAnswers[i].setForeground(Color.BLACK);
506                 JLBIsTrue[i].setForeground(Color.BLACK);
507             }
508         }
509         //显示成绩
510         JLBScores.setText("你的成绩为:"+ scores);
511 
512         //创建用户文件
513         pFile.mkdirs();
514         String filename = JTFUserName.getText()+".his";
515         File aUserRec = new File(pFile,filename);
516         if(! (aUserRec.exists()))
517         {
518             try{
519                 aUserRec.createNewFile();
520             }catch(Exception e){
521                 e.printStackTrace();
522                 JFrame jf = new JFrame();
523                 JOptionPane.showMessageDialog(jf,"用户文件创建失败");
524             }   
525         }
526 
527         //将每道题的正确答案和用户答案写入文件
528         for(int i = 0;i < 10;i++)
529         {
530             questions[i].writeToFile(aUserRec);
531         }
532 
533         //将得分和用时写入文件
534         try
535         {
536             PrintWriter out = new PrintWriter(new FileWriter(aUserRec,true));
537             out.println("");
538             out.println("你此次的得分是:"+scores+"    "+"所用时间为:"+usedTime+"秒");
539             out.println("");
540             out.println("");
541             out.close();
542         }catch(FileNotFoundException e){
543             System.err.println("File not found!" );
544         }catch(IOException e2){
545             e2.printStackTrace();
546         }       
547     }   
548 }
View Code

(3)Operation.java(对操作数的运算、判断正误)

 1 package fourArithmetic;
 2 
 3 import java.io.File;
 4 import java.io.FileNotFoundException;
 5 import java.io.FileWriter;
 6 import java.io.IOException;
 7 import java.io.PrintWriter;
 8 
 9 public abstract class Operation {
10     protected int op1,op2,remainder,usersRemainder,n,correctAnswer,usersAnswer,maxInt=1;
11     protected String ch;
12     protected long minRange,maxRange;
13 
14     public Operation(String ch,int n) {
15         super();
16         this.ch = ch;
17         this.n = n;
18     }
19 
20     public abstract void operation();
21     public abstract void isNumRight();
22     public abstract void setRange();
23 
24     protected void getRanNum()
25     {
26         op1 = (int)(Math.random()*Math.pow(10,n));
27         op2 = (int)(Math.random()*Math.pow(10,n));
28     }
29 
30     public void setUsersAnswer(int usersAnswer,int usersRemainder) //throws Exception
31     {
32         /*setRange();
33         if(usersAnswer < minRange || usersAnswer > maxRange)
34             throw new NumberTooBigException("答案范围应为"+minRange+"到"+maxRange);*/
35         this.usersAnswer = usersAnswer;
36         this.usersRemainder = usersRemainder;
37     }
38 
39     public void setUsersAnswer(int usersAnswer) //throws Exception
40     {
41         setUsersAnswer(usersAnswer,0);
42     }
43 
44     public String isCorrect()
45     {
46         if(usersAnswer == correctAnswer)
47             return "回答正确";
48         else
49             return "回答错误";
50     }
51 
52     public String printQuestion()
53     {
54         getRanNum();
55         isNumRight();
56         return op1+" "+ch+" "+op2+" =";
57     }
58 
59     public String ptintQA()
60     {
61         operation();
62         return "答案:"+op1+" "+ch+" "+op2+" = "+correctAnswer;
63     }
64 
65     public void writeToFile(File aFile)
66     {
67         try
68         {
69             PrintWriter out = new PrintWriter(new FileWriter(aFile,true));
70             out.println("题目:"+op1+" "+ch+" "+op2);
71             out.println("你的答案:"+usersAnswer + "    "+ "正确答案:"+correctAnswer);
72             out.close();
73         }catch(FileNotFoundException e){
74             System.err.println("File not found!" );
75         }catch(IOException e2){
76             e2.printStackTrace();
77         }       
78     }
79 }
View Code

(4)Addition.java(加法)

 1 package fourArithmetic;
 2 
 3 import fourArithmetic.Operation;
 4 
 5 public class Addition extends Operation {
 6 
 7     static String ch = "+";
 8 
 9     public Addition(int n) {
10         super(ch,n);
11     }
12 
13     @Override
14     public void operation() {
15         correctAnswer = op1 + op2;
16     }
17 
18     public void isNumRight(){}
19 
20     public void setRange(){
21         minRange = 0;
22         maxRange = maxInt + maxInt;
23     }
24 }
View Code

(5)Subtraction.java(减法)

 1 package fourArithmetic;
 2 
 3 public class Subtraction extends Operation{
 4 
 5     static String ch = "-";
 6 
 7     public Subtraction(int n) {
 8         super(ch,n);
 9     }
10 
11     public void operation() {
12         correctAnswer = op1 - op2;
13     }
14 
15     public void isNumRight(){
16         while(op1 == op2)
17             getRanNum();
18         if(op1 < op2)
19         {
20             int temp = op1;
21             op1 = op2;
22             op2 = temp;
23         }
24     }
25 
26     public void setRange(){
27         minRange = -maxInt;
28         maxRange = maxInt;
29     }
30 }
View Code

(6)Multiplication.java(乘法)

 1 package fourArithmetic;
 2 
 3 
 4 public class Multiplication extends Operation {
 5 
 6     static String ch = "X";
 7 
 8     public Multiplication(int n) {
 9         super(ch,n);
10     }
11 
12     @Override
13     public void operation() {
14         correctAnswer = op1 * op2;
15     }
16 
17     @Override
18     public void isNumRight() {}
19 
20     public void setRange(){
21         minRange = 0;
22         maxRange = maxInt * maxInt;
23     }
24 
25 }
View Code

(7)Division.java(除法)

 1 package fourArithmetic;
 2 
 3 import java.io.File;
 4 import java.io.FileNotFoundException;
 5 import java.io.FileWriter;
 6 import java.io.IOException;
 7 import java.io.PrintWriter;
 8 
 9 import fourArithmetic.Operation;
10 
11 public class Division extends Operation {
12 
13     static String ch = "/";
14 
15     public Division(int n) {
16         super(ch,n);
17     }
18 
19     @Override
20     public void operation() {
21         // TODO Auto-generated method stub
22         correctAnswer = op1 / op2;
23         remainder = op1 % op2;
24     }
25 
26     public String isCorrect()
27     {
28         if(usersAnswer == correctAnswer && remainder == usersRemainder)
29             return "回答正确";
30         else
31             return "回答错误";
32     }
33 
34     public String ptintQA()
35     {
36         operation();
37         return "答案:"+op1+" "+ch+" "+op2+" = "+correctAnswer+" "+remainder;
38     }
39 
40     @Override
41     public void isNumRight() {
42         while(op2 == 0)
43             getRanNum();
44     }
45 
46     public void setRange(){
47         minRange = 0;
48         maxRange = maxInt;
49     }
50 
51     public void writeToFile(File aFile)
52     {
53         try
54         {
55             PrintWriter out = new PrintWriter(new FileWriter(aFile,true));
56             out.println("题目:"+op1+" "+ch+" "+op2);
57             out.println("你的答案:"+usersAnswer+" "+usersRemainder + "    "+ "正确答案:"+correctAnswer+" "+remainder);
58             out.close();
59         }catch(FileNotFoundException e){
60             System.err.println("File not found!" );
61         }catch(IOException e2){
62             e2.printStackTrace();
63         }       
64     }
65 }
View Code

(8)ArithmeticTest.java(主函数调用Gui)

 1 package fourArithmetic;
 2 
 3 import fourArithmetic.Gui;
 4 
 5 public class ArithmeticTest{
 6     public static void main(String[] args) {
 7         // TODO Auto-generated method stub
 8         Gui exercise = new Gui();
 9     }
10 }
View Code

2.6 代码运行结果:

(1)开始界面

 (2)答题界面

 (3)答题测试

(4)查看记录

四、反思总结体会

1)由于题目需求较多,因此,在编程之前的设计思路非常重要。

2)将需要封装的封装为类,相应的一些功能函数应当写成函数以便后面可以灵活的调用;

3)计算结果的过程利用的是递归的方法,此处是把握了每次计算的规律,找到相似的地方,在递归函数的实现上,起初总是没结果,后来发现没有传递回来值,所以递归中返回值也是很重要的;

4)原本想要设计的功能是可以自己规定倒计时的时间,写代码的时候遇到困难,没有实现这个功能,后续希望可以完善。

 

原文地址:https://www.cnblogs.com/hx494682/p/15310734.html