首页 > 其他分享 >结对项目

结对项目

时间:2024-09-28 23:45:14浏览次数:8  
标签:extraCopy 结对 项目 int StringBuilder denominator numerator param

这个作业属于哪个课程 计科12班
这个作业要求在哪里 作业要求
这个作业的目标 要求实现一个自动生成小学四则运算题目的命令行程序

成员及仓库

学号 成员 代码仓库
3122004657 林诗淇 https://github.com/shiqi323/examination

PSP表格

PSP2.1 Personal Software Process Stages 预估耗时 (分钟) 实际耗时(分钟)
Planning 计划 30 30
·Estimate ·估计这个任务需要多少时间 30 30
Development 开发 500 600
·Analysis ·需求分析(包括学习新技术) 50 40
·Design Spec ·生成设计文档 20 20
·Design Review ·设计复审 10 5
·Coding Standard ·代码规范(为目前的开发制定合适的规范) 10 15
·Design ·具体设计 30 40
·Coding ·具体编码 300 350
·Code Review ·代码复审 30 60
·Test ·测试(自我测试,修改代码,提交修改) 10 40
Reporting 报告 65 75
·Test Repor ·测试报告 30 40
·Size Measurement ·计算工作量 15 10
·Postmortem & Process Improvement Plan ·事后总结,并提出过程改进计划 20 25
合计 1050 1200

需求分析

1.从个人项目出发,将程序改造成一个带用户界面的程序

2.自动生成题目,单个题目最多不能超过4个运算符,操作数小于100

3.用户可以输入答案

4.判断并提示用户输入答案的对错,显示正确答案

代码部分

1.运算

点击查看代码
package main.com.examination.util;

import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@SuppressWarnings("all")
public class CalculateUtil {

	private static final Logger logger = Logger.getLogger("CalculateUtil");

	/**
	 * 加法运算
	 * @param numerator1 分子1
	 * @param denominator1 分母1
	 * @param numerator2 分子2
	 * @param denominator2 分母2
	 * @return 返回结果
	 */
	public static StringBuilder add(int numerator1,int denominator1,int numerator2,int denominator2) {
		int numerator,denominator;
		StringBuilder result = new StringBuilder();
		numerator = numerator1*denominator2+numerator2*denominator1;
		denominator = denominator1 * denominator2;
		if(numerator!=0) {
			//化简分子分母(除以最大公因数)
			int gcdNum = HandleUtil.gcd(numerator,denominator);
			numerator /= gcdNum;
			denominator /= gcdNum;
		}

		result.append(numerator+"/"+denominator);
		return result;
	}

	/**
	 * 减法运算
	 * @param numerator1 分子1
	 * @param denominator1 分母1
	 * @param numerator2 分子2
	 * @param denominator2 分母2
	 * @return 返回计算结果
	 */
	public static StringBuilder minus(int numerator1,int denominator1,int numerator2,int denominator2) {
		int numerator,denominator;
		StringBuilder result = new StringBuilder();

		numerator = numerator1*denominator2-numerator2*denominator1;
		denominator = denominator1*denominator2;
		//化简分子分母(除以最大公因数)
		if(numerator!=0) {
			int gcdNum = HandleUtil.gcd(numerator,denominator);
			numerator /= gcdNum;
			denominator /= gcdNum;
		}
		result.append(numerator+"/"+denominator);
		return result;
	}

	/**
	 * 乘法运算
	 * @param numerator1 分子1
	 * @param denominator1 分母1
	 * @param numerator2 分子2
	 * @param denominator2 分母2
	 * @return 返回计算结果
	 */
	public static StringBuilder multiply(int numerator1,int denominator1,int numerator2,int denominator2) {
		int numerator,denominator;
		StringBuilder result = new StringBuilder();
		//操作数有一个等于0的情况
		if(numerator1==0||numerator2==0) {
			result.append(0+"/"+1);
		}
		//操作数大于0的情况
		else {
			numerator = numerator1*numerator2;
			denominator = denominator1*denominator2;
			//化简分子分母(除以最大公因数)
			if(numerator!=0) {
				int gcdNum = HandleUtil.gcd(numerator,denominator);
				numerator /= gcdNum;
				denominator /= gcdNum;
			}
			result.append(numerator+"/"+denominator);
		}
		return result;
	}

