java编程实现素数环_结对编程(JAVA实现)

项目成员:黄思扬(3117004657)、刘嘉媚(3217004685)

二、PSP表格

PSPPersonal Software Process Stages预估耗时(分钟)实际耗时(分钟)

Planning

计划

60

40

· Estimate

· 估计这个任务需要多少时间

60

40

Development

开发

1440

1505

· Analysis

· 需求分析

30

15

· Design Spec

· 生成设计文档

20

15

· Design Review

· 设计复审

30

15

· Coding Standard

· 代码规范

20

20

· Design

· 具体设计

80

80

· Coding

· 具体编码

900

980

· Code Review

· 代码复审

30

30

· Test

· 测试(自我测试,修改代码,提交修改)

330

400

Reporting

报告

130

100

· Test Report

· 测试报告

80

60

· Size Measurement

· 计算工作量

30

20

· Postmortem & Process Improvement Plan

· 事后总结, 并提出过程改进计划

30

20

合计

1630

1695

三、效能分析

由于之前采用单线程执行,在文件IO流的处理上花费了不少的时间,包括代码上的执行存在部分冗余,代码上可以提高利用率。打开了线程池以后,多线程执行,大大提高了执行速度,在代码逻辑改进优化后,对大量生成题目的效果十分显著,由30s时间完成优化到2s:

8b0717ebc7f92e93b849a97598baacdc.png

0ede7605ffed6023aabfda4e8816fd77.png

四、设计过程

(一)流程图

视图设计过程:

d105a2b8f4f2f34b7ba48aa2f68758c3.png

生成题目设计过程:

29e92eec130d8064369b9c01e1c3c107.png

判断对错设计过程:

e060882d08c7264e7718216b05e07285.png

(二)项目目录:

b89952a5bc6f8d670d2f06d81e68a0ae.png

分包思路:

1)视图层:view 包含主页面与两个功能页面

2)实体类:po  包含题目存放类Deposit、ChildDeposit,分数处理类

3)逻辑处理层:service  处理题目生成等的逻辑、处理题目判错的逻辑

4)工具类:util 包含文件的读写功能

(三)总体实现思路

程序运行,进入主页面,点击选择进入相应功能页面(生成题目or判断对错),如果为生成题目,用户需要输入相关参数(题目数量、数的大小范围),视图层获取输入的数据,传入至逻辑层中进行处理,先判断输入是否有误,有误则终止程序,无误则调用题目生成的方法CreateAth;如果为判断对错,用户需要选择相应的文件(Exersises.txt和Answers.txt),视图层获取输入的数据,传入到逻辑层进行处理,判断输入无误后,调用题目判错的方法Judge。

题目生成的思路:题目要求生成的算术运算符少于3个,先随机生成一个运算符的个数,传入到CreateAth方法中,先生成一个根结点即算术运算符,然后随机生成在左右子树小于总运算符个数的运算符个数,同时生成运算符,当生成运算符个数为0,则生成叶子结点即运算操作数,左右子树也是重复上述过程。把生成的算式放在一个动态数组里面,每当生成一个算式,就去检查里面是否包含这个算式,如果重复就去掉,达到查重的目的。

判断对错的思路:使用readfile读取Exersises.txt文件内容,使用正则表达式分割开题目的序号和算式,算式是中缀表达式的表示方式,通过build方法把算式改为前缀表达式,如:1 + (( 2 + 3)* 4 ) – 5,转换成前缀则为- + 1 * + 2 3 4 5,计算其答案,读取Answers.txt的内容,使用正则表达式分割开题目的序号和答案,根据两个文件的序号,对比答案是否相同,如果相同则记录对的题目的数量,和题目序号,写出到Correction.txt文件。

(四)细节实现思路

1)如何保证基本的数值运算,确定参数的范围?

自然数的数值之间的运算可简单实现,但是自然数、真分数、带分数之间的运算之间的格式需要自己设计的,并且题目要求“如果存在形如e1÷ e2的子表达式,那么其结果应是真分数”,经过讨论之后,决定把所有数据统一当成分数来处理,整数的分母则为1,在运算的过程中把分子与分母独立出来分别操作加减乘除运算,到最后再进行约分等化简处理。

2)怎么生成算式并且查重?

生成的算式要求不能产生负数、生成的题目不能重复,且即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目,经过讨论,决定使用二叉树来实现,由于二叉树的运算次序是孩子结点的运算次序要优先于根结点的,所以使用非叶子节点存放运算符,叶子结点存放数值,可以解决前后符号之间的优先级别关系,解决括号的添加问题,当父母结点的算术符优先级高于右孩子结点的算术运算符时,左右都要加括号,当相等时,则右孩子树要加括号;出现了负数时,交换左右子树即可;此外,解决了查重的复杂度问题,开始的方案想采用遍历的方式来达到查重,现只需要判断两棵树是否相同即可。

五、程序关键代码

