基于案例的软件构造教程学期大作业-100以内的加减法

小组开发,感谢组内大佬带我飞,我就是个做ppt的混子

说明:
①代码仅供参考,实现了课本上的所有功能并且通过了上台展示。
②编写用的eclipse,具体的文件路径结构已经不记得了。
③下面的代码是很多个Java程序放在一起了,想要用把代码顺一遍,找找文件的开始结尾位置。
④ 注释是个好东西,建议学弟学妹不要直接白嫖,尽量读一读代码。

package ExerciseTest;

public class AdditionOperation extends BinaryOperation{
	AdditionOperation(){
		generateBinaryOperation('+');
	}
	public boolean checkingCalculation(int anInteger){
	//方法重写,使该类的算式符合规定的加法算式标准
		if(anInteger<=upper)
			return true;
		else
			return false;
	}
	int calculate(int left,int right){
		return left + right;	
	}
}

class SubstractOperation extends BinaryOperation{
	SubstractOperation(){
		generateBinaryOperation('-');
	}
	public boolean checkingCalculation(int anInteger){
	//方法重写,使该类的算式符合规定的减法算式标准
		if(anInteger>=lower)
			return true;
		else
			return false;
	}
	int calculate(int left,int right){
		return left - right;
	}
}
package ExerciseTest;

import java.io.Serializable;
import java.util.Random;

public abstract class BinaryOperation implements Serializable{
	static final int upper = 100;
	static final int lower = 0;
	private int left_operand = 0,right_operand = 0;
	private char operator = '+';
	private int value = 0;
	
	public void insert(String left, String right){
		//新增:insert通过调用这个方法可以直接插入算式
		left_operand = Integer.valueOf(left);
		right_operand = Integer.valueOf(right);
		value = calculate(left_operand, right_operand);
	}
	public void insert(int left, int right){
		//新增:int参数的insert
		left_operand = left;
		right_operand = right;
		value = calculate(left_operand, right_operand);
	}
	//重载public String toString
	public String toString(){
		String s;
		String Charop = String.valueOf(operator);
		s = left_operand+Charop+right_operand+"=";
		return s;
	}
	
	
	// getXX 返回需要访问的数字和符号
	public char getOperator(){
		return operator;
	}
	public int getleft_operand(){
		return left_operand;
	}
	public int getright_operand(){
		return right_operand;
	}
	public int getvalue() {
		return value;
	}
	
	protected void generateBinaryOperation(char anOperator){
		//传入的anOperator即为该类生成的算式的运算符号
		int left,right,result;
		Random random = new Random();
		left = random.nextInt(upper+1);
		do{
		//约束,两位整数必须符合约束条件才能赋值给成员函数
			right = random.nextInt(upper+1);
			result = calculate(left,right);
		}while(!(checkingCalculation(result)));
		left_operand = left;
		right_operand = right;
		operator = anOperator;
		value = result;
	}
	abstract boolean checkingCalculation(int anInteger);
	//检查是否符合算式标准
	abstract int calculate(int left, int right);
	//计算算式结果