	/**
	 * 除法运算
	 * @param numerator1 分子1
	 * @param denominator1 分母1
	 * @param numerator2 分子2
	 * @param denominator2 分母2
	 * @return 返回计算结果
	 */
	public static StringBuilder divide(int numerator1,int denominator1,int numerator2,int denominator2) {
		int numerator,denominator;
		StringBuilder result = new StringBuilder();
		numerator = numerator1*denominator2;
		denominator = denominator1*numerator2;
		//化简分子分母(除以最大公因数)
		if(numerator!=0) {
			int gcdNum = HandleUtil.gcd(numerator,denominator);
			numerator /= gcdNum;
			denominator /= gcdNum;
		}
		result.append(numerator+"/"+denominator);
		return result;
	}

	/**
	 * 对运算符号左右的两个数进行运算
	 * @param index 运算符的位序
	 * @param extraCopy 待计算的式子
	 * @return
	 */
	public static StringBuilder calculate(int index,StringBuilder extraCopy) {
		char sign = extraCopy.charAt(index);
		int beginIndex = 0, endIndex = -1;
		int[] datas;
		for(int index1=0; ; beginIndex=index1) {
			//找到第一个操作数的开头空格
			index1 = extraCopy.indexOf(" ", index1+1);
			if(index1==(index-1)) {
				break;
			}
		}
		datas = HandleUtil.change(extraCopy, beginIndex);
		int numerator1 = datas[1];
		int denominator1 = datas[2];
		datas = HandleUtil.change(extraCopy, index+1);
		int numerator2 = datas[1];
		int denominator2 = datas[2];
		endIndex = datas[0];
		//删除数字部分
		extraCopy.delete(beginIndex+1,endIndex);
		//根据符号进行相应的运算
		switch(sign){
			case '+':
				extraCopy.insert(beginIndex+1, add(numerator1,denominator1,numerator2,denominator2));
				break;
			case '-':
				if(!HandleUtil.judge(numerator1, denominator1, numerator2, denominator2)) {
					//识别答案是否为负数
					extraCopy.insert(0, "@ ");
					break;
				} else{
					extraCopy.insert(beginIndex+1, minus(numerator1,denominator1,numerator2,denominator2));
					break;
				}
			case '*':
				extraCopy.insert(beginIndex+1, multiply(numerator1,denominator1,numerator2,denominator2));
				break;
			case '÷':
				if(numerator2 == 0) {
					//识别答案是否为负数,是的话在开头插入@作为标识
					extraCopy.insert(0, "@ ");
					break;
				} else{
					extraCopy.insert(beginIndex+1, divide(numerator1,denominator1,numerator2,denominator2));
					break;
				}
			default: break;
		}
		return extraCopy;
	}