从页面获取到数据,进行处理:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packageservice;importjava.util.HashMap;importjava.util.Map;public classEntryJudge{public booleanEntry(String[] args){//向主页面返回的运行成功与否的标志

boolean tag = false;//判断用户输入是否正确

if(args.length == 0 || args.length % 2 != 0) {

tag= false;returntag;

}//取出参数

Map params =checkParams(args);//执行相应处理

CreateAth opera = newCreateAth(params);

Judge check= newJudge(params);if(params.containsKey("-e")&&params.containsKey("-a")){

check.Judge();

tag= true;returntag;

}else if(params.containsKey("-n") || params.containsKey("-r") || params.containsKey("-d")) {

opera.createAth();

tag= true;returntag;

}returntag;

}private MapcheckParams(String[] args) {

Map params = new HashMap<>();for (int i = 0; i < args.length; i = i + 2) {

params.put(args[i], args[i+1]);

}returnparams;

}

}

EntryJudge

题目生成逻辑处理:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packageservice;importcom.sun.org.apache.xalan.internal.xsltc.compiler.util.StringStack;importpo.Deposit;importpo.Fraction;importutil.FileUtil;importpo.ChildDeposit;importjava.util.ArrayList;importjava.util.List;importjava.util.Map;importjava.util.Stack;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.ThreadLocalRandom;importjava.util.concurrent.TimeUnit;/*** 生成题目类*/

public classCreateAth{private int maxNum = 100; //生成题目的整数最大值

private int denArea = 20; //分母的范围

private int maxCount = 10;//生成题目数量

privateDeposit content;private static final String[] SYMBOLS = newString[]{"+", "-", "x", "\u00F7"};/*** 生成随机题目,初始化,把主类中输入的参数内容调进来*/

public CreateAth(Mapparams) {for(String str : params.keySet()) {if (str.equals("-n")) {

maxCount=Integer.valueOf(params.get(str));

}else if (str.equals("-r")) {

maxNum=Integer.valueOf(params.get(str));

}else if (str.equals("-d")) {

denArea=Integer.valueOf(params.get(str));

}

}

}/*** 生成题目*/

private ExecutorService executor =Executors.newCachedThreadPool();public voidcreateAth() {

StringBuilder exercises= newStringBuilder();

StringBuilder answers= newStringBuilder();

List list = new ArrayList<>();long start =System.currentTimeMillis();for (int i = 1; i <=maxCount;) {

CreateAth generate= new CreateAth(true);if (!list.contains(generate)){

String[] strs= generate.print().split("=");

exercises.append(i).append(". ").append(strs[0]).append("\n");

answers.append(i).append(".").append(strs[1]).append("\n");

list.add(generate);

i++;

}

}

executor.execute(()-> FileUtil.writeFile(exercises.toString(), "Exercises.txt"));

executor.execute(()-> FileUtil.writeFile(answers.toString(), "Answers.txt"));

executor.shutdown();long end =System.currentTimeMillis();try{boolean loop = true;while(loop) {

loop= !executor.awaitTermination(30, TimeUnit.SECONDS); //超时等待阻塞,直到线程池里所有任务结束

} //等待所有任务完成

System.out.println("生成的" + maxCount + "道题和答案存放在当前目录下的Exercises.txt和Answers.txt,耗时为:"+(end - start) + "ms");

}catch(InterruptedException e) {

e.printStackTrace();

}

}

——————以下是生成题目所调用到的方法———————————/*** 生成组成题目随机数

* area:分母的范围*/

private int random(intarea) {

ThreadLocalRandom random=ThreadLocalRandom.current();int x =random.nextInt(area);if (x == 0) x = 1;returnx;

}/*** ThreadLocalRandom类在多线程环境中生成随机数。

* nextBoolean() 方法用于从随机数生成器的序列返回下一个伪随机的,均匀分布的布尔值*/

private booleanrandomBoolean() {

ThreadLocalRandom random=ThreadLocalRandom.current();returnrandom.nextBoolean();

}/*** 把生成的每个数进行处理得出分子分母*/

privateFraction creator() {if(randomBoolean()) {return new Fraction((random(maxNum)), 1);

}else{if(randomBoolean()) {int den =random(denArea);int mol = random(den *maxNum);return newFraction(den, mol);

}else{int den =random(denArea);return newFraction(random(den), den);

}

}

}/*** 单步计算

*@paramsymbol 符号

*@paramleft 左

*@paramright 右

*@return得出来结果后经过约分的分数*/

privateFraction calculate(String symbol, Fraction left, Fraction right) {switch(symbol) {case "+":returnleft.add(right);case "-":returnleft.subtract(right);case "x":returnleft.multiply(right);default:returnleft.divide(right);

}

}/*** 随机生成一道四则运算题目

*@paramfractionNum 运算符个数

*@return二叉树*/

private Deposit build(intfractionNum){if(fractionNum == 0){return new Deposit(creator(),null,null);

}

ThreadLocalRandom random=ThreadLocalRandom.current();

ChildDeposit node= new ChildDeposit(SYMBOLS [random.nextInt(4)],null, null);//左子树运算符数量

int left =random.nextInt(fractionNum);//右子树运算符数量

int right = fractionNum - left - 1;

node.setLeft(build(left));

node.setRight(build(right));

Fraction value=calculate(node.getSymbol(),node.getLeft().getValue(),node.getRight().getValue());//负数处理

if(value.Negative()){//交换左右子树,就是交换两个减数的顺序

if (node != null) {

Deposit swap=node.getLeft();

node.setLeft(node.getRight());

node.setRight(swap);

}

value=calculate(node.getSymbol(),node.getLeft().getValue(),node.getRight().getValue());

}

node.setValue(value);returnnode;

}/*** 获取表达式,

* 打印题目与答案*/

privateString print(){return print(content) + " = " +content.getValue();

}privateString print(Deposit node){if (node == null){return "";

}

String frac=node.toString();

String left=print(node.getLeft());if (node.getLeft() instanceof ChildDeposit && node instanceofChildDeposit) {if(bracketsLeft(((ChildDeposit) node.getLeft()).getSymbol(), ((ChildDeposit) node).getSymbol())) {

left= "(" + " " + left + " " + ")";

}

}

String right=print(node.getRight());if (node.getRight() instanceof ChildDeposit && node instanceofChildDeposit) {if(bracketsRight(((ChildDeposit) node.getRight()).getSymbol(), ((ChildDeposit) node).getSymbol())) {

right= "(" + " " + right + " " + ")";

}

}return left + frac +right;

}/*** 比较两个符号谁优先级更高,子树的箱号优先级低要加括号,左括号or右括号*/

private booleanbracketsLeft(String left,String mid){return (left.equals("+")|| left.equals("-")) && (mid.equals("x")||mid.equals("\u00F7"));

}private booleanbracketsRight(String right, String mid){return (right.equals("+")|| right.equals("-")) && (mid.equals("x")||mid.equals("\u00F7"))||(mid.equals("\u00F7"))||(mid.equals("-")&&(mid.equals("+")|| mid.equals("-")));

}/***生成一个题目,先调用下面的createAth方法来判断有没有生成一个用build方法生成的树*/CreateAth(booleanisBuild){if(isBuild){

ThreadLocalRandom random=ThreadLocalRandom.current();int kind = random.nextInt(4);if (kind == 0) kind = 1;

content=build(kind);while(content.getValue().Zero()){

content=build(kind);

}

}

}/*** 查重*/@Overridepublic booleanequals(Object o) {if (this == o) return true;if (!(o instanceof CreateAth)) return false;

CreateAth exercise=(CreateAth) o;returncontent.equals(exercise.content);

}

Fraction getResult() {returncontent.getValue();

}

——————以下是判断题目所要调用到的方法———————————/*** 中缀表达式生成树,用栈的特点,把中缀表达式变成前缀表达式

* 在判错中调用

*@paramexercise 中缀表达式

*@return二叉树*/Deposit build(String exercise) {

String[] strs= exercise.trim().split(" "); //拿走标号

Stack depositStack = new Stack<>(); //结点栈

StringStack symbolStack = new StringStack(); //符号栈//中缀表达式转换成前缀表达式,然后再用前序遍历生成数

for (int i = strs.length - 1; i >= 0; i--) {

String str=strs[i];if (!str.matches("[()+\\u00F7\\-x]")) {

depositStack.push(new Deposit(newFraction(str)));

}else{//符号结点

while (!symbolStack.empty() && ((symbolStack.peekString().equals("x") ||symbolStack.peekString().equals("\u00F7"))&& (str.equals("+") || str.equals("-"))|| str.equals("("))) {

String symbol=symbolStack.popString();if (symbol.equals(")")) {break;

}

push(symbol, depositStack);

}if (str.equals("(")) {continue;

}

symbolStack.pushString(str);

}

}while (!symbolStack.empty()) {

push(symbolStack.popString(), depositStack);

}this.content =depositStack.pop();returncontent;

}/*** 将符号压入节点栈且计算结果,仅在生成前缀表达式*/

private void push(String symbol, StacknodeStack) {

Deposit left=nodeStack.pop();

Deposit right=nodeStack.pop();

ChildDeposit node= newChildDeposit(symbol, left, right);

node.setValue(calculate(symbol, left.getValue(), right.getValue()));

nodeStack.push(node);

}

}