	public boolean equals(BinaryOperation anOperation){
	//方法将该对象的数字符号与另一个对象的数字符号做比较,起到检查是否重复的作用
		return operator==anOperation.getOperator()&&
				right_operand==anOperation.getright_operand()&&
				left_operand==anOperation.getleft_operand();
	}
}
package ExerciseTest;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Exercise implements Serializable{
	private static final long serialVersionUID = 6829563053067592708L;
	private int OperationCount = 0;//新增:记录这个Exercise的算式总数
	protected String FileName ;//新增:练习名称
	public String Addr = "D:/加减法练习/";//新增:练习地址
	private int current = 0;//记录当前访问位置
	
	class Answers implements Serializable {	//答案内部类
		private static final long serialVersionUID = -232662116583465565L;
		String content;		//答案内容
		boolean correct;	//正确性
		public Answers() {content = ""; correct = false;}
		public Answers(String ans, boolean cr) {
			content = ans; correct = cr;
		}
	}
	
	private ArrayList operationList = new ArrayList();
	private List  answers = new ArrayList<>();		//用户填写的所有题目的答案列表
	
	private ExerciseType currentType;		//当前题目类型,为串行化保存用
	public ExerciseType getCurrentType() {return currentType;}
	
	public String getExerciseType() {
		String s = new String();
		switch(currentType) {
		case ADDandSUB:
			s = "加减混合";
			break;
		case ADD:
			s = "仅加法";
			break;
		case SUB:
			s = "仅减法";
			break;
		}	
		return s;
	}
	
	private void setCurrentType(ExerciseType type) { this.currentType = type;}
	public void setAnswer(int index, String ans) {		
		//设置答案内容并判断正确性
		BinaryOperation op;
		op = operationList.get(index);		//获取算式
		String result = String.valueOf(op.getvalue());		//获取正确结果
		String tans = ans.trim();//获取用户输入的答案
		answers.set(index, new Answers(tans, result.equals(tans)));  
		//设置答案内容和正确性,index位置上设置为对应的answer对象,对象里面保存用户答案和是否正确
	}
	public String getAnswer(int index) {	//获取答案
		return answers.get(index).content;
	}
	public void clearAnswers() {		//清空答案(全设为空,错误)
		for (int i = 0; i < answers.size(); i++)
			answers.set(i, new Answers("", false));
	}
	
	public int Correct() {		//统计正确题数
		int correctAmount = 0;
		for (int i = 0; i < answers.size(); i++) {
			if (getJudgement(i))
				correctAmount++;
		}
		return correctAmount;
	}
	
	public boolean getJudgement(int index) {	
		//获取判题结果
		return answers.get(index).correct;
	}
	
	public void saveObject(String filename, Exercise exercise) throws ExerciseIOException{		
		//串行化存储对象
		FileOutputStream f = null;
		try {
			 f = new FileOutputStream(filename);
			 //可以传入一个字符串的文件地址,地址不为空时,自动为字符串创建File对象
		} catch (FileNotFoundException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		
		ObjectOutputStream s = null;
		try {
			 s = new ObjectOutputStream(f);
			 //定义ObjectOutputStream对象需要用一个FileOutputStream来构造文件字节输出流对象
		} catch (IOException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		
		try {
			s.writeObject(exercise);//向文件中输出算式
			s.flush();
			//刷新此输出流并强制写出所有缓冲的输出字节。
			//flush 的常规协定是:如果此输出流的实现已经缓冲了以前写入的任何字节,则调用此方法指示应将这些字节立即写入它们预期的目标。
		} catch (IOException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		
		try {
			s.close();
		} catch (IOException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		
	}
	public static Exercise loadObject(String filename) throws ExerciseIOException{	
		//串行化载入对象
		FileInputStream in = null;
		try {
			in = new FileInputStream(filename);
		} catch (FileNotFoundException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		ObjectInputStream s = null;
		try {
			s = new ObjectInputStream(in);
		} catch (IOException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		Exercise exercise = null;
		try {
			exercise = (Exercise) s.readObject();
		} catch (ClassNotFoundException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		} catch (IOException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		try {
			s.close();
		} catch (IOException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		return exercise;
	}
	public void generateWithFormerType(int operationCount) {	
		//采用原题型生成新题目
		switch(currentType) {
		case ADDandSUB:
			this.generateBinaryExercise(operationCount);
			break;
		case ADD:
			this.generateAdditionExercise(operationCount);
			break;
		case SUB:
			this.generateBinaryExercise(operationCount);
			break;
		}	
	}
	public enum ExerciseType {
		ADD , SUB, ADDandSUB, 
	}
	//重构结束
	
	
	//创建一个关于BinaryOperation(算式)的动态数组
	
	public Exercise() {
		File aFile = new File(Addr);
		if(!aFile.exists())
				aFile.mkdir();
	}
	
	public boolean hasNext(){
		return current<=operationList.size()-1;
	}//若数组还有元素,则返回是,否则返回否

	public BinaryOperation next(){
		return operationList.get(current++);
	}//若有元素,返回当前元素,当前访问位置移动到下一个位置

	public boolean contains(BinaryOperation anOperation){
		boolean flag = true;
		int size = operationList.size();
		if(size==0){//如果数组里没有算式,返回false,允许加入数组
			return false;
		}
		for(int i = 0;i0){
				do{
					anOperation = generateOperation();
					}while(contains(anOperation));
				operationList.add(anOperation);
				answers.add(new Answers());
				//将anOperation 加入到Exercise中
				operationCount--;
			}
	}

	public void generateAdditionExercise(int operationCount){
		//随机生成加法算式并加入数组
		setCurrentType(ExerciseType.ADD ); //设置题目类型
		
		answers.clear();
		operationList.clear();
		current = 0;
		OperationCount = operationCount;
		FileName= "Addition_exercise_"+operationCount+"_";
		BinaryOperation anOperation1;
			while(operationCount>0){
				do{anOperation1 = new AdditionOperation();}while(contains(anOperation1));
				operationList.add(anOperation1);//将anOperation 加入到Exercise中
				answers.add(new Answers());
				operationCount--;
			}
	}
	
	public void generateSubstractExercise(int operationCount){
	//随机生成减法算式并加入数组
		setCurrentType(ExerciseType.SUB );
		operationList.clear();
		answers.clear();
		
		operationList.clear();
		current = 0;
		OperationCount = operationCount; 
		FileName= "Substract_exercise_"+operationCount+"_";
		BinaryOperation anOperation1;
			while(operationCount>0){
				do{anOperation1 = new SubstractOperation();}while(contains(anOperation1));
				operationList.add(anOperation1);
				answers.add(new Answers());
				//将anOperation 加入到Exercise中
				operationCount--;
		}
	}

	public void writeCSVExercise()//生成文件
	{
		int count = OperationCount;//算式数量
		FileName = Addr + FileName+".csv";//生成习题文件名称
		String PracticeName = FileName.replaceAll("exercise", "practice");
		System.out.println(FileName);
		System.out.println(PracticeName);
		try {
			File file =new File(FileName);
			 if(!file.exists()){
				   file.createNewFile();
			}
			 File pfile = new File(PracticeName);
			 if(!pfile.exists()) {
				 pfile.createNewFile();
			 }
			FileWriter fileWritter = new FileWriter(file,false);
			for(int i=0;i opResults=new ArrayList  ();
		FileInputStream in = new FileInputStream(anExerciseFile);
		int b = 0;
		String eqString="";
		while(b!=-1){
				b = in.read();
				if((char)b==','||(char)b=='\r'){
					opResults.add(Integer.valueOf(eqString));
					eqString="";
				}else if((char)b!='\r'&&(char)b!='\n')
					eqString+=(char)b;
			}
			in.close();
			Integer[] bb=new Integer[opResults.size()];
			return opResults.toArray(bb);
	}
	
	private Integer[] getAnswers(Exercise exercise)throws Exception{
		//获得正确答案
		ArrayListopAnswer = new ArrayList();
		while(exercise.hasNext()) {
			//System.out.println(exercise.next());
			opAnswer.add(exercise.next().getvalue());
		}
		Integer[]bb = new Integer[opAnswer.size()];
		return opAnswer.toArray(bb);
	}
	
	public void writeCSVReport(File aReportFile) throws IOException{			
	//传入一个文件,将批改结果输出到该文件中
		OperationCount = correct+wrong;//算式数量
		String str;
		str = "答案:"+ CheckingName;
		FileWriter FW = new FileWriter(aReportFile,false);
		FW.write(str+",\r\n");
		str = "答案总数:"+OperationCount;
		FW.write(str+",\r\n");
		str = "正确:"+correct;
		FW.write(str+",\r\n");
		str = "错误:"+wrong;
		FW.write(str+",\r\n");
		str = "得分:"+score;
		FW.write(str+",\r\n");
		System.out.println("批改文件已生成");
		FW.close();
	}
	
	public void Practice(Exercise anExercise) throws Exception {
		//传入一个习题对象,并查找目录下的练习文件,然后进行批改,生成文件
		getAllName(anExercise.FileName);
		Integer[]Results = getResults(anExercise);
		Integer[]Answers = getAnswers(anExercise);
		evaluate(Answers,Results);
		String Addr_Name = anExercise.Addr+CheckingName;
		File file = new File(Addr_Name);
		
		if(!file.exists())
				file.createNewFile();
		writeCSVReport(file);
	}
	
	public void getAllName(String Name){
	//分解习题文件名称,便于找到练习文件名称和生成批改文件名称
		String type,count;
		int a,b,c;
		a = Name.indexOf("_");
		b = Name.indexOf("_",a+1);
		c = Name.indexOf("_",b+1);
		type = Name.substring(0,a);
		count = Name.substring(b+1,c);
		CheckingName = type+"_checking_"+count+"_.csv";
		PracticeName = type+"_practice_"+count+"_.csv";
	}
	
}
package ExerciseTest;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Random;

public class OperationBase{//算式基类
	static final int UPPER = 100;
	
	private BinaryOperation[][]AdditionBase;//加法算式基
	private BinaryOperation[][]SubstractBase;//减法算式基
	
	public void displayBase(BinaryOperation[][] base) {
	//测试方法,显示传进来的算式基的所有算式
		for(BinaryOperation[]ba:base) {
			for(BinaryOperation aa:ba) {
				if(aa!=null)
					System.out.print(aa.toString()+'\t');
			}
			System.out.println();
		}
	}
	
	public Exercise generationExercise(int count, BinaryOperation[][] Base) {
	//传入算式基,该算式基可以是加法算式基也可以是减法算式基,根据这个算式基随机生成算式并返回习题对象
		Exercise anExercise = new Exercise();
		BinaryOperation anOperation;
		Random random = new Random();
		int i, j;
		while(count>0) {
			do {
				i = random.nextInt(UPPER+1);
				j = random.nextInt(UPPER+1);
				anOperation = Base[i][j];
			}while(anOperation==null||anExercise.contains(anOperation));
			anExercise.Add(anOperation);
			count--;
		}
		return anExercise;
	}
	
	public Exercise generationExercise(int count,BinaryOperation[][]AddBase,BinaryOperation[][]SubBase) {
	//传入两个算式基,既加法和减法算式基,根据这两个算式基随机生成混合算式并返回习题对象
		Exercise anExercise = new Exercise();
		BinaryOperation anOperation;
		Random random = new Random();
		int i, j, ran;
		while(count>0) {
			ran = random.nextInt(2);
			switch(ran) {
			case 0:
				do {
					i = random.nextInt(UPPER+1);
					j = random.nextInt(UPPER+1);
					anOperation = AddBase[i][j];
				}while(anOperation==null||anExercise.contains(anOperation));
				anExercise.Add(anOperation);
				count--;
				break;
			case 1:
				do {
					i = random.nextInt(UPPER+1);
					j = random.nextInt(UPPER+1);
					anOperation = SubBase[i][j];
				}while(anOperation==null||anExercise.contains(anOperation));
				anExercise.Add(anOperation);
				count--;
				break;
			}
		}
		return anExercise;
	}
	//以下三个方法被直接调用,返回一个习题,并生成文件
	public Exercise generateAdditionExercise(int count) {
		//生成加法习题
		Exercise exercise;
		exercise = generationExercise(count,AdditionBase);
		exercise.FileName = "Addition_exercise_"+count+"_";
		return exercise;
	}
	
	public Exercise generateSubstractExercise(int count) {
		//生成减法习题
		Exercise exercise;
		exercise = generationExercise(count,SubstractBase);
		exercise.FileName = "Substract_exercise_"+count+"_";
		return exercise;
	}
	
	public Exercise generateBinaryExercise(int count) {
		//生成加法习题
		Exercise exercise;
		exercise = generationExercise(count,AdditionBase,SubstractBase);
		exercise.FileName = "MixOperation_exercise_"+count+"_";
		return exercise;
	}
	
	public OperationBase() throws Throwable {
		//构造函数,算式基对象实例化就判断算式基文件是否存在,若存在则直接读入,若不存在就生成
		File aFile = new File("d:/加减法练习/AdditionOperationBase.csv");
		File bFile = new File("d:/加减法练习/SubstractOperationBase.csv");
		if(aFile.exists()&&bFile.exists()) {
			readOperationBase(aFile, bFile);
			System.out.println("已从文件读入算式基");
		}
		else {
			writeOperationBase();
			System.out.println("已将算式基写入文件");
		}
	}
	public void readOperationBase(File aFile,File bFile) throws IOException {
		//读入算式基
		FileInputStream fisa = new FileInputStream(aFile);
		FileInputStream fisb = new FileInputStream(bFile);
		AdditionBase = new BinaryOperation[UPPER+1][UPPER+1];
		SubstractBase = new BinaryOperation[UPPER+1][UPPER+1];
		BinaryOperation op;
		String eqString = "";
		int b ;
		for(int i = 0;i<=UPPER;i++) {
			for(int j = 0;j<=UPPER-i;j++) {
				while(true) {
					b = fisa.read();
					if(b=='\r'||b=='\n')
						continue;
					if(b==',')
						break;
					else
						eqString+=(char)b;
				}
				op = Exercise.AddSubOperation(eqString);
				AdditionBase[i][j] = op;
				eqString = "";
			}
		}
		
		for(int i = 0;i<=UPPER;i++) {
			for(int j = 0;j<=i;j++) {
				while(true) {
					b = fisb.read();
					if(b=='\r'||b=='\n')
						continue;
					if(b==',')
						break;
					else
						eqString+=(char)b;
				}
				op = Exercise.AddSubOperation(eqString);
				SubstractBase[i][j] = op;
				eqString = "";
			}
		}
		fisa.close();
		fisb.close();
	}
	public void writeOperationBase() throws Throwable  {
		//生成算式基文件
		AdditionBase = new BinaryOperation[UPPER+1][UPPER+1];
		SubstractBase = new BinaryOperation[UPPER+1][UPPER+1];
		BinaryOperation op;
		File aFile = new File("d:/加减法练习/AdditionOperationBase.csv");
		File bFile = new File("d:/加减法练习/SubstractOperationBase.csv");
		if(!aFile.exists())
				aFile.createNewFile();
		FileWriter FW = new FileWriter(aFile,false);
		for(int i = 0;i<=UPPER;i++){
			for(int j = 0;j<=UPPER-i;j++) {
				op = new AdditionOperation();
				op.insert(i, j);
				AdditionBase[i][j] = op;
				FW.write(op.toString());
				FW.write(",");
			}
			FW.write("\r\n");
		}
		FW.close();
		
		op = new SubstractOperation();
		if(!bFile.exists())
				bFile.createNewFile();
		FW = new FileWriter(bFile,false);
		for(int i = 0;i<=UPPER;i++){
			for(int j = 0;j<=i;j++) {
				op = new SubstractOperation();
				op.insert(i, j);
				SubstractBase[i][j] = op;
				FW.write(op.toString());
				FW.write(",");
			}
			FW.write("\r\n");
		}
		FW.close();
		displayBase(AdditionBase);
		displayBase(SubstractBase);
	}
}
package GUITest;


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;

import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.GroupLayout.Alignment;
import javax.swing.border.EmptyBorder;

import ExerciseTest.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class PracticeGui extends JFrame {

	private static final long serialVersionUID = 6478286329988994564L;

	private JPanel contentPane;

	/**
	 * Launch the application.
	 */
	
	static final int WINDOW_WIDTH = 600;
	static final int WINDOW_HEIGHT = 500;
	static final int OP_AMOUNT = 20;
	static final int OP_COLUMN = 5;
	static final int OP_WIDTH = 65;
	static final int ANSWER_WIDTH = 35;
	static final int COMPONET_HEIGHT = 25;
	static final int STAT_WIDTH = 200;
	static final int STAT_HEIGHT = 100;
	
	private JTextField [] tfOp;
	private JTextField [] tfAns;
	private JTextArea taStat;
	
	private Exercise exercises;
	private int correctAmount;
	private int wrongAmount;
	private double accuracy;
	private double errorrate;
	private JButton btnNewButton;
	private JButton btnNewButton_1;
	
	private void judge() {
		BinaryOperation op;
		correctAmount = wrongAmount = 0;
		accuracy = errorrate = 0;
		for (int i = 0; i < OP_AMOUNT; i++) {
			op = exercises.getOperation(i);
			String result = String.valueOf(op.getvalue());
			String answer = tfAns[i].getText().trim();
			if (result.contentEquals(answer)) {
				tfAns[i].setBackground(Color.GREEN);
				correctAmount++;
			}
			else {
				tfAns[i].setBackground(Color.RED);
				wrongAmount++;
			}
		}
		accuracy = (correctAmount * 1.0 / OP_AMOUNT * 1.0) * 100.0;
		errorrate = (wrongAmount * 1.0 / OP_AMOUNT * 1.0) * 100.0;
		
		String ac = String.format("%.2f", accuracy);
		ac += '%';
		String er = String.format("%.2f", errorrate);
		er += '%';
		taStat.setText("统计信息:\n\n" + "总题数: " + OP_AMOUNT 
				+ "     正确题数 :" + correctAmount + "     错误题数: " + wrongAmount + '\n' 
				+ "                            正确率: " + ac + "        错误率: " + er);
	}
	
	private void initExerciseComponets() {
		exercises = new Exercise();
		exercises.generateAdditionExercise(OP_AMOUNT);
		
		tfOp = new JTextField[OP_AMOUNT];
		tfAns = new JTextField[OP_AMOUNT];
		for (int i = 0; i < OP_AMOUNT; i++) {
			tfOp[i] = new JTextField();
			tfOp[i].setBounds(20 + (i % OP_COLUMN) * (OP_WIDTH + ANSWER_WIDTH + 5),
					20 + (i / OP_COLUMN) * (COMPONET_HEIGHT + 10),
					OP_WIDTH,
					COMPONET_HEIGHT);
			tfOp[i].setHorizontalAlignment(JTextField.RIGHT);
			tfOp[i].setEditable(false);
			contentPane.add(tfOp[i]);
			
			tfAns[i] = new JTextField();
			tfAns[i].setBounds(20 + (i % OP_COLUMN) * (OP_WIDTH + ANSWER_WIDTH + 5) + OP_WIDTH,
					20 + (i / OP_COLUMN) * (COMPONET_HEIGHT + 10),
					ANSWER_WIDTH,
					COMPONET_HEIGHT);
			tfAns[i].setEditable(true);
			contentPane.add(tfAns[i]);
		}
		
		
		
		//按钮与统计信息文本域
		JButton button = new JButton("\u91CD\u65B0\u751F\u6210\u9898\u76EE");
		button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				exercises.generateAdditionExercise(OP_AMOUNT);
				updateExerciseComponets();
			}
		});
		
		JButton button_1 = new JButton("\u63D0\u4EA4\u7B54\u6848");
		button_1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				judge();
			}
		});
		
		taStat = new JTextArea();
		
		btnNewButton = new JButton("New button");
		contentPane.add(btnNewButton, BorderLayout.WEST);
		
		btnNewButton_1 = new JButton("New button");
		contentPane.add(btnNewButton_1, BorderLayout.EAST);
		GroupLayout gl_contentPane = new GroupLayout(contentPane);
		gl_contentPane.setHorizontalGroup(
			gl_contentPane.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_contentPane.createSequentialGroup()
					.addGap(46)
					.addGroup(gl_contentPane.createParallelGroup(Alignment.TRAILING, false)
						.addComponent(button_1, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
						.addComponent(button, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
					.addGap(47)
					.addComponent(taStat, GroupLayout.PREFERRED_SIZE, 330, GroupLayout.PREFERRED_SIZE)
					.addContainerGap(246, Short.MAX_VALUE))
		);
		gl_contentPane.setVerticalGroup(
			gl_contentPane.createParallelGroup(Alignment.TRAILING)
				.addGroup(gl_contentPane.createSequentialGroup()
					.addContainerGap(290, Short.MAX_VALUE)
					.addGroup(gl_contentPane.createParallelGroup(Alignment.TRAILING)
						.addComponent(taStat, GroupLayout.PREFERRED_SIZE, 97, GroupLayout.PREFERRED_SIZE)
						.addGroup(gl_contentPane.createSequentialGroup()
							.addComponent(button)
							.addGap(36)
							.addComponent(button_1)))
					.addGap(64))
		);
		contentPane.setLayout(gl_contentPane);
		
	}
	
	private void updateExerciseComponets() {
		BinaryOperation op;
		for (int i = 0; i < OP_AMOUNT; i++) {
			op = exercises.getOperation(i);
			tfOp[i].setText(op.toString());
			tfAns[i].setBackground(Color.WHITE);
			tfAns[i].setText(" ");
		}
		String ac = String.format("%.2f", accuracy);
		ac += '%';
		String er = String.format("%.2f", errorrate);
		er += '%';
		taStat.setText("统计信息:\n\n" + "总题数: " + OP_AMOUNT 
				+ "     正确题数 :" + correctAmount + "     错误题数: " + wrongAmount + '\n' 
				+ "                            正确率: " + ac + "        错误率: " + er);
		taStat.setEditable(false);
	}
	
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					PracticeGui frame = new PracticeGui();
					frame.setTitle("100以内的口算练习程序");
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public PracticeGui() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, WINDOW_WIDTH, WINDOW_HEIGHT);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		contentPane.setLayout(new BorderLayout(0, 0));
		setContentPane(contentPane);
		
		initExerciseComponets();
		updateExerciseComponets();
	}
}
package GUITest;

import java.awt.Color;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

import ExerciseTest.BinaryOperation;
import ExerciseTest.Exercise;
import ExerciseTest.ExerciseIOException;

import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JMenuBar;
import javax.swing.JButton;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JToolBar;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.JTextField;
import java.awt.event.ActionListener;
import java.io.File;
import java.awt.event.ActionEvent;
import javax.swing.JLabel;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFileChooser;

public class PracticeGui2 extends JFrame {

	private static final long serialVersionUID = -8069047189470765958L;
	private JPanel contentPane;
	private boolean submitted;//确定当前位置的题目是不是已经写了
	
	static final int WINDOW_WIDTH = 600;
	static final int WINDOW_HEIGHT = 500;
	static final int OP_AMOUNT = 20;
	static final int OP_COLUMN = 5;
	static final int OP_WIDTH = 65;
	static final int ANSWER_WIDTH = 35;
	static final int COMPONET_HEIGHT = 25;
	static final int STAT_WIDTH = 200;
	static final int STAT_HEIGHT = 100;
	//设置窗口大小和相关变量的位置
	
	private JTextField [] tfOp;//放算式的文本域
	private JTextField [] tfAns;//放答案的框
	
	private Exercise exercise;
	private int totalAmount;
	private int correctAmount;
	private int wrongAmount;
	private double accuracy;
	private double errorrate;
	private int currentPage;
	private int totalPages;
	
	JToolBar toolBar = new JToolBar();   //导入
	JToolBar toolBar_1 = new JToolBar(); //题目
	JToolBar toolBar_2 = new JToolBar(); // 翻页
	//三个工具栏,对应三个功能组合
	
	JButton button_7 = new JButton("\u4E0A\u4E00\u9875"); //上一页
	JButton button_8 = new JButton("\u4E0B\u4E00\u9875"); //下一页
	JMenuItem menuItem_5 = new JMenuItem("\u4E0A\u4E00\u9875"); //菜单上一页
	JMenuItem menuItem_6 = new JMenuItem("\u4E0B\u4E00\u9875"); //菜单下一页
	
	JLabel label = new JLabel("");
	
	JLabel lblNewLabel = new JLabel("New label");	//当前页数
	JLabel lblNewLabel_1 = new JLabel("New label"); //总页数
	
	JLabel lblNewLabel_3 = new JLabel("New label"); //状态栏
	JLabel lblNewLabel_4 = new JLabel("New label"); //答案状态栏
	
	private void reachBegin() {
		this.button_7.setEnabled(false);
		this.menuItem_5 .setEnabled(false);
		//一开始没有上一页,禁止点击上一页
	}
	private void reachEnd() {
		this.button_8.setEnabled(false);
		this.menuItem_6 .setEnabled(false);
		//到达最后一页后没有下一页,禁止点击下一页
	}
	private void leaveBegin() {
		this.button_7.setEnabled(true);
		this.menuItem_5 .setEnabled(true);
	}
	private void leaveEnd() {
		this.button_8.setEnabled(true);
		this.menuItem_6 .setEnabled(true);
	}
	//这两个方法用于离开最后一页或者离开第一页的时候,可以点击第一页或者最后一页,要解开禁止
	
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					PracticeGui2 frame = new PracticeGui2();//定义窗口对象
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}
	
	private void initComponets() {
		//加入一定数目的算式和答案
		this.submitted = false;
		exercise = new Exercise();
		exercise.generateAdditionExercise(OP_AMOUNT);
		
		this.currentPage = 1;
		this.totalPages = 1;
		this.reachBegin();
		this.reachEnd();
		
		tfOp = new JTextField[OP_AMOUNT];
		tfAns = new JTextField[OP_AMOUNT];
		//生成对应数目的算式位置和答案位置
		
		for (int i = 0; i < OP_AMOUNT; i++) {
			//循环加入算式和答案,配对加入
			tfOp[i] = new JTextField();
			tfOp[i].setBounds(20 + (i % OP_COLUMN) * (OP_WIDTH + ANSWER_WIDTH + 5),
					50 + (i / OP_COLUMN) * (COMPONET_HEIGHT + 10),
					OP_WIDTH,COMPONET_HEIGHT);
			//设置算式框的位置和大小,位置遵循一定的规律
			tfOp[i].setHorizontalAlignment(JTextField.RIGHT);
			//设置算式框里面的算式为右对齐
			tfOp[i].setEditable(false);//算式位置是不可更改的
			contentPane.add(tfOp[i]);
			
			tfAns[i] = new JTextField();
			tfAns[i].setBounds(20 + (i % OP_COLUMN) * (OP_WIDTH + ANSWER_WIDTH + 5) + OP_WIDTH,
					50 + (i / OP_COLUMN) * (COMPONET_HEIGHT + 10),
					ANSWER_WIDTH,
					COMPONET_HEIGHT);
			tfAns[i].setEditable(true);
			contentPane.add(tfAns[i]);
			//答案框的加入和算式框相同
		}
	}
	
	private void updateComponets() {
		//显示题目和答案框以及其对应格式
		this.totalPages = exercise.length() / OP_AMOUNT;
		this.lblNewLabel.setText("第   " + String.valueOf(this.currentPage) + "   页");
		this.lblNewLabel_1.setText("共  " + String.valueOf(this.totalPages) + "   页");
		//设置页数标签
		
		if (this.currentPage == 1) 
			this.reachBegin();
		else 
			this.leaveBegin();
		
		if (this.currentPage == this.totalPages) 
			this.reachEnd();
		else 
			this.leaveEnd();
		//设置当前页到第一页或者最后一页的时候点击权限
		
		BinaryOperation op;
		for (int i = 0; i < OP_AMOUNT; i++) {
			op = exercise.getOperation((currentPage - 1) * OP_AMOUNT + i);
			tfOp[i].setText(op.toString());
			//获得已经生成的算式中的算式并加入到文本域中
			
			if(!submitted) {
				tfAns[i].setBackground(Color.WHITE);
				//没写东西的时候答案框设置为白色
			}
			else {
				if(exercise.getJudgement((currentPage - 1) * OP_AMOUNT + i))
					tfAns[i].setBackground(Color.GREEN);
				else
					tfAns[i].setBackground(Color.RED);
				//已经提交了的话就根据答案是否正确,将答案框设置为不同的颜色
			}
			tfAns[i].setText(exercise.getAnswer((currentPage - 1) * OP_AMOUNT + i));
		}
		
		String s = new String();
		
		if(!submitted ) {
			s = "点击【提交】后可获取";
		}
		else {
			//计算正确率等一系列量
			totalAmount = exercise.length();
			correctAmount = exercise.Correct();
			wrongAmount = totalAmount - correctAmount;
			accuracy = (correctAmount * 1.0 / totalAmount * 1.0) * 100.0;
			errorrate = (wrongAmount * 1.0 / totalAmount * 1.0) * 100.0;
			
			String co = String.format("%d", correctAmount);
			String wr = String.format("%d", wrongAmount);
			String ac = String.format("%.2f", accuracy);
			ac += '%';
			String er = String.format("%.2f", errorrate);
			er += '%';
			s = "正确题数 : " + co + "   " + "错误题数 : " + wr + "   " + 
					"正确率  : " + ac + "   " + "错误率 : " + er;
		}
		
		lblNewLabel_3.setText("状态:  " 
				+ "题目类型 - " + exercise.getExerciseType()
				+ "     "
				+ "题目数量 - " + exercise.length());
		lblNewLabel_4.setText(s);
	}
	
	private void impExercise() {	
		//导入题目
		JFileChooser jfc = new JFileChooser();//新建一个文件选择器
		jfc.showOpenDialog(null);//设置参数的值可以改变文件选择器在屏幕上的弹出位置
		
		File file = jfc.getSelectedFile();
		try {
			exercise = Exercise.loadObject(file.getAbsolutePath());
			JOptionPane.showMessageDialog(null, "导入题目成功!"
					,"提示",JOptionPane.INFORMATION_MESSAGE);
			this.submitted = false;
			updateComponets();
		}catch(NullPointerException npe) {
			
		}catch(ExerciseIOException e) {
			JOptionPane.showMessageDialog(null, "导入题目失败,可能是因为选择了错误的文件",
					"错误",JOptionPane.ERROR_MESSAGE);
		}
	}
	
	private void expExercise() {	
		//导出题目
		JFileChooser jfc = new JFileChooser();
		jfc.showOpenDialog(null);
		File file = jfc.getSelectedFile();
		try {
			exercise.saveObject(file.getAbsolutePath(), exercise);
			//把这一道题目导出到文件里面
			JOptionPane.showMessageDialog(null, "导出题目成功!"
					,"提示",JOptionPane.INFORMATION_MESSAGE);
		}catch(NullPointerException npe) {
			
		}catch(ExerciseIOException e) {
			JOptionPane.showMessageDialog(null, "导出题目失败,可能是因为选择了错误的文件",
					"错误",JOptionPane.ERROR_MESSAGE);
		}
	}
	//导入导出题目用的都是JFileChooser对象,用这个对象来获得目标路径,之后用file对象进行导入导出
	
	private void prePage() {	//上翻一页
		getAnswers(this.currentPage);
		//上下翻页的时候,先把当前页的内容存下来
		if(this.currentPage == this.totalPages) 
			this.leaveEnd();
		if(--currentPage == 1) 
			this.reachBegin();
		//调整页数之后对页数上下翻页的限制
		this.lblNewLabel.setText(String.valueOf(currentPage));
		updateComponets();
	}
	private void nextPage() {	//下翻一页
		getAnswers(this.currentPage);
		if(this.currentPage == this.totalPages)
			this.leaveEnd();
		if(++currentPage == totalPages) 
			this.reachEnd();
		this.lblNewLabel.setText(String.valueOf(currentPage));
		updateComponets();
	}
	
	private void getAnswers(int pageIndex) { //获取答案
		for (int i = 0; i < OP_AMOUNT; i++) {
			exercise.setAnswer((pageIndex - 1) * OP_AMOUNT + i, tfAns[i].getText());
		}
	}
	
	private void generateExercise() {	//重新生成题目
		int length = exercise.length();
		exercise.generateWithFormerType(length);
		//通过两次调用方法,更新题目对象,实现重新生成题目的功能
		updateComponets();
	}
	
	private void judgeAnswer() {
		this.submitted = true;
		getAnswers(this.currentPage);
		updateComponets();//把目前做的题目进行批改,更新答案框的颜色
	}
	
	private void clearAnswers() {
		exercise.clearAnswers();
		this.submitted = false;
		updateComponets();
		//把答案清空,提交状态改为未提交
	}
	
	public PracticeGui2() {
		//可视化窗口编辑GUI界面,添加对应的动作监听
		setTitle("100\u4EE5\u5185\u7684\u53E3\u7B97\u7EC3\u4E60\u7A0B\u5E8F");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 570, 376);
		
		JMenuBar menuBar = new JMenuBar();
		setJMenuBar(menuBar);
		
		JMenu menu = new JMenu("\u6587\u4EF6");
		menuBar.add(menu);
		
		JMenuItem menuItem = new JMenuItem("\u5BFC\u5165");
		menu.add(menuItem);
		
		menuItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				impExercise();
			}
		});
		
		JMenuItem menuItem_1 = new JMenuItem("\u5BFC\u51FA");
		menu.add(menuItem_1);
		
		menuItem_1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				expExercise();
			}
		});
		
		JMenu menu_1 = new JMenu("\u9898\u76EE\u8BBE\u7F6E");
		menuBar.add(menu_1);
		
		JMenu menuItem_7 = new JMenu("\u6839\u636E\u7C7B\u578B\u751F\u6210");
		menu_1.add(menuItem_7);
		
		JCheckBoxMenuItem chckbxmntmadd = new JCheckBoxMenuItem("\u52A0\u6CD5\u9898\u76EE");
		menuItem_7.add(chckbxmntmadd);
		chckbxmntmadd.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				int length = exercise.length();
				exercise.generateAdditionExercise(length);
				updateComponets();
			}
		});
		
		JCheckBoxMenuItem chckbxmntmsub = new JCheckBoxMenuItem("\u51CF\u6CD5\u9898\u76EE");
		menuItem_7.add(chckbxmntmsub);
		
		chckbxmntmsub.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				int length = exercise.length();
				exercise.generateSubstractExercise(length);
				updateComponets();
			}
		});
		
		JCheckBoxMenuItem chckbxmntmas = new JCheckBoxMenuItem("\u52A0\u51CF\u6DF7\u5408");
		menuItem_7.add(chckbxmntmas);
		
		chckbxmntmas.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				int length = exercise.length();
				exercise.generateBinaryExercise(length);
				updateComponets();
			}
		});
		
		JMenu menuItem_8 = new JMenu("\u6839\u636E\u6570\u91CF\u751F\u6210");
		menu_1.add(menuItem_8);
		
		JCheckBoxMenuItem checkBoxMenuItem_3 = new JCheckBoxMenuItem("20");
		menuItem_8.add(checkBoxMenuItem_3);
		
		checkBoxMenuItem_3.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				exercise.generateWithFormerType(20);
				updateComponets();
			}
		});
		
		JCheckBoxMenuItem checkBoxMenuItem_4 = new JCheckBoxMenuItem("40");
		menuItem_8.add(checkBoxMenuItem_4);
		
		checkBoxMenuItem_4.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				exercise.generateWithFormerType(40);
				updateComponets();
			}
		});
		
		JCheckBoxMenuItem checkBoxMenuItem_5 = new JCheckBoxMenuItem("100");
		menuItem_8.add(checkBoxMenuItem_5);
		
		checkBoxMenuItem_5.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				exercise.generateWithFormerType(100);
				updateComponets();
			}
		});
		
		JMenu menu_2 = new JMenu("\u9898\u76EE\u64CD\u4F5C");
		menuBar.add(menu_2);
		
		JMenuItem menuItem_2 = new JMenuItem("\u91CD\u65B0\u751F\u6210");
		menu_2.add(menuItem_2);
		
		menuItem_2.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				generateExercise();
				clearAnswers();
			}
		});
		
		JMenuItem menuItem_3 = new JMenuItem("\u6E05\u7A7A");
		menu_2.add(menuItem_3);
		
		menuItem_3.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				clearAnswers();
			}
		});
		
		JMenuItem menuItem_4 = new JMenuItem("\u63D0\u4EA4");
		menu_2.add(menuItem_4);
		
		menuItem_4.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				judgeAnswer();
			}
		});
		
		JMenu menu_3 = new JMenu("\u67E5\u770B");
		menuBar.add(menu_3);
		
		
		menu_3.add(menuItem_5);
		
		menuItem_5.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				prePage();
			}
			
		});
		
		menu_3.add(menuItem_6);
		
		menuItem_6.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				nextPage();
			}
			
		});
		
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		
		JLabel lblNewLabel_2 = new JLabel("New label");
		
		lblNewLabel_2.setText("------------------------------------------"
				+ "------------------------------------------"
				+ "-----------------------------------------------------");

		GroupLayout gl_contentPane = new GroupLayout(contentPane);
		gl_contentPane.setHorizontalGroup(
			gl_contentPane.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_contentPane.createSequentialGroup()
					.addGroup(gl_contentPane.createParallelGroup(Alignment.LEADING)
						.addGroup(gl_contentPane.createSequentialGroup()
							.addComponent(toolBar, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
							.addPreferredGap(ComponentPlacement.RELATED)
							.addComponent(toolBar_1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
							.addPreferredGap(ComponentPlacement.RELATED)
							.addComponent(toolBar_2, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
						.addGroup(gl_contentPane.createSequentialGroup()
							.addGap(137)
							.addGroup(gl_contentPane.createParallelGroup(Alignment.LEADING)
								.addGroup(gl_contentPane.createSequentialGroup()
									.addGap(63)
									.addComponent(lblNewLabel)
									.addGap(42)
									.addComponent(lblNewLabel_1))
								.addComponent(label)))
						.addComponent(lblNewLabel_2)
						.addGroup(gl_contentPane.createSequentialGroup()
							.addContainerGap()
							.addComponent(lblNewLabel_3))
						.addGroup(gl_contentPane.createSequentialGroup()
							.addContainerGap()
							.addComponent(lblNewLabel_4)))
					.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
		);
		gl_contentPane.setVerticalGroup(
			gl_contentPane.createParallelGroup(Alignment.TRAILING)
				.addGroup(gl_contentPane.createSequentialGroup()
					.addGroup(gl_contentPane.createParallelGroup(Alignment.LEADING)
						.addComponent(toolBar, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
						.addComponent(toolBar_1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
						.addComponent(toolBar_2, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
					.addPreferredGap(ComponentPlacement.RELATED, 169, Short.MAX_VALUE)
					.addComponent(label)
					.addGap(13)
					.addGroup(gl_contentPane.createParallelGroup(Alignment.BASELINE)
						.addComponent(lblNewLabel_1)
						.addComponent(lblNewLabel))
					.addPreferredGap(ComponentPlacement.RELATED)
					.addComponent(lblNewLabel_2)
					.addPreferredGap(ComponentPlacement.RELATED)
					.addComponent(lblNewLabel_3)
					.addPreferredGap(ComponentPlacement.UNRELATED)
					.addComponent(lblNewLabel_4)
					.addGap(19))
		);
		
		
		button_7.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				prePage();
			}
		});
		
		toolBar_2.add(button_7);
		
		button_8.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				nextPage();
			}
		});
		toolBar_2.add(button_8);
		
		JButton button_4 = new JButton("\u91CD\u65B0\u751F\u6210");
		button_4.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				generateExercise();
				clearAnswers();
			}
		});
		toolBar_1.add(button_4);
		
		JButton button = new JButton("\u6E05\u7A7A");
		button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				clearAnswers();
			}
		});
		toolBar_1.add(button);
		
		JButton button_6 = new JButton("\u63D0\u4EA4");
		button_6.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				judgeAnswer();
			}
		});
		toolBar_1.add(button_6);
		
		JButton button_2 = new JButton("\u5BFC\u5165");
		button_2.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				impExercise();
			}
		});
		toolBar.add(button_2);
		
		JButton button_3 = new JButton("\u5BFC\u51FA");
		button_3.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				expExercise();
			}
		});
		toolBar.add(button_3);
		contentPane.setLayout(gl_contentPane);
		
		initComponets();
		updateComponets();
	}
}

你可能感兴趣的:(杂项)