2023/11/10 每日总结
今天完成了软件构造课后作业
完成了以下功能,
给之前的口算题生成软件构建合适的GUI界面(注意不能直接提交课程案例中的界面代码),并尝试到处exe可运行文件。提交实现效果截图及相关代码。
package std; import java.util.HashSet; import java.util.Random; import java.util.Set; public class Exercise { private Set<Expression> exercises; public Exercise() { exercises = new HashSet<>(); } public void generateExercises(int numberOfExercises, int operandRange) { Random random = new Random(); exercises.clear(); // 清空已有的题目 while (exercises.size() < numberOfExercises) { int operand1 = random.nextInt(operandRange + 1); int operand2 = random.nextInt(operandRange + 1); char operator = random.nextBoolean() ? '+' : '-'; Expression newExpression = new Expression(operand1, operand2, operator); // 检查新生成的题目是否已存在 if (!exercises.contains(newExpression)) { exercises.add(newExpression); } } } public Set<Expression> getExercises() { return exercises; } public int getExerciseCount() { return exercises.size(); } } package std; import java.util.Objects; public class Expression { private int operand1; private int operand2; private char operator; private int result; private Integer userAnswer; public Expression(int operand1, int operand2, char operator) { this.operand1 = operand1; this.operand2 = operand2; this.operator = operator; this.result = calculateResult(); } private int calculateResult() { switch (operator) { case '+': return operand1 + operand2; case '-': return operand1 - operand2; default: return 0; } } public String getExpressionString() { return operand1 + " " + operator + " " + operand2 + " = "; } public int getResult() { return result; } public Integer getUserAnswer() { return userAnswer; } public void setUserAnswer(Integer userAnswer) { this.userAnswer = userAnswer; } public boolean isAnswered() { return userAnswer != null; } public boolean isCorrect() { return isAnswered() && userAnswer.equals(result); } public int getOperand1() { return operand1; } public int getOperand2() { return operand2; } public char getOperator() { return operator; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; Expression that = (Expression) obj; return operand1 == that.operand1 && operand2 == that.operand2 && operator == that.operator; } @Override public int hashCode() { return Objects.hash(operand1, operand2, operator); } }
package std;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class GUI extends JFrame {
private Exercise exercise;
private int currentPage;
private int exercisesPerPage;
private int totalExercises;
private JTextField numberOfExercisesField;
private JPanel exercisePanel;
public GUI() {
exercise = new Exercise();
currentPage = 0;
exercisesPerPage = 25;
numberOfExercisesField = new JTextField(5);
JButton setNumberOfExercisesButton = new JButton("Set Number of Exercises");
setNumberOfExercisesButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
totalExercises = Integer.parseInt(numberOfExercisesField.getText());
generateExercises(totalExercises);
currentPage = 0;
displayExercises();
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(GUI.this, "请输入有效的题目数量。", "错误", JOptionPane.ERROR_MESSAGE);
}
}
});
JButton checkAnswersButton = new JButton("Check Answers");
checkAnswersButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
checkAnswers();
}
});
JButton saveToCSVButton = new JButton("Save to CSV");
saveToCSVButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
saveToCSV();
}
});
JButton loadFromCSVButton = new JButton("Load from CSV");
loadFromCSVButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
loadFromCSV();
}
});
JPanel buttonPanel = new JPanel();
buttonPanel.add(new JLabel("Number of Exercises:"));
buttonPanel.add(numberOfExercisesField);
buttonPanel.add(setNumberOfExercisesButton);
buttonPanel.add(checkAnswersButton);
buttonPanel.add(saveToCSVButton);
buttonPanel.add(loadFromCSVButton);
add(buttonPanel, BorderLayout.SOUTH);
exercisePanel = new JPanel();
exercisePanel.setLayout(new GridLayout(exercisesPerPage / 5, 5, 10, 10));
JButton prevButton = new JButton("Prev");
prevButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
currentPage = Math.max(0, currentPage - 1);
displayExercises();
}
});
JButton nextButton = new JButton("Next");
nextButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
currentPage++;
displayExercises();
}
});
JPanel paginationPanel = new JPanel();
paginationPanel.add(prevButton);
paginationPanel.add(nextButton);
add(paginationPanel, BorderLayout.NORTH);
add(new JScrollPane(exercisePanel), BorderLayout.CENTER);
setSize(1000, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
private void generateExercises(int numberOfExercises) {
exercise.generateExercises(numberOfExercises, 10);
}
private void displayExercises() {
exercisePanel.removeAll();
int startIndex = currentPage * exercisesPerPage;
int endIndex = Math.min((currentPage + 1) * exercisesPerPage, totalExercises);
List<Expression> exercisesList = new ArrayList<>(exercise.getExercises());
for (int i = startIndex; i < endIndex; i += 5) {
JPanel rowPanel = new JPanel();
rowPanel.setLayout(new GridLayout(1, 0, 10, 10));
for (int j = 0; j < 5; j++) {
if (i + j < endIndex) {
Expression exp = exercisesList.get(i + j);
JLabel expressionLabel = new JLabel(exp.getExpressionString());
rowPanel.add(expressionLabel);
JTextField answerField = new JTextField(5);
answerField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
updateExpression();
}
@Override
public void removeUpdate(DocumentEvent e) {
updateExpression();
}
@Override
public void changedUpdate(DocumentEvent e) {
updateExpression();
}
private void updateExpression() {
try {
String userInput = answerField.getText();
if (!userInput.isEmpty()) {
int userAnswer = Integer.parseInt(userInput);
exp.setUserAnswer(userAnswer);
}
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(GUI.this, "请输入有效的数字。", "错误", JOptionPane.ERROR_MESSAGE);
}
}
});
rowPanel.add(answerField);
}
}
exercisePanel.add(rowPanel);
}
revalidate();
repaint();
}
private void checkAnswers() {
int correctCount = 0;
for (Expression exp : exercise.getExercises()) {
if (exp.isCorrect()) {
correctCount++;
}
}
int accuracy = (int) ((double) correctCount / totalExercises * 100);
JOptionPane.showMessageDialog(this, "Correct Answers: " + correctCount + "\nAccuracy: " + accuracy + "%", "Results",
JOptionPane.INFORMATION_MESSAGE);
}
private void saveToCSV() {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogTitle("Save to CSV");
fileChooser.setFileFilter(new FileNameExtensionFilter("CSV files (*.csv)", "csv"));
int userSelection = fileChooser.showSaveDialog(this);
if (userSelection == JFileChooser.APPROVE_OPTION) {
File fileToSave = fileChooser.getSelectedFile();
if (!fileToSave.getName().toLowerCase().endsWith(".csv")) {
fileToSave = new File(fileToSave.getAbsolutePath() + ".csv");
}
try (PrintWriter writer = new PrintWriter(fileToSave)) {
List<Expression> exercisesList = new ArrayList<>(exercise.getExercises());
for (Expression exp : exercisesList) {
writer.println(exp.getOperand1() + "," + exp.getOperator() + "," + exp.getOperand2() + "," + exp.getResult());
}
JOptionPane.showMessageDialog(this, "Saved to: " + fileToSave.getAbsolutePath(), "Save Successful", JOptionPane.INFORMATION_MESSAGE);
} catch (IOException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(this, "Error saving file.", "Error", JOptionPane.ERROR_MESSAGE);
}
}
}
private void loadFromCSV() {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogTitle("Load from CSV");
fileChooser.setFileFilter(new FileNameExtensionFilter("CSV files (*.csv)", "csv"));
int userSelection = fileChooser.showOpenDialog(this);
if (userSelection == JFileChooser.APPROVE_OPTION) {
File fileToLoad = fileChooser.getSelectedFile();
try (BufferedReader reader = new BufferedReader(new FileReader(fileToLoad))) {
exercise.getExercises().clear();
String line;
while ((line = reader.readLine()) != null) {
String[] parts = line.split(",");
if (parts.length == 4) {
int operand1 = Integer.parseInt(parts[0]);
char operator = parts[1].charAt(0);
int operand2 = Integer.parseInt(parts[2]);
int result = Integer.parseInt(parts[3]);
Expression exp = new Expression(operand1, operand2, operator);
exp.setUserAnswer(null); // Reset user answer
exercise.getExercises().add(exp);
}
}
totalExercises = exercise.getExercises().size();
currentPage = 0;
displayExercises();
JOptionPane.showMessageDialog(this, "Loaded from: " + fileToLoad.getAbsolutePath(), "Load Successful", JOptionPane.INFORMATION_MESSAGE);
} catch (IOException | NumberFormatException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(this, "Error loading file.", "Error", JOptionPane.ERROR_MESSAGE);
}
}
}
}
package std; public class Main { public static void main(String[] args) { GUI gui = new GUI(); } }