9.24方法PPT课后
- 编写一个方法,使用纯随机数发生器生成指定数目(比如1000个)的随机整数。
import java.util.ArrayList;
import java.util.List;
public class RandomGenerator {
// 固定参数:和题目对应
private static final long MODULUS = (1L << 31) - 1; // 2^31 -1,注意用long避免溢出
private static final long MULTIPLIER = 16807; // 即7^5
private static final long C = 0;
// 种子:需要初始化,默认可以用当前时间戳
private long seed;
/**
* 用自定义种子构造生成器
* @param seed 初始种子 不能是0,否则生成的所有数都是0
*/
public RandomGenerator(long seed) {
if (seed == 0) {
throw new IllegalArgumentException("种子不能为0");
}
// 保证种子在模数范围内
this.seed = seed % MODULUS;
}
/**
* 默认用当前时间戳作为种子
*/
public RandomGenerator() {
this(System.currentTimeMillis());
}
/**
* 生成下一个随机整数
* @return 范围在 [1, 2^31-2] 的随机整数
*/
public int nextInt() {
// 用long计算防止整数溢出
seed = (MULTIPLIER * seed + C) % MODULUS;
// 因为范围是1~2^31-2,强转为int正好是合法的正整数
return (int) seed;
}
/**
* 生成指定数量的随机整数
* @param count 要生成的个数
* @return 随机数列表
*/
public List<Integer> generate(int count) {
if (count <= 0) {
throw new IllegalArgumentException("生成数量必须大于0");
}
List<Integer> res = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
res.add(nextInt());
}
return res;
}
// 测试:生成1000个随机数
public static void main(String[] args) {
RandomGenerator generator = new RandomGenerator();
// 生成1000个随机数
List<Integer> randomNumbers = generator.generate(1000);
// 输出前20个做演示,避免打印太多
System.out.println("前20个生成的随机数:");
for (int i = 0; i < 20; i++) {
System.out.printf("%d\t", randomNumbers.get(i));
if ((i + 1) % 5 == 0) {
System.out.println();
}
}
}
}
- 以下代码的特殊之处