CreateAth

题目判错处理:判断答案的正确性,并记录下来正确题目与错误题目序号,打印到Grade.txt

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packageservice;importpo.Fraction;importutil.FileUtil;importjava.util.ArrayList;importjava.util.List;importjava.util.Map;/*** 答案判错类*/

public classJudge{private int trueNum; //正确数目

private int wrongNum; //错误数目

private String exerciseFileName; //题目文件名

private String answerFileName; //答案文件名

public Judge(Mapparams) {for(String str : params.keySet()) {if (str.equals("-e")) {

exerciseFileName=params.get(str);

}else if (str.equals("-a")) {

answerFileName=params.get(str);

}

}

}/*** 判断错误 ,并把错误写入文件*/

public voidJudge() {long start =System.currentTimeMillis();

List correctNums = new ArrayList<>();

List wrongNums = new ArrayList<>();

FileUtil.readFile((exercise, answer)->{

String[] strs1= exercise.split("\\."); //匹配每一行

String[] strs2 = answer.split("\\.");if (strs1[0].equals(strs2[0])) {

CreateAth exes= new CreateAth(false);

exes.build(strs1[1].trim()); //去掉两端的空格后,将后缀表达式生成树变成前缀的,

if (exes.getResult().equals(new Fraction(strs2[1].trim()))) { //答案两边都相等,继续执行下面的

correctNums.add(strs1[0]);

trueNum++;

}else{

wrongNums.add(strs1[0]);

wrongNum++;

}

}

}, exerciseFileName, answerFileName);

FileUtil.writeFile(printResult(correctNums, wrongNums),"Correction.txt");long end =System.currentTimeMillis();

System.out.println("题目答案对错统计存在当前目录下的Correction.txt文件下,耗时为:" + (end - start) + "ms");

}private String printResult(List correctNums, ListwrongNums) {

StringBuilder builder= newStringBuilder();

builder.append("Correct: ").append(trueNum).append(" (");for (int i = 0; i < correctNums.size(); i++) {if (i == correctNums.size() - 1) {

builder.append(correctNums.get(i));break;

}

builder.append(correctNums.get(i)).append(", ");

}

builder.append(")").append("\n");

builder.append("Wrong: ").append(wrongNum).append(" (");for (int i = 0; i < wrongNums.size(); i++) {if (i == wrongNums.size() - 1) {

builder.append(wrongNums.get(i));break;

}

builder.append(wrongNums.get(i)).append(", ");

}

builder.append(")").append("\n");returnbuilder.toString();

}

}