	/**
	 * 按优先级进行运算(*  /  +  -)
	 * @param extraCopy copy副本
	 * @return 返回
	 */
	public static StringBuilder calculateFormula(StringBuilder extraCopy) {
//		logger.info(extraCopy.toString());
		//记录符号的位序
		int index = -1;
		//计算式子
		Pattern pattern1 = Pattern.compile("[*]|[÷]");
		Matcher m1;
		while((m1 = pattern1.matcher(extraCopy)).find()) {
			index = m1.start();
			calculate(index, extraCopy);
			if(extraCopy.charAt(0)=='@') {
				break;
			}	
		}
		//如果式子正确,在进行加运算(从左到右)
		if(extraCopy.charAt(0)!='@') {
			Pattern pattern2 = Pattern.compile("[-]|[+]");
			Matcher m2;
			while((m2 = pattern2.matcher(extraCopy)).find()) {
				index = m2.start();
				calculate(index, extraCopy);
				if(extraCopy.charAt(0)=='@') {
					break;
				}	
			}
		}
		//如果运算结束后(式子正确),调整答案格式
		if(extraCopy.charAt(0)!='@') {
			int datas[];
			datas = HandleUtil.change(extraCopy, 0);
			//分子
			int numerator = datas[1];
			//分母
			int denominator = datas[2];
			//将原存储内容清空
			extraCopy.setLength(0);
			//将答案换成标准格式
			extraCopy.append(HandleUtil.creatNum(numerator, denominator));
		}
		return extraCopy;
	}
}

2.检验
点击查看代码
package main.com.examination.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

@SuppressWarnings("all")
public class CheckUtil {

    /**
     * 将StringBuilder拆分成string数组
     * @param stringBuilder
     * @return 返回string[] 数组
     */
    public static String[] spiltStringBuilderToArray(StringBuilder stringBuilder){
        return stringBuilder.toString().split("\\s+");
    }

    /**
     * 将StringBuilder拆分成List数组
     * @param stringBuilder string串串
     * @return 返回List数组
     */
    public static List<String> spiltStringBuilderToList(StringBuilder stringBuilder){
        return Arrays.asList(spiltStringBuilderToArray(stringBuilder));
    }

    /**
     * 将StringBuilder拆分成有序的 List 数组
     * @param stringBuilder string串串
     * @return 返回List数组
     */
    public static List<String> spiltStringBuilderToOrderList(StringBuilder stringBuilder){
        List<String> stringList = spiltStringBuilderToList(stringBuilder);
        Collections.sort(stringList);
        return stringList;
    }

    /**
     * 判断内容是否有重复
     * @param formula 判断的式子
     * @param lists 排序完的全部 list
     * @param answer 答案
     * @param answerLists 答案集
     * @return 返回是否重复
     */
    public static boolean judgeRepeat(StringBuilder formula, List<List<String>> lists,StringBuilder answer,List<StringBuilder> answerLists){
        List<String> formulaList = spiltStringBuilderToOrderList(formula);
        int i;
        for (i = 0;i<lists.size();i++){
            if(lists.get(i).equals(formulaList) && answer.toString().equals(answerLists.get(i).toString())){
                return true;
            }
        }
        lists.add(formulaList);
        return false;
    }

}

3.生成题目
点击查看代码
package main.com.examination.util;

import main.com.examination.commons.OperatorVar;
import main.com.examination.dao.IODao;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

public class CreateUtil {

    //日志输出
    private static final Logger logger = Logger.getLogger("CreateUtil");
    List<StringBuilder> formula;
    //备份式子,存储"分子/分母"结构的式子,便于结果计算
    List<StringBuilder> answer;
    StringBuilder extraCopy ;

    public List<StringBuilder> getFormula() {
        return formula;
    }

    public List<StringBuilder> getAnswer() {
        return answer;
    }

    /**
     * 随机生成式子
     * 用List存储式子
     * @param maxNum 最大值
     * @return 返回该字符串
     * */
    public StringBuilder create(int maxNum) {
        StringBuilder formula = new StringBuilder();
        extraCopy = new StringBuilder(" ");
        //符号个数 (1,2,3)
        int signNum = (int)(Math.random()*3+1);
        creatNum(formula,maxNum);
        for(int i=0; i<signNum; i++) {
            createSign(formula);
            creatNum(formula,maxNum);
        }
        formula.append(OperatorVar.EQUAL_SIGN.getExpress() +" ");
        return formula;
    }