这段代码的特殊之处在于它展示了方法重载的概念。方法重载是指在同一个类中,允许存在多个同名方法,但这些方法的参数列表必须不同(参数的类型、个数或顺序不同)。
具体到这段代码:
- 定义了两个同名方法 square,一个接受 int 类型的参数,另一个接受 double 类型的参数。
- 在 main 方法中,分别调用了这两个重载方法:
- square(7) 调用的是接受 int 参数的方法,返回 7 * 7 = 49。
- square(7.5) 调用的是接受 double 参数的方法,返回 7.5 * 7.5 = 56.25
- 像二柱子那样,花二十分钟写一个能自动生成30道小学四则运算题目的 “软件”
import java.util.Random;
public class ArithmeticGenerator {
public static void main(String[] args) {
System.out.println("--- 小学二年级四则运算自动生成器 ---");
System.out.println("-------------------------------------");
// 循环生成30道题目
for (int i = 1; i <= 30; i++) {
String question = generateQuestion();
// 格式化输出,每行显示5道题,方便打印
System.out.printf("%-2d. %-15s", i, question);
if (i % 3 == 0) { // 每3道题换一行(也可以改成5)
System.out.println();
}
}
}
/**
* 生成单道题目的方法
*/
public static String generateQuestion() {
Random random = new Random();
// 随机选择运算符:0:+, 1:-, 2:*, 3:/
int operatorType = random.nextInt(4);
int num1, num2;
String operator = "";
int result = 0;
switch (operatorType) {
case 0: // 加法
// 限制在100以内
num1 = random.nextInt(50) + 1;
num2 = random.nextInt(50) + 1;
operator = "+";
break;
case 1: // 减法
// 保证 num1 >= num2,结果不为负数
num1 = random.nextInt(100) + 1;
num2 = random.nextInt(num1) + 1; // 生成 1 到 num1 之间的数
operator = "-";
break;
case 2: // 乘法
// 小学二年级乘法通常使用乘法口诀表范围 (1-9)
num1 = random.nextInt(9) + 1;
num2 = random.nextInt(9) + 1;
operator = "×";
break;
case 3: // 除法
default:
// 保证能整除
num2 = random.nextInt(9) + 1; // 除数 1-9
int multiplier = random.nextInt(9) + 1; // 商 1-9
num1 = num2 * multiplier; // 被除数 = 除数 * 商
operator = "÷";
break;
}
return num1 + " " + operator + " " + num2 + " =";
}
}
- (1)要求题目避免重复,减法不允许出现负数,乘法结果不允许出现四位数,除法必须整除不允许出现小数;
(2)实现在线实时答题,并在答题结束后,统计显示错题数,正确率;
(3)增加倒计时功能,要求在指定时间内完成测试,超时未做完视为错题。
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
public class ArithmeticTestGUI extends JFrame {
private static final int TOTAL_QUESTIONS = 20; // 每轮题目数量,参考图片大约20道
private static final int TIME_LIMIT_SECONDS = 300; // 倒计时时间(秒),例如5分钟
private JTextField[] answerFields = new JTextField[TOTAL_QUESTIONS];
private String[] questions = new String[TOTAL_QUESTIONS];
private int[] correctAnswers = new int[TOTAL_QUESTIONS];
private long startTime;
private int timeRemaining = TIME_LIMIT_SECONDS;
private Timer countdownTimer;
private boolean isSubmitted = false;
public ArithmeticTestGUI() {
// 1. 初始化窗口设置
setTitle("整数四则运算测试");
setSize(900, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null); // 居中显示
setLayout(new BorderLayout(10, 10));
// 2. 生成题目
generateQuestions();
// 3. 构建顶部信息面板
JPanel topPanel = new JPanel(new BorderLayout());
JLabel infoLabel = new JLabel(" 201571030128 王静雅的第1轮测试...", JLabel.LEFT);
infoLabel.setFont(new Font("宋体", Font.BOLD, 14));
topPanel.add(infoLabel, BorderLayout.WEST);
// (可选) 顶部可以放倒计时,但图片中没有直观显示倒计时在界面上,所以我们在后台运行,最后弹窗提示
add(topPanel, BorderLayout.NORTH);
// 4. 构建中间题目面板 (4列5行的网格)
JPanel centerPanel = new JPanel(new GridLayout(5, 4, 10, 20));
centerPanel.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20));
for (int i = 0; i < TOTAL_QUESTIONS; i++) {
JPanel qPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
JLabel qLabel = new JLabel(questions[i] + " =");
qLabel.setFont(new Font("Arial", Font.PLAIN, 14));
answerFields[i] = new JTextField(4);
answerFields[i].setFont(new Font("Arial", Font.PLAIN, 14));
qPanel.add(qLabel);
qPanel.add(answerFields[i]);
centerPanel.add(qPanel);
}
add(centerPanel, BorderLayout.CENTER);
// 5. 构建底部按钮面板
JPanel bottomPanel = new JPanel();
JButton submitButton = new JButton("查看得分");
submitButton.setFont(new Font("宋体", Font.BOLD, 14));
submitButton.setPreferredSize(new Dimension(120, 35));
bottomPanel.add(submitButton);
add(bottomPanel, BorderLayout.SOUTH);
// 6. 绑定交卷事件
submitButton.addActionListener(e -> submitTest(false));
// 7. 启动倒计时
startTimer();
}
private void startTimer() {
startTime = System.currentTimeMillis();
countdownTimer = new Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
timeRemaining--;
if (timeRemaining <= 0) {
countdownTimer.stop();
submitTest(true); // 超时交卷
}
}
});
countdownTimer.start();
}
private void submitTest(boolean isTimeout) {
if (isSubmitted) return; // 防止重复提交
isSubmitted = true;
if (countdownTimer != null) {
countdownTimer.stop();
}
long endTime = System.currentTimeMillis();
long timeSpentSeconds = (endTime - startTime) / 1000;
int wrongCount = 0;
// 遍历检查答案
for (int i = 0; i < TOTAL_QUESTIONS; i++) {
String userAnswerStr = answerFields[i].getText().trim();
if (userAnswerStr.isEmpty()) {
wrongCount++; // 未作答视为错题
continue;
}
try {
int userAnswer = Integer.parseInt(userAnswerStr);
if (userAnswer != correctAnswers[i]) {
wrongCount++;
}
} catch (NumberFormatException e) {
wrongCount++; // 输入非数字视为错题
}
}
int correctCount = TOTAL_QUESTIONS - wrongCount;
double accuracy = (double) correctCount / TOTAL_QUESTIONS * 100;
// 弹出成绩对话框
String message;
if (isTimeout) {
message = String.format("时间到!自动交卷。\n\n本次用时:%d 秒\n错题数:%d 题\n正确率:%.1f%%",
timeSpentSeconds, wrongCount, accuracy);
} else {
message = String.format("您本次用时:%d 秒\n错题数:%d 题\n正确率:%.1f%%",
timeSpentSeconds, wrongCount, accuracy);
}
JOptionPane.showMessageDialog(this, message, "测试结果", JOptionPane.INFORMATION_MESSAGE);
// 禁用所有输入框,防止交卷后修改
for (JTextField field : answerFields) {
field.setEnabled(false);
}
}
private void generateQuestions() {
Random random = new Random();
Set<String> questionSet = new HashSet<>(); // 用于去重
int count = 0;
while (count < TOTAL_QUESTIONS) {
// 随机决定这道题有几个运算符 (1个或2个,太复杂不适合口算)
int operatorCount = random.nextInt(2) + 1;
String question = "";
int result = 0;
if (operatorCount == 1) {
// 简单题:A op B
int[] nums = new int[2];
char[] ops = new char[1];
if (generateSimpleExpression(random, nums, ops)) {
question = nums[0] + " " + ops[0] + " " + nums[1];
result = calculate(nums[0], nums[1], ops[0]);
} else {
continue;
}
} else {
// 复杂题:A op1 B op2 C (形如 55*18+89 等)
int[] nums = new int[3];
char[] ops = new char[2];
if (generateComplexExpression(random, nums, ops)) {
question = nums[0] + " " + ops[0] + " " + nums[1] + " " + ops[1] + " " + nums[2];
// 按照从左到右计算(默认无括号),若需支持括号需特殊处理,此处简化处理,保持与图一致
int temp = calculate(nums[0], nums[1], ops[0]);
result = calculate(temp, nums[2], ops[1]);
} else {
continue;
}
}
// 去重逻辑
if (!questionSet.contains(question) && result >= 0) {
questions[count] = question;
correctAnswers[count] = result;
questionSet.add(question);
count++;
}
}
}
// 生成简单的单运算符表达式,满足约束
private boolean generateSimpleExpression(Random random, int[] nums, char[] ops) {
int opType = random.nextInt(4); // 0:+, 1:-, 2:*, 3:/
int a, b;
switch (opType) {
case 0: // 加法:限制在100以内
a = random.nextInt(50) + 1;
b = random.nextInt(50) + 1;
nums[0] = a; nums[1] = b; ops[0] = '+';
return true;
case 1: // 减法:不出现负数
a = random.nextInt(100) + 1;
b = random.nextInt(a) + 1; // b <= a
nums[0] = a; nums[1] = b; ops[0] = '-';
return true;
case 2: // 乘法:结果不出现四位数 (<=999,即a*b < 1000)
a = random.nextInt(99) + 1;
b = random.nextInt(99) + 1;
if (a * b > 999) return false;
nums[0] = a; nums[1] = b; ops[0] = '*';
return true;
case 3: // 除法:必须整除,不出现小数
b = random.nextInt(99) + 1;
int tempResult = random.nextInt(99) + 1;
a = b * tempResult;
nums[0] = a; nums[1] = b; ops[0] = '/';
return true;
}
return false;
}
// 生成复杂的双运算符表达式 (如 A*B+C)
private boolean generateComplexExpression(Random random, int[] nums, char[] ops) {
// 为保证结果合理,通常第一个运算符优先级较高(乘除),或者第一个是加减法
// 这里为了简化,模拟图片中的题型,生成形如 a*b+c 或 a+b*c 等
int type = random.nextInt(4);
int a, b, c;
// 此处只做基础校验,保证每步计算都不越界
try {
switch (type) {
case 0: // a * b + c
a = random.nextInt(20) + 1; b = random.nextInt(20) + 1;
if (a * b > 999) return false;
c = random.nextInt(100) + 1;
nums[0]=a; nums[1]=b; nums[2]=c; ops[0]='*'; ops[1]='+';
return true;
case 1: // a + b * c
a = random.nextInt(100) + 1;
b = random.nextInt(20) + 1; c = random.nextInt(20) + 1;
if (b * c > 999) return false;
nums[0]=a; nums[1]=b; nums[2]=c; ops[0]='+'; ops[1]='*';
return true;
case 2: // a * b - c
a = random.nextInt(20) + 1; b = random.nextInt(20) + 1;
if (a * b > 999 || a * b < 1) return false;
c = random.nextInt(a * b) + 1; // 保证减去后不为负数
nums[0]=a; nums[1]=b; nums[2]=c; ops[0]='*'; ops[1]='-';
return true;
case 3: // a / b + c
b = random.nextInt(20) + 1;
int res = random.nextInt(20) + 1;
a = b * res;
c = random.nextInt(100) + 1;
nums[0]=a; nums[1]=b; nums[2]=c; ops[0]='/'; ops[1]='+';
return true;
}
} catch (Exception e) {
return false;
}
return false;
}
// 计算单步结果
private int calculate(int a, int b, char op) {
switch (op) {
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/': return b != 0 ? a / b : 0;
}
return 0;
}
public static void main(String[] args) {
// 在事件调度线程中运行GUI
SwingUtilities.invokeLater(() -> {
new ArithmeticTestGUI().setVisible(true);
});
}
}
浙公网安备 33010602011771号