Judge

分数处理类:把所有随机生成的数都当成是分数处理,同时在些定义分数的四则运算方法

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packagepo;/*** 1. 把所有随机生成的数都当成是分数处理(解决了自然整数,分数,带分数之间的差异)

* 2. 定义了分数的四则运算类*/

public classFraction{private int mol; //分子

private int den; //分母

/*** 处理随机生成的数值(约分等),组合分数对象*/

public Fraction(int mol, intden) {this.mol =mol;this.den =den;if (den <= 0) {throw new RuntimeException("分数分母不能为0");

}//否则就进行约分

int mod = 1;int max = den > mol ?den : mol;for (int i = 1; i <= max; i++) {if (mol % i == 0 && den % i == 0) {

mod=i;

}

}this.mol = mol /mod;this.den = den /mod;

}/*** 处理随机生成的数值,这个用于分解分数对象(仅在判错中使用)*/

publicFraction(String str) {int a = str.indexOf("'");int b = str.indexOf("/");if (a != -1) {//取出数组,转换类型

int c = Integer.valueOf(str.substring(0, a));

den= Integer.valueOf(str.substring(b + 1));

mol= c * den + Integer.valueOf(str.substring(a + 1, b));

}else if (b != -1) {

String[] sirs= str.split("/");

mol= Integer.valueOf(sirs[0]);

den= Integer.valueOf(sirs[1]);

}else{

mol=Integer.valueOf(str);

den= 1;

}

}/*** 定义加减乘除类,返回值类型(全都当成分数处理),由于要返回这个类的内容,所以方法前要加类名*/

publicFraction add(Fraction fraction) {return new Fraction(this.mol * fraction.den + this.den * fraction.mol, this.den *fraction.den);

}publicFraction subtract(Fraction fraction) {return new Fraction(this.mol * fraction.den - this.den * fraction.mol, this.den *fraction.den);

}publicFraction multiply(Fraction fraction) {return new Fraction(this.mol * fraction.mol, this.den *fraction.den);

}publicFraction divide(Fraction fraction) {return new Fraction(this.mol * fraction.den, this.den *fraction.mol);

}

}

Fraction

题目实现存放类以及其子类:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packagepo;importjava.util.Objects;/*** 用于存放题目的类,用二叉树的形式*/

public classDeposit{privateDeposit left;privateDeposit right;private Fraction value; //用于二叉树结点的是符号与运算结果数值的之间的变化

publicDeposit(Fraction value, Deposit left, Deposit right){this.value =value;this.left =left;this.right =right;

}/*** 取结点数据*/

publicFraction getValue() {returnvalue;

}publicDeposit getRight(){returnright;

}publicDeposit getLeft(){returnleft;

}/*** 设置结点数据*/

publicDeposit(Fraction value){this.value =value;

}public voidsetLeft(Deposit left){this.left =left;

}public voidsetRight(Deposit right){this.right =right ;

}public voidsetValue(Fraction value) {this.value =value;

}

@OverridepublicString toString() {returnvalue.toString();

}/*** 用于查重,判断二棵树是否相同*/@Overridepublic booleanequals(Object o) {if (this == o) return true;if (!(o instanceof Deposit)) return false;

Deposit node=(Deposit) o;return Objects.equals(value, node.value) &&Objects.equals(left, node.left)&&Objects.equals(right, node.right);

}

}

—————————————————————————————————————分割线——————————————————————————————————————————————packagepo;/*** 用于记录符号结点,与Deposit类是一样的道理*/

public class ChildDeposit extendsDeposit{privateString symbol;publicChildDeposit(String symbol, Deposit left, Deposit right){super(null, left, right);this.symbol =symbol;

}publicString getSymbol() {returnsymbol;

}

@OverridepublicString toString() {return " " + symbol + " ";

}/*** 用于查重*/@Overridepublic booleanequals(Object o) {if (this == o) return true;if (!(o instanceof ChildDeposit)) return false;

ChildDeposit that=(ChildDeposit) o;boolean flag = this.symbol != null &&symbol.equals(that.symbol);if(!flag) return false;boolean left = this.getLeft() != null &&getLeft().equals(that.getLeft());boolean right = this.getRight() != null &&getRight().equals(that.getRight());//左右子树相同

if(left &&right) {return true;

}if(left ^right) {return false;

}//如果是加法或乘法由于满足交换律所以要判断

if(this.symbol.equals("+") || this.symbol.equals("x")) {

left= this.getLeft() != null &&getLeft().equals(that.getRight());

right= this.getRight() != null &&getRight().equals(that.getLeft());

}return left &&right;

}

}