    /**
     * 随机生成操作数
     * 并将操作数存入list中
     * @param formula 字符串
     * @param maxNum 数
     * @return 返回参数的字符串
     * */
    public StringBuilder creatNum(StringBuilder formula,int maxNum) {
    	int numerator,denominator,type;
		type = (int)(Math.random()*2);
        //生成整数
		if(type==0) {
			do {
				numerator =(int)(Math.random()*10);
			}while(numerator > maxNum);
            //备份分子/分母
			extraCopy.append(numerator+"/"+1+" ");
			formula.append(numerator+" ");
		}
		else {
			do {
                //随机生成分子
				numerator = (int)(Math.random()*10);
                //保证分母不等于0
				while((denominator=(int)(Math.random()*10))==0);
			}while(!numRange(numerator, denominator,maxNum));
            //备份分子/分母
			extraCopy.append(numerator+"/"+denominator+" ");
			formula.append(HandleUtil.creatNum(numerator, denominator));
		}
		return formula;
    }

    /**
     *  随机生成符号
     * 并将符号存入list中
     * @param formula 符号
     * @return 返回符号
     */
    public StringBuilder createSign(StringBuilder formula) {
        //符号类型(+ - * /)
        int signType = (int)(Math.random()*4+1);
        switch (signType){
            case 1 :
                formula.append(OperatorVar.PLUS_SIGN.getExpress());
                extraCopy.append(OperatorVar.PLUS_SIGN.getExpress());
                break;
            case 2 :
                formula.append(OperatorVar.MINUS_SIGN.getExpress());
                extraCopy.append(OperatorVar.MINUS_SIGN.getExpress());
                break;
            case 3 :
                formula.append(OperatorVar.MULTIPLIED_SIGN.getExpress());
                extraCopy.append(OperatorVar.MULTIPLIED_SIGN.getExpress());
                break;
            case 4 :
                formula.append(OperatorVar.DIVISION_SIGN.getExpress());
                extraCopy.append(OperatorVar.DIVISION_SIGN.getExpress());
                break;
            default:

        }
        extraCopy.append(" ");
        formula.append(" ");
        return formula;
    }

    /**
     * 设定随机生成一定数目的式子,并将式子和答案分别存在formula和answer中
     * @param num 生成的式子数目
     * @param maxNum 最大值
     */
    public void formulaNum(int num, int maxNum) throws IOException {
        Long beginTime = System.currentTimeMillis();
        //存放拆分完的式子
        List<List<String>> formulaLists = new ArrayList<List<String>>(num);
        formula = new ArrayList<StringBuilder>();
        answer = new ArrayList<StringBuilder>();
        //原始式子
        StringBuilder singleFormula;
        for(int i=0; formula.size()<num; i++) {
            formula.add(singleFormula = create(maxNum));
            CalculateUtil.calculateFormula(extraCopy);
            //式子不符合规范(结果为负数),并且查重
            if(extraCopy.charAt(0)=='@' || CheckUtil.judgeRepeat(singleFormula,formulaLists,extraCopy,answer)) {
                formula.remove(formula.size()-1);
                continue;
            }
            answer.add(extraCopy);
        }
        int i=0;
        IODao.storageFile(formula,"Exercises.txt");
        IODao.storageFile(answer,"Answers.txt");
        System.out.println("生成时间: " + (System.currentTimeMillis()-beginTime));
    }

    /**
     * 设定操作数的最大数值
     * @param numerator 分子
     * @param denominator 分母
     * @param maxNum 最大值
     * @return 是否超过最大值
     */
    public boolean numRange(int numerator, int denominator,int maxNum) {
        if((numerator/denominator)<maxNum) {
            return true;
        }else if((numerator/denominator)==maxNum) {
            if((numerator%denominator)==0) {
                return true;
            }
        }
        return false;
    }

}

4.答案
点击查看代码
package main.com.examination.util;

public class HandleUtil {

