一、设计思想:
1.通过Java可视化界面实现对是否有乘除法、是否有负数、是否支持分数以及取值范围等条件的选择。
2.将选择后的真值调用到生成题目的函数中。
3.生成题目的函数中,每个限制条件的子函数通过if语句判断真值,确定是否进入此子函数。
4.子函数的实现:
取值范围:分别为生成随机数的上限和下限。
是否有负数:通过生成随机数的奇偶性来判断是否为负数。
是否有乘除法:若有,则生成随机数对4取余。否则,对2取余。
(注:取余后的值为1、2、3、4分别代表加减乘除)
是否有分数:对分子分母分别去随机值。
(注:若令分数的值在取值范围内,则分子或分母的值可能过大,极难计算。所以,此处将分子和分母的值控制在取值范围内)
注:打印方式没有函数实现。
5.打印题目。
注:用string的二维数组进行记录每个题目的两个值和运算符号。每个题目与它之前记录的所有题目进行比较,如果两个值和运算符号都相同,则题目重出。
点击“生成题目”按钮进行题目打印。如果未输入或未以数字输入取值范围和打印数量、输入的取值下限大于等于上限或者输入的范围小于0,则提示重新输入。
二、源代码
1 package 四则运算; 2 3 import java.awt.Font; 4 import java.awt.Container; 5 import java.awt.event.ActionEvent; 6 import java.awt.event.ActionListener; 7 8 import javax.swing.ButtonGroup; 9 import javax.swing.JComboBox; 10 import javax.swing.JLabel; 11 import javax.swing.JButton; 12 import javax.swing.JOptionPane; 13 import javax.swing.JFrame; 14 import javax.swing.JRadioButton; 15 import javax.swing.JScrollPane; 16 import javax.swing.JTextArea; 17 import javax.swing.JTextField; 18 19 public class Main extends JFrame{ 20 /** 21 * 22 */ 23 private static final long serialVersionUID = 3243154827578985972L; 24 25 public Main(){ 26 super("四则运算题目生成器"); 27 setResizable(false); 28 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 29 setBounds(100,100,500,400); 30 setVisible(true); 31 setLayout(null); 32 DrawMenu(); 33 Update(); 34 } 35 // 申请控件变量 36 JLabel cc_Label = new JLabel("是否有乘除法:"); 37 ButtonGroup bg1 = new ButtonGroup(); 38 JRadioButton cc_RB_Yes = new JRadioButton("有"); 39 JRadioButton cc_RB_No = new JRadioButton("无"); 40 41 JLabel fu_Label = new JLabel("是否有负数:"); 42 ButtonGroup bg2 = new ButtonGroup(); 43 JRadioButton fu_RB_Yes = new JRadioButton("有"); 44 JRadioButton fu_RB_No = new JRadioButton("无"); 45 46 JLabel fen_Label = new JLabel("是否有分数:"); 47 ButtonGroup bg3 = new ButtonGroup(); 48 JRadioButton fen_RB_Yes = new JRadioButton("有"); 49 JRadioButton fen_RB_No = new JRadioButton("无"); 50 51 JLabel sz_Label = new JLabel("数值范围:"); 52 JTextField tf1 = new JTextField("0"); 53 JLabel xx = new JLabel("~"); 54 JTextField tf2 = new JTextField("100"); 55 56 JLabel num_JLabel = new JLabel("打印数量:"); 57 JTextField num_tf = new JTextField("10"); 58 JLabel plan_JLabel = new JLabel("打印方式"); 59 public String[] plan_choice = {"1","2","3"}; 60 JComboBox plan_cb = new JComboBox(plan_choice); 61 ; 62 Container con = getContentPane(); 63 JButton ok_button = new JButton("生成题目"); 64 65 // 出题区域 66 JTextArea question_area = new JTextArea(); 67 JScrollPane sp = new JScrollPane(); 68 69 // 申请数值变量 70 public int num_s = 0,num_b = 0,num_print = 0; // 数值范围和打印数量 71 public int leftNumber = 0,rightNumber = 0; // 生成题目左右的两个数 72 public boolean cc_flag = false,fu_flag = false,fen_flag = false; // 对于条件的判断 73 public int flag = 0; // 用来随机计算运用+ - × ÷ 74 public String qt[][] = new String[10000][3]; 75 public String leftNumber_string = "",rightNumber_string = "",sign_string = ""; // 将生成题目的数转换为String类型 76 77 // 更新数值范围和打印数量 78 public void Update(){ 79 num_s = Integer.parseInt(tf1.getText()); 80 num_b = Integer.parseInt(tf2.getText()); 81 num_print = Integer.parseInt(num_tf.getText()); 82 cc_flag = cc_RB_Yes.isSelected(); 83 fu_flag = fu_RB_Yes.isSelected(); 84 fen_flag = fen_RB_Yes.isSelected(); 85 } 86 87 public void DrawMenu(){ 88 89 // 添加是否有乘除法内容 90 cc_Label.setBounds(10, 10, 100, 20); 91 cc_RB_Yes.setBounds(100, 10, 40, 20); 92 cc_RB_No.setSelected(true); 93 cc_RB_No.setBounds(140,10,40,20); 94 bg1.add(cc_RB_No); 95 bg1.add(cc_RB_Yes); 96 con.add(cc_Label); 97 con.add(cc_RB_No); 98 con.add(cc_RB_Yes); 99 100 // 添加是否有负数法内容 101 fu_Label.setBounds(10, 50, 100, 20); 102 fu_RB_Yes.setBounds(100, 50, 40, 20); 103 fu_RB_No.setSelected(true); 104 fu_RB_No.setBounds(140,50,40,20); 105 bg2.add(fu_RB_No); 106 bg2.add(fu_RB_Yes); 107 con.add(fu_Label); 108 con.add(fu_RB_No); 109 con.add(fu_RB_Yes); 110 111 // 是否支持分数内容 112 fen_Label.setBounds(10, 90, 100, 20); 113 fen_RB_Yes.setBounds(100, 90, 40, 20); 114 fen_RB_No.setSelected(true); 115 fen_RB_No.setBounds(140,90,40,20); 116 bg3.add(fen_RB_No); 117 bg3.add(fen_RB_Yes); 118 con.add(fen_Label); 119 con.add(fen_RB_No); 120 con.add(fen_RB_Yes); 121 122 // 数值范围 123 sz_Label.setBounds(10, 130, 100, 20); 124 con.add(sz_Label); 125 tf1.setBounds(100, 130, 30, 20); 126 con.add(tf1); 127 xx.setBounds(140, 130, 20, 20); 128 con.add(xx); 129 tf2.setBounds(160, 130, 30, 20); 130 con.add(tf2); 131 132 // 打印数量 133 num_JLabel.setBounds(10, 170, 100, 20); 134 con.add(num_JLabel); 135 num_tf.setBounds(100, 170, 30, 20); 136 con.add(num_tf); 137 138 // 打印方式 139 plan_JLabel.setBounds(10, 210, 100, 20); 140 plan_cb.setBounds(100,210,100,20); 141 con.add(plan_JLabel); 142 con.add(plan_cb); 143 144 // 生成题目 145 ok_button.setBounds(10, 280, 100, 30); 146 ok_button.addActionListener(new ok_click()); 147 con.add(ok_button); 148 149 // 出题区域 150 question_area.setEditable(false); 151 question_area.setLineWrap(true); 152 sp.setViewportView(question_area); 153 sp.setBounds(220, 10, 250, 350); 154 // 设置显示字体 155 Font font=new Font("宋体",Font.PLAIN,18); 156 question_area.setFont(font); 157 con.add(sp); 158 } 159 160 public void Output(){ 161 int f0 = 0,f1 = 0; // 判断两个值是否是负数 162 for(int i = 1;i <= num_print;i++){ 163 leftNumber_string = ""; 164 rightNumber_string = ""; 165 166 leftNumber = num_s + (int)(Math.random() * (num_b + 1 - num_s)); 167 rightNumber = num_s + (int)(Math.random()*(num_b + 1 - num_s)); 168 169 if(fu_flag){ // 如果支持负数,随机生成原来数的负数 170 f0 = (int)(Math.random()*5); 171 if(f0 % 2 == 0 && leftNumber != 0) 172 leftNumber_string = "(-"; 173 f1 = (int)(Math.random()*5); 174 if(f1 % 2 == 0 && rightNumber != 0) 175 rightNumber_string = "(-"; 176 } 177 178 flag = (int)(Math.random()*100); 179 if(cc_flag) // 如果支持乘除法 180 flag = flag % 4; // 当flag = 0,1,2,3时,分别进行+,-,×,÷ 181 else 182 flag = flag % 2; 183 184 switch(flag){ 185 case 0: sign_string = "+";break; 186 case 1: sign_string = "-";break; 187 case 2: sign_string = "×";break; 188 case 3: sign_string = "÷";break; 189 } 190 191 if(fen_flag){ // 如果支持分数(注:分数的分子和分母均在取值范围之内) 192 int leftNumber_up = 0,leftNumber_down = 0,rightNumber_up = 0,rightNumber_down = 0; 193 do{ 194 leftNumber_up = num_s + (int)(Math.random()*(num_b + 1 - num_s)); 195 leftNumber_down = num_s + (int)(Math.random()*(num_b + 1- num_s)); 196 rightNumber_up = num_s + (int)(Math.random()*(num_b + 1 - num_s)); 197 rightNumber_down = num_s + (int)(Math.random()*(num_b + 1 - num_s)); 198 }while( leftNumber_down == 0 || rightNumber_down == 0 /* || leftNumber_up / leftNumber_down > num_b || 199 leftNumber_up / leftNumber_down < num_s || rightNumber_up / rightNumber_down > num_b || 200 rightNumber_up / rightNumber_down < num_s */); 201 202 // 分数约分 203 int temp_min_left = Math.min(leftNumber_up,leftNumber_down); 204 int temp_min_right= Math.min(rightNumber_up,rightNumber_down); 205 206 for(int k = temp_min_left;k >= 2;k--){ 207 if(leftNumber_up % k == 0 && leftNumber_down % k == 0){ 208 leftNumber_up = leftNumber_up / k; 209 leftNumber_down = leftNumber_down /k; 210 break; 211 } 212 } 213 if(leftNumber_down == 1) 214 leftNumber_string = leftNumber_string + Integer.toString(leftNumber_up); 215 else 216 leftNumber_string = leftNumber_string + Integer.toString(leftNumber_up) + "/" + Integer.toString(leftNumber_down); 217 218 for(int l = temp_min_right;l >= 2;l--){ 219 if(rightNumber_up % l == 0 && rightNumber_down % l == 0){ 220 rightNumber_up = rightNumber_up / l; 221 rightNumber_down = rightNumber_down / l; 222 break; 223 } 224 } 225 if(rightNumber_down == 1) 226 rightNumber_string = rightNumber_string + Integer.toString(rightNumber_up); 227 else 228 rightNumber_string = rightNumber_string + Integer.toString(rightNumber_up) + "/" + Integer.toString(rightNumber_down); 229 230 } 231 else{ // 如果不支持分数 232 // 将生成的题目记录为String类型 233 leftNumber_string = leftNumber_string + Integer.toString(leftNumber); 234 rightNumber_string = rightNumber_string + Integer.toString(rightNumber); 235 } 236 237 // 如果是负数添加括号(注:分数无负数) 238 if(f0 % 2 == 0 && fu_flag && leftNumber != 0) 239 leftNumber_string = leftNumber_string + ")"; 240 if(f1 % 2 == 0 && fu_flag && rightNumber != 0) 241 rightNumber_string = rightNumber_string + ")"; 242 243 244 // 判断题目是否有问题 245 boolean re = false; 246 for(int j = 1;j < i;j++){ 247 // 判断题目是否重复 248 if(leftNumber_string == qt[j][0] && rightNumber_string == qt[j][1] && sign_string == qt[j][2]){ 249 re = true; 250 } 251 // 判断除数是否为0 252 if(flag == 3 && rightNumber == 0){ 253 re = true; 254 } 255 } 256 if(re){ 257 i = i - 1; 258 } 259 else{ 260 qt[i][0] = leftNumber_string; 261 qt[i][1] = rightNumber_string; 262 qt[i][2] = sign_string; 263 } 264 265 } 266 267 } 268 269 270 public void Print(){ 271 for(int i = 1;i <= num_print;i++){ 272 question_area.append(qt[i][0] + " " + qt[i][2] + " " + qt[i][1] + " " +"="); 273 question_area.append(" "); 274 } 275 276 } 277 278 public static void main(String args[]){ 279 new Main(); 280 } 281 282 class ok_click implements ActionListener{ 283 284 @Override 285 public void actionPerformed(ActionEvent e) { 286 // TODO 自动生成的方法存根 287 question_area.setText(""); // 重新出题,进行区域清空 288 // 对输入的值是否规范进行判断 289 boolean isInt = true; 290 for(int i = 0;i < tf1.getText().length();i++) 291 if(!Character.isDigit(tf1.getText().charAt(i))) 292 isInt = false; 293 for(int i = 0;i < tf2.getText().length();i++) 294 if(!Character.isDigit(tf2.getText().charAt(i))) 295 isInt = false; 296 for(int i = 0;i < num_tf.getText().length();i++) 297 if(!Character.isDigit(num_tf.getText().charAt(i))) 298 isInt = false; 299 // 判断值是否不是整型,是否为空值,取值是否超出范围 300 if(tf1.getText().equalsIgnoreCase("") || tf2.getText().equalsIgnoreCase("")|| 301 num_tf.getText().equalsIgnoreCase("")) 302 JOptionPane.showMessageDialog(null, "输入不能有空值,请重新输入!"); 303 else if(isInt == false) 304 JOptionPane.showMessageDialog(null, "输入必须为数字,请重新输入!"); 305 else if(Integer.parseInt(num_tf.getText()) >= 10000) 306 JOptionPane.showMessageDialog(null, "打印数量过多,请重新输入!"); 307 else if(Integer.parseInt(tf1.getText()) >= Integer.parseInt(tf2.getText())) 308 JOptionPane.showMessageDialog(null, "取值范围的下限不能大于等于上限,请重新输入!"); 309 else if(Integer.parseInt(tf1.getText()) < 0 || Integer.parseInt(tf2.getText()) < 0) 310 JOptionPane.showMessageDialog(null, "取值范围不能为负数,请重新输入!"); 311 else{ 312 Update(); 313 Output(); 314 Print(); 315 } 316 } 317 } 318 }
三、运行结果
运行界面:
所有条件均满足时,打印界面:
四、时间记录日志
日期 | 时间 | 进度 | 净时 |
3/18 | 13:00~14:00 | 实现初步界面 | 60 |
14:00~15:30 | 实现初步算法 | 90 | |
15:30~17:00 | 算法完善 | 90 | |
19:00~21:00 |
算法完善与界面优化 | 120 |
五、个人总结:
1.做出更加详细的设计思想,尽量不要摸着石头过河。
2.灵活运用一些全局变量。