Deposit,ChildDeposit

文件读写工具类:处理文件的写入与读出

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packageutil;import java.io.*;public classFileUtil{/*** 写入文件中*/

public static voidwriteFile(String content, String fileName) {

File file= newFile(fileName);try (BufferedWriter bw = new BufferedWriter(newFileWriter(file))){if(!file.exists()){

file.createNewFile();

}

bw.write(content);

bw.flush();

}catch(IOException e) {

System.out.println("文件操作失败...");

}

}/*** 读文件内容

*@paramcallBack 回调接口,分别处理每一行

*@paramexerciseFileName 题目文件

*@paramanswerFileName 答案文件*/

public static voidreadFile(ReaderCallBack callBack, String exerciseFileName, String answerFileName) {

File exerciseFile= newFile(exerciseFileName);

File answerFile= newFile(answerFileName);if(!exerciseFile.exists() || !answerFile.exists()) {

System.out.println("文件不存在!");return;

}try (BufferedReader br1 = new BufferedReader(newFileReader(exerciseFileName));

BufferedReader br2= new BufferedReader(newFileReader(answerFileName))) {

String line1, line2;while ((line1 = br1.readLine()) != null && (line2 = br2.readLine()) != null) {

callBack.deal(line1, line2);

}

}catch(IOException e) {

System.out.println("读取文件失败!");

}

}public interfaceReaderCallBack {void deal(String exercise, String answer) throwsIOException;

}

}

FileUtil

图形界面:

MainView :主页面,用户在两种操作中选一进行

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packageview;import javax.swing.*;import java.awt.*;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;public classMainView {public static voidmain(String[] args) {newMainJFrame();

}

}class MainJFrame extendsJFrame {/*** 程序主界面*/

private static final long serialVersionUID = 1;//定义全局变量

privateJLabel title;privateJButton generate,judge;privateJLabel result;private JPanel down = newJPanel();//创建一个容器

Container ct;

MainJFrame(){

ct=this.getContentPane();this.setLayout(null);//设置容器为空布局,绝对定位//标题

title= new JLabel("四则运算题目生成程序");

title.setFont(new Font("微软雅黑",Font.BOLD, 30));

title.setBounds(140, 40, 340, 100);//生成

generate = new JButton("生成题目");

generate.setBounds(120, 220, 140, 40);

generate.addActionListener(newgenerateListener());//判错

judge = new JButton("判断对错");

judge.setBounds(300, 220, 140, 40);

judge.addActionListener(newjudgeListenner());//添加组件

ct.add(title);

ct.add(generate);

ct.add(judge);

ct.add(down);this.setTitle("MyApp");this.setSize(600, 450);//设置窗口大小

this.setLocationRelativeTo(null);//基本设置 把窗口位置设置到屏幕中心

this.setVisible(true);//显示窗口

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //关闭窗口 当点击窗口的关闭按钮时退出程序(没有这一句,程序不会退出)

}class generateListener implementsActionListener {//监听生成按钮点击事件

public voidactionPerformed(ActionEvent e) {newGenerateView();

}

}class judgeListenner implementsActionListener{//监听判错按钮点击事件

public voidactionPerformed(ActionEvent e) {newJudgeView();

}

}

}

MainView

GenerateView:用户输入参数范围、生成题目的页面

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packageview;importservice.EntryJudge;import javax.swing.*;import java.awt.*;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;public class GenerateView extendsJFrame {privateJLabel title,result;privateJButton confirm;privateJLabel subjectNum,intArea,denArea;privateJTextField subjectNumField,intAreaField,denAreaField;private JPanel down = newJPanel();publicGenerateView() {//创建一个容器

Container ct;

ct=this.getContentPane();//this.setLayout(null);//设置容器为空布局,绝对定位

this.setSize(600, 450);//基本设置

this.setLocationRelativeTo(null);this.setLayout(null);

title= new JLabel("生成题目");

title.setFont(new Font("微软雅黑",Font.BOLD, 20));

title.setBounds(200,20,280,60);//生成题目数

subjectNum = new JLabel("请输入生成题目数:");

subjectNum.setFont(new Font("微软雅黑",Font.BOLD, 16));

subjectNum.setBounds(70,100,160,50);

subjectNumField= new JTextField (10);

subjectNumField.setBounds(260,100,260,40);//整数范围

intArea = new JLabel("请输入整数范围:");

intArea.setFont(new Font("微软雅黑",Font.BOLD, 16));

intArea.setBounds(70,150,160,50);

intAreaField= new JTextField (20);

intAreaField.setBounds(260,150,260,40);//分母范围

denArea = new JLabel("请输入分数分母的范围:");

denArea.setFont(new Font("微软雅黑",Font.BOLD, 16));

denArea.setBounds(70,200,180,50);

denAreaField= new JTextField (20);

denAreaField.setBounds(260,200,260,40);

confirm= new JButton("确定");

confirm.setBounds(250,270, 60, 50);

confirm.addActionListener(newConfirmActionListener());//设置底部panel

down.setBounds(130, 330, 280, 50);//设置底部panel背景透明

down.setBackground(null);

down.setOpaque(false);

result= newJLabel();

result.setFont(new Font("微软雅黑",Font.BOLD, 18));//添加组件

down.add(result);

ct.add(title);

ct.add(subjectNum);

ct.add(subjectNumField);

ct.add(intArea);

ct.add(intAreaField);

ct.add(denArea);

ct.add(denAreaField);

ct.add(confirm);

ct.add(down);this.setVisible(true);//显示窗口

this.setLocationRelativeTo(null);//基本设置 把窗口位置设置到屏幕中心

this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); //关闭窗口

}class ConfirmActionListener implementsActionListener {public voidactionPerformed(ActionEvent e) {

String args1=subjectNumField.getText();

String args2=intAreaField.getText();

String args3=denAreaField.getText();

String [] args= new String[]{"-n",args1,"-r",args2,"-d",args3};

EntryJudge ej= newEntryJudge();boolean res =ej.Entry(args);//获取命令执行结果

if(res == true) {

result.setText("结果:生成题目成功");

}else{

result.setText("结果:生成题目失败");

}

}

}

}

GenerateView

JudegeView:用户选择文件,是判断对错的页面

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packageview;importservice.EntryJudge;import javax.swing.*;import java.awt.*;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;public class JudgeView extendsJFrame {privateJLabel title,result;privateJButton confirm;privateJLabel subjectNum,intArea,file1,file2;privateJButton btn1,btn2;private JPanel down = newJPanel();publicJudgeView() {//创建一个容器

Container ct;

ct=this.getContentPane();this.setSize(600, 450);//基本设置

this.setLocationRelativeTo(null);this.setLayout(null);

title= new JLabel("判断对错");

title.setFont(new Font("微软雅黑",Font.BOLD, 20));

title.setBounds(200,20,280,60);//生成题目数

subjectNum = new JLabel("请选择题目文件:");

subjectNum.setFont(new Font("微软雅黑",Font.BOLD, 16));

subjectNum.setBounds(70,100,160,50);

btn1= new JButton ("选择文件");

btn1.setBounds(240,100,120,40);

btn1.addActionListener(newChooseFile1ActionListener());

file1= newJLabel();

file1.setFont(new Font("微软雅黑",Font.BOLD, 14));

file1.setBounds(390,100,130,50);//整数范围

intArea = new JLabel("请输入答案文件:");

intArea.setFont(new Font("微软雅黑",Font.BOLD, 16));

intArea.setBounds(70,150,160,50);

btn2= new JButton ("选择文件");

btn2.setBounds(240,150,120,40);

btn2.addActionListener(newChooseFile2ActionListener());

file2= newJLabel();

file2.setFont(new Font("微软雅黑",Font.BOLD, 14));

file2.setBounds(390,150,130,50);

confirm= new JButton("确定");

confirm.setBounds(250,270, 60, 50);

confirm.addActionListener(newConfirmActionListener());//设置底部panel

down.setBounds(130, 330, 280, 50);//设置底部panel背景透明

down.setBackground(null);

down.setOpaque(false);

result= newJLabel();

result.setFont(new Font("微软雅黑",Font.BOLD, 18));//添加组件

down.add(result);

ct.add(title);

ct.add(subjectNum);

ct.add(btn1);

ct.add(file1);

ct.add(intArea);

ct.add(btn2);

ct.add(file2);

ct.add(confirm);

ct.add(down);this.setVisible(true);//显示窗口

this.setLocationRelativeTo(null);//基本设置 把窗口位置设置到屏幕中心

this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); //关闭窗口

}class ChooseFile1ActionListener implementsActionListener {public voidactionPerformed(ActionEvent e) {

JFileChooser chooser= new JFileChooser(); //设置选择器

chooser.setMultiSelectionEnabled(true); //设为多选

int returnVal = chooser.showDialog(new JLabel(),"选择");

String filename= chooser.getSelectedFile().getName(); //获取绝对路径

file1.setText(filename);

}

}class ChooseFile2ActionListener implementsActionListener {public voidactionPerformed(ActionEvent e) {

JFileChooser chooser2= new JFileChooser(); //设置选择器

chooser2.setMultiSelectionEnabled(true); //设为多选

int returnVal = chooser2.showDialog(new JLabel(),"选择");

String filename= chooser2.getSelectedFile().getName(); //获取绝对路径

file2.setText(filename);

}

}class ConfirmActionListener implementsActionListener {public voidactionPerformed(ActionEvent e) {//获取结果

String [] args = new String[]{"-e", "Exercises.txt","-a","Answers.txt"};

EntryJudge ej= newEntryJudge();boolean res =ej.Entry(args);//获取命令执行结果

if(res == true) {

result.setText("结果:生成题目成功");

}else{

result.setText("结果:生成题目失败");

}

}

}

}

JudegeView

六、测试测试结果

程序运行,成功打开图形界面:

0656e450f788e4ade2e263231f98b2c5.png

测试题目生成是否成功:

输入相关参数,点击确定 ,生成题目成功:

091d8b008497538688a88c3bb4c60a65.png

查看Exersises.txt,成功生成题目:

ef7a3e835895ce5716abfa67d74d25a0.png

查看Answers.txt,答案:

d43e2384075308be6aea063ad790da84.png

测试判错程序:

改错二道题的答案:

55368de1cec92a82ddb6ffb47c8c91ff.png

打开判错的图形界面,选择算式文件、选择答案文件:

d76272c7c18535d2062ddaa81925417d.png

点击确定,查看统计文件Grade.txt:

b3197d76f3c717de3852408edd87d8b0.png

生成一万道算式:

详细的github地址:

部分截图:

3934b12f6f4cc6b9203fa53940f8a578.png

ba0ba05ebd9cb10c55ff6fb097eeb436.png

七、项目小结

此次的结对编程,我们均涉及了代码的设计、编写以及测试。讨论项目的基本构思对我负责的前期编码十分重要,从基础数值的定义和生成,再到采用二叉树存放算式,最后一步步完成项目,通过两个人的讨论,使得项目的整体思路变得清晰。在后期的编码中我的伙伴对我的编程方式提出了更有条理性的建议,最终在小改动下让整个项目的代码变得更为整洁与条理。

多讨论交流意见对编程的帮助很大,在判错功能中,从开始的没有头绪,到讨论出来通过应用一个栈的实例:中缀表达式转前缀表达式,解决了判错的问题;开始项目生成大数量题目的速度很慢,在小伙伴丰富的编程经验下,指出了关于多线程运行程序的方式,并且通过优化一些代码,大大提高了效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/505563.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java版的中世纪战争_世界战争英雄设置-火焰纹章英雄英雄地图及AI命令设置

英雄地图及AI命令设置游戏中练级塔中的AI设置和故事地图中的一样&#xff0c;所以如果故事地图中的AI是主动出击的&#xff0c;那练级塔一样的地图也是主动出击。故事地图中配置有5个敌人&#xff0c;在练级塔中也一样会配置5个敌人。不同的是职业可能会发生变化&#xff0c;但…

python pip安装依赖的常用软件源

目录 引言 一、什么是镜像源&#xff1f;​​​​​​​ 二、清华源 三、阿里源 四、中科大源 五、豆瓣源 六、更多资源 引言 在软件开发和使用过程中&#xff0c;我们经常需要下载和更新各种软件包和库文件。然而&#xff0c;由于网络环境的限制或者服务器的负载&#…

java虚拟机规范 51cto_java虚拟机

最近学习java虚拟机做了一些整理&#xff0c;会陆续发完。Java虚拟机一、概念&#xff1a;当我们谈到java虚拟机的时候&#xff0c;有可能指下面3个方面&#xff1a;1)&#xff1a;抽象java虚拟机的规范。2)&#xff1a;一个java虚拟机具体的实现。------实现是指&#xff1a;实…

ipv6+ssh+java_IPv6的本地联网地址计算方法详解

IPv6的世界里&#xff0c;如果DHCP6和SLACC这两位大佬都为没有为可怜的网卡分配IP地址&#xff0c;也没有人为网卡设置静态的IP地址&#xff0c;系统就会为网卡计算一个IPv6的网址来。这样的网址只能在本地使用&#xff0c;不得路由&#xff0c;所以&#xff0c;被称为“link-l…

java互斥锁的实现原理_java-深入分析synchronized原理

互斥锁互斥锁futex&#xff0c;全拼fast userspace mutexes&#xff0c;直翻为快速用户空间互斥器&#xff0c;它是我们上层应用实现锁的最常用方法。futex是一块所有进程都可以访问的内存&#xff0c;是通过cpu的原子操作修改内存中的值来尝试获取琐&#xff0c;如果没有竞争&…

京东开普勒php接口,IOS菜鸟初学第十五篇:接入京东开普勒sdk,呼起京东app打开任意京东的链接-Go语言中文社区...

我之前写了一篇关于接入京东联盟sdk的文章&#xff0c;但是最近&#xff0c;由于这个原因&#xff0c;如下图导致需要重新集成京东的sdk&#xff0c;但是由于某种原因&#xff0c;因为android和ios端不统一&#xff0c;android接入的是京东开普勒的SDK&#xff0c;这次为了统一…

oracle安装过程掉电,Oracle数据库掉电后ORA-01172磁盘坏块解决方法

由于服务器突然掉电&#xff0c;重启机器后发现数据库无法启动。数据库版本 Oracle10201&#xff0c;OS REDHAT 5.4数据库无归档&#xff0c;无备份 [oraclehuna由于服务器突然掉电&#xff0c;重启机器后发现数据库无法启动。数据库版本 Oracle10201&#xff0c;&#xff0c;O…

linux删除了mount目录,Linux记录-分区(df/fdisk/mount/umount/fuser)

1.查看磁盘挂载(df -TH)2.卸载umount /dev/vdb13.查杀用户进程(fuser -m -v -i -k /dev/vdb1)4.再次卸载umount /dev/vdb1&#xff0c;并查看挂载信息df -TH5.删除分区(fdisk /dev/vdb m d 1 d w)6.查看分区(fdisk -l&#xff0c;没有Start-End磁盘分区表示可用)7.添加分区(fdi…

linux中pak命令,如何在Linux系统中安装Flatpak

选择你的Linux发行版快速安装Flatpak及使用Flatpak。支持Ubuntu、Fedora、Red Hat Enterprise Linux、Deepin、Endless OS、Linux Mint、openSUSE、Arch、Debian、CentOS、Gentoo、Solus、Alpine、Mageia、Pop!_OS、elementary OS、Raspbian。以下为你逐一介绍如何在这些Linux版…

ubuntu 改linux密码忘了怎么办,Ubuntu 14.04忘记root密码的解决方法

电脑20多天没用&#xff0c;忘记Ubuntu 14.04 root密码了&#xff0c;下面是在网上找到的一个解决办法&#xff0c;其它的和这个也大概相同。因为其中有些缺漏&#xff0c;没能给我解决问题。通过分析最终问题还是解决了&#xff0c;现解决方案的关键点记录一下。希望能方便到其…

linux设置历史命令保留数目限制,linux下修改history命令保存条数

在linux系统下、history命令会保存多少条命令呢&#xff1f;曾在一本书上说&#xff0c;如果注销系统&#xff0c;那么会将所有的历史命令都定入到~/.bash_history,但只保留1000条命令(这个是由默认的shell变量所设置了的)但是为什么我们执行history命令后会出现大于1000条的历…

android 手机壁纸源码,Android工程实现换壁纸功能【附源码】

最近工作要实现换壁纸小功能,将代码做成demo发出来没有采用zip格式换肤,因为只是更换一张图片背景1.将三张图放入drawable-hdpi,我放的是480*800的2.用sharedPreference存取皮肤的id,以便于下次启动的时候根据id来选择用哪个皮肤,在onresume()里刷新皮肤3.存到sharedPreference…

android webview 加载本地,webview加载本地资源的各种尝试

1.webview 打开sd卡上的静态html文件 &#xff0c;js文件既然放在assets文件夹下能找到&#xff0c;那能通过放在sd卡&#xff0c;能加载吗&#xff1f;答&#xff1a;事实证明&#xff0c;是没有用的。2.既然能拿到html的数据&#xff0c;那我们是不是重写html的script的tag的…

apple手表android手机,Apple Watch 4发布了,安卓手机用户如何选择呢?

Apple Watch 4发布了&#xff0c;安卓手机用户如何选择呢&#xff1f;2018年09月13日 17:40作者&#xff1a;黄页编辑&#xff1a;黄页分享一年一度的“科技界春晚”苹果新品发布在今天凌晨举行。苹果带来了新一代的智能手表——Apple Watch Series 4系列。作为“课代表”,科技…

android投屏到电视机,华为手机如何投屏到电视机上?按步骤,1分钟搞定手机投屏电视机...

现在&#xff0c;越来越多的人开始用上了华为手机&#xff0c;几乎人手一台。在平时学习、工作中&#xff0c;我也经常使用华为手机来处理、完成很多事项、任务&#xff0c;例如把手机投屏到电视机上。除了满足学习、工作需求&#xff0c;我也经常把手机投屏电视来看视频、玩游…

html语言可以干什么,JavaScript语言能做什么?

JavaScript是除了HTML和CSS之外&#xff0c;万维网的核心技术之一。JavaScript支持交互式web页面&#xff0c;是web应用程序的重要组成部分。绝大多数网站都使用它&#xff0c;主要的网络浏览器都有专门的JavaScript引擎来执行它。JavaScript(简称“JS”) 是一种具有函数优先的…

html获取当前二级域名,列举某域名下所有二级域名的方法总结

鬼仔注&#xff1a;本文为总结文&#xff0c;转载请注明来源( http://huaidan.org )这里介绍三种列举某域名下所有二级域名的方法&#xff0c;有知道其他方法的请到 http://huaidan.org/archives/1088.html 留言进行补充~谢谢。1、命令行下列举此方法好像是hoky很久以前写的&am…

html5绘制矩形动画,HTML5下绘制矩形教程

绘制矩形上一节&#xff0c;我们使用lineto()方法绘制一个封闭的矩形。其实&#xff0c;canvas的api提供了rect()方法可以绘制矩形。rect()方法是路径方法&#xff0c;它会把指定的矩形添加到当前路径的子路径中。它只添加路径&#xff0c;绘制图形还是由stroke()或fill()方法完…

html免费天气预报代码,免费自我定制天气预报代码

免费自我定制天气预报代码(2010-06-15 22:03:35)标签&#xff1a;昔阳天气预报一乌海天气预报一杂谈今晚蚊子又发现一个天气预报,在别人博客上看见的,昔阳天气预报一周,觉得还不错,查看了一下源代码,把怎么弄的方法告诉大家,南靖天气预报一周,其实没什么技术含量,很简单的,就是…

html5伪类触发机制,HTML5表单验证

validity属性表单元素对象具有此属性&#xff0c;返回值是一个ValidityState对象。ValidityState对象的名称是合成词&#xff0c;如有两个单词构成&#xff1a;(1).validity&#xff1a;翻译成汉语具有"验证"的意思。(2).state&#xff1a;翻译成汉语具有"状态&…