    /**
     * 将答案按规范生成出来
     * @param numerator 分子
     * @param denominator 分母
     * @return 式子
     */
    public static StringBuilder creatNum(int numerator, int denominator) {
        StringBuilder num = new StringBuilder();
        int gcdNum = gcd(numerator, denominator);
        numerator /= gcdNum;
        denominator /= gcdNum;
        if (numerator >= denominator) {
            //分子大于等于分母
            if (numerator % denominator == 0) {
                //结果为整数
                num.append(numerator / denominator + "");
            } else {
                //结果为带分数
                int interger = numerator / denominator;
                numerator = numerator - (interger * denominator);
                num.append(interger + "'" + numerator + "/" + denominator + "");
            }
        } else {
            //分子小于分母
            if (numerator == 0) {
                //分子等于0
                num.append(0 + "");
            } else {
                //其他情况
                num.append(numerator + "/" + denominator + "");
            }
        }
        return num;
    }

    /**
     * 求两数的最大公因数
     * @param num01 数字1
     * @param num02 数字2
     * @return 返回公因数
     */
    public static int gcd(int num01, int num02) {
        int num;
        while (num02 != 0) {
            num = num01 % num02;
            num01 = num02;
            num02 = num;
        }
        return num01;
    }

    /**
     * 将式子中指定字符的所有位序存储起来
     * @param str 字符串
     * @param formula 式子
     * @return 返回位序
     */
    public static int[] charFind(String str, StringBuilder formula) {
        int[] indexs = new int[20];
        for (int i = 0; ; i++) {
            if (i == 0) {
                indexs[i] = formula.indexOf(str, 0);
                continue;
            }
            if (str.equals(" ") && (indexs[i - 1] == formula.length() - 1)) {
                break;
            }
            if (str.equals(" ") || str.equals("/")) {
                indexs[i] = formula.indexOf(str, indexs[i - 1] + 1);
            }
            if (str.equals("/") && (formula.length() - 1 - indexs[i] <= 4)) {
                break;
            }
        }
        return indexs;
    }


    /**
     * 将指定数字字符串转为数字值
     * @param formula 带查找的式子
     * @param fromIndex 操作数前的空格位序
     * @param endIndex 操作数后的空格位序
     * @return 返回数字
     */
    public static int changeNum(StringBuilder formula, int fromIndex, int endIndex) {
        int num = -1;
        //根据数字的位数进行转换
        int sum = 0, temp;
        for (int i = 1; i < (endIndex - fromIndex); i++) {
            temp = (int) Math.pow((double) 10, (double) (i - 1));
            num = (int) (formula.charAt(endIndex - i) - 48) * temp;
            sum += num;
        }
        return sum;
    }

    /**
     * 判断被减数、减数是否符合规范(true:符合;false:不符合)
     * @param numerator1 第一个操作数的分子
     * @param denominator1  第一个操作数的分母
     * @param numerator2 第二个操作数的分子
     * @param denominator2 第二个操作数的分母
     * @return 返回是否正确
     */
    public static boolean judge(int numerator1, int denominator1, int numerator2, int denominator2) {
        int numerator = numerator1 * denominator2 - numerator2 * denominator1;
        if (numerator < 0) {
            return false;
        }
        return true;
    }



    /**
     * 通过字符串将操作数的分子分母转成数字
     * @param extraCopy 进行操作的字符串
     * @param beginIndex 操作数前的空格位序
     * @return 返回数字集
     */
    public static int[] change(StringBuilder extraCopy, int beginIndex) {
		int[] num = new int[3];
        //存储空格的位序,方便找到完整的操作数
		int[] blanks = charFind(" ", extraCopy);
        //反斜杠的位置
		int indexBl = -1 ,indexBa = extraCopy.indexOf("/", beginIndex);
		for(int i=0; i<blanks.length; i++) {
			if(blanks[i]==beginIndex) {
			    //找到传入空格位序在blanks中的位置
				indexBl = i;
				break;
			}
		}
		num[0]=blanks[indexBl+1];//操作数后的空格位序
		num[1]=changeNum(extraCopy,beginIndex,indexBa);//分子
		num[2]=changeNum(extraCopy,indexBa,num[0]);//分母
		return num;
	}
}



#测试分析



标签:extraCopy,结对,项目,int,StringBuilder,denominator,numerator,param
From: https://www.cnblogs.com/shiqi323/p/18438633

相关文章

  • 结对项目
    这个作业属于哪个课程https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/这个作业要求在哪里https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/homework/13230这个作业的目标实现一个自动生成小学四则运算题目的命令行程序一、成员个人信息姓名学号......
  • 结对项目——实现一个自动生成小学四则运算题目的命令行程序
    这个作业属于哪个课程https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/这个作业要求在哪里结对项目-作业-计科22级34班-班级博客-博客园(cnblogs.com)这个作业的目标结对项目——实现一个自动生成小学四则运算题目的命令行程序成员1陈奕奕32220045......
  • 结对项目
    这个作业属于哪个课程软件工程课程这个作业要求在哪里https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/homework/13230这个作业的目标实现一个自动生成小学四则运算题目的命令行程序成员一32222004725乌克来·布拉什成员二3222004728钟慧雯GitHub地......
  • 结对项目
    这个作业属于哪个课程https://edu.cnblogs.com/campus/gdgy/CSGrade22-12/homework/13221这个作业要求在哪里结对项目这个作业的目标合作完成一个自动生成小学四则运算题目的命令行程序结对组合成员:结对组合成员姓名学号曾平凡3222004326题目:实......
  • 结对项目
    这个作业属于哪个课程计科22级12班这个作业的要求在哪里结对项目这个作业的目标实现小学四则运算的程序,在合作中完成项目设计结对项目成员姓名学号黄英琦3122004909张怀坤3122004926Github地址预估设计时间PSP表格PSP2.1PersonalSof......
  • 结对项目
    结对项目这个作业属于哪个课程https://edu.cnblogs.com/campus/gdgy/CSGrade22-34这个作业要求在哪https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/homework/13230这个作业的目标设计一个四则运算生成器成员:3班3122004861:方尔博4班3122004610:黄文超git......
  • 结对项目:自动生成小学四则运算题目的命令行程序
    这个作业属于哪个课程计科22级12班这个作业要求在哪里https://edu.cnblogs.com/campus/gdgy/CSGrade22-12/homework/13221姓名学号曾繁曦3122004841吴健民3122004667PSP表格一、流程图二、模块设计1.模块划分Main模块(Main.java)功能描述:程序的入......
  • 《深度学习》【项目】OpenCV 发票识别 透视变换、轮廓检测解析及案例解析
    目录一、透视变换1、什么是透视变换2、操作步骤    1)选择透视变换的源图像和目标图像    2)确定透视变换所需的关键点    3)计算透视变换的变换矩阵    4)对源图像进行透视变换    5)对变换后的图像进行插值处理二、轮廓检测1、......
  • 开题报告-毕设如何选题-计算机视觉项目大集合(图像分类+目标检测+目标跟踪+姿态识别+
    #毕设选题-开题报告-计算机视觉项目大集合计算机视觉项目大集合yolo系列及创新点和应用(测距测速等):改进的yolo目标检测-测距测速图像去雨去雾+目标检测+测距项目交通标志识别项目yolo系列-重磅yolov9界面-最新的yoloyolov8双目测距-yolov8+sgbm(原理+代码)yolov5......
  • 【qt】QQ仿真项目1
    一览全局:QQ仿真项目一.创建项目添加资源文件二.创建数据库三.自定义标题栏Qt类四.加载样式表标题栏按钮的搭配五.标题栏实现移动窗体六.标题栏按钮连接信号槽七.标题栏双击最大化和还原八.基类窗口实现标题栏按钮信号九.重写基类窗口绘图事件确保设置样式表生效十.用......