一、需求分析
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 }
(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 }
(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 }
(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 }
(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 }
(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 }
(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 }
(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 }
2.6 代码运行结果:
(1)开始界面
(2)答题界面
(3)答题测试
(4)查看记录
四、反思总结体会
1)由于题目需求较多,因此,在编程之前的设计思路非常重要。
2)将需要封装的封装为类,相应的一些功能函数应当写成函数以便后面可以灵活的调用;
3)计算结果的过程利用的是递归的方法,此处是把握了每次计算的规律,找到相似的地方,在递归函数的实现上,起初总是没结果,后来发现没有传递回来值,所以递归中返回值也是很重要的;
4)原本想要设计的功能是可以自己规定倒计时的时间,写代码的时候遇到困难,没有实现这个功能,后续希望可以完善。