# 2019-2020-4 《Java 程序设计》结对项目总结

2019/04/03 21:30
阅读数 19

2019-2020-4 《Java 程序设计》结对项目阶段总结---《四则运算——整数》

一、需求分析

实现一个命令行程序

要求:

  1. 自动生成小学四则运算题目(加,减,乘,除);
  2. 支持整数;
  3. 支持多运算符(例如生成包含n个运算符的题目);
  4. 支持真分数(后续实现);
  5. 统计正确率。

扩展需求

  1. 文件: (1) 处理生成题目并输出到文件; (2) 完成题目后从文件读入并判断。
  2. 多语言支持:简体中文,繁體中文,English;
  3. 生成题目去重。

二、设计思路以及代码解释

刚拿到结对项目

刚拿到结对项目时,感觉不是很难,是因为没有考虑到括号、运算优先级以及多个数字运算的问题,所以只是简单设计了一个两个数字简单的四则运算,具体程序如下:

//生成随机整数的运算

public class Zheng {
        int a=0,b=0,c=0;
	int result=0,g=0;
	String s=null;
	public void Zheng(){
		a = (int)(Math.random()*100);//生成0-99的随机数
		b = (int)(Math.random()*100);
		c = (int)(Math.random()*4);//生成0-3的随机数,用来随机产生运算符
		 if(c==0){
			 System.out.println(a+"+"+b+"=");
			 result = a + b;
		 }
		 if(c==1){
                         System.out.println(a+"-"+b+"=");
			 result = a - b;
		 }
                 if(c==2){
                         System.out.println(a+"*"+b+"=");
			 result = a * b;
		}
                 if(c==3){
                      if(b==0){
                             while(b==0) 
                             b=(int)(Math.random()*10);//防止分母为0
            }
                      else{ 
                         System.out.println(a+"/"+b+"=");
                         int smaller = a > b ? b : a;//将a与b中的最小值赋给变量
                         for (int i = 1; i <= smaller; i++) {
				 if (a % i == 0 && b % i == 0) {
					 g = i;
				 }//求a与b的最大公因子
			 }
			 a = a/g;
			 b = b/g;
			 s = a+"/"+b;
        }   
    }
  } 
}

//实现四则运算

import java.util.*;
public class YunSuan {
	public static void main (String args[]){
		int x,z=0;
		Zheng zheng = new Zheng();
		System.out.print("请输入要生成的题目数:");
		Scanner reader = new Scanner(System.in);
		int n = reader.nextInt();
		Random random = new Random();
		for(int i=1;i<n+1;i++){
		for(;;){
			System.out.println("题目"+i+":");
			zheng.Zheng();
			System.out.print("请输入结果:");
			if(zheng.c==3){
				Scanner sc=new Scanner(System.in);
				String s =new String();
			        s =sc.nextLine();
				if(s.equals(zheng.s)){
					z++;
					System.out.println("此题正确");
			}
		        	else
			        	System.out.println("此题错误,正确答案为:"+zheng.s);
			}
			else{
			x =reader.nextInt();
			if(x==zheng.result){
				z++;
			        System.out.println("此题正确");
			}
			else
				System.out.println("此题错误,正确答案为:"+zheng.result);
			
			}
		        break;
              }
            }
	    int o =(int)(((double)z/(double)n)*100);//计算正确率
            System.out.print("完成"+n+"道题,正确数目为:"+z+",正确率为:");
	    System.out.printf("%d",o);
	    System.out.println("%");
	}
}

简单四则运算码云链接:链接

考虑到多种因素后

当发现需要考虑括号、运算优先级以及多个数字计算的因素时,发现事情没那么简单,然后疯狂脑阔疼.........,在看到栈以及中缀转后缀等问题后,陷入了沉思,在通过长时间的学习和理解后才知道如何解决括号与计算问题,之前没有这些知识前,根本无从下手,通过最终地艰苦奋斗还是设计出代码,但是还是有些问题,代码如下:

//生成随机数

import java.util.*;
public class RandomNum {
	int RandomNum(int x){
		int num =(int)(Math.random()*x);
		return num;
	}
}

//生成随机运算符
import java.util.*;
public class RandomChar {
	 char RandomChar(){
        int num = (int)(Math.random()*4);
        switch (num){
            case 0:return'+';
            case 1:return'-';
            case 2:return'*';
            case 3:return'÷';
            default:return 0;
        }
    }
}

//生成中缀表达式以及产生题目

import java.util.*;
public class Produce {
	void Produce(int n){
		RandomNum num = new RandomNum();
		RandomChar c = new RandomChar();
		Scanner reader = new Scanner(System.in);
		String s = "";
		String d = "";
		String g = "";
		String out = "";//最终的中缀表达式
		String end = "";//转化后的后缀表达式
		int count = 0;//记录做对的题目个数
	        for(int i=1;i<n+1;i++){
			System.out.println("题目"+i+":");
			int a = (int)(Math.random()*5+1);
		        int amount = num.RandomNum(a)+1;//记录随机产生运算符的个数
			for(int j=0;j<amount;j++){
			s = s+c.RandomChar()+" ";
			}
			String str[] = s.split(" ");//将字符串转化成字符串数组
			for(int z=0;z<str.length;z++){
				d = d+num.RandomNum(50)+str[z];
			}
			d = d + num.RandomNum(50);
			switch((num.RandomNum(2))){
				case 0:
					System.out.println(d+" = ");//输出不带括号的中缀表达式
					break;
				case 1:
				        for(int k=0;k<str.length;k++){
					       g = num.RandomNum(50)+ str[num.RandomNum(str.length-1)] + "(" + num.RandomNum(50) + str[num.RandomNum(str.length-1)] + num.RandomNum(50) + ")" + str[k];
					}//在中缀表达式中加入括号
					g = g + num.RandomNum(50);
					System.out.println(g+" = ");//输出不带括号的中缀表达式
                                        break;

			}
			out = g;
			out = d;
			int p = 0;//初始化最终得到的答案
			infixToSuffix in = new infixToSuffix();
			end = in.infixToSuffix(out);//将中缀表达式转化为后缀表达式
			suffixToArithmetic ex = new suffixToArithmetic();
			p = (int) ex.suffixToArithmetic(end);//计算后缀表达式的结果
		        System.out.print("请输入结果:");
			int x = reader.nextInt();
			if(x==p){
				System.out.println("结果正确!");
				count++;
			}
			else{
				System.out.println("结果错误,正确结果是:"+p);
			}
			s="";
			g="";
			d="";
		}
		int result = (int)(((double)count/(double)n)*100);//计算正确率
		System.out.println("总共答题"+n+"道,正确率为:"+result+"%");
	}
	
}

//将中缀表达式转化为后缀表达式

import java.util.*;
public class infixToSuffix {
public static String infixToSuffix(String infix) {
        Stack<Character> stack = new Stack<Character>();
        String suffix = "";
        int length = infix.length();
        for (int i = 0; i < length; i++) {
            Character temp;
            char c = infix.charAt(i);
            switch (c) {
                // 忽略空格
                case ' ':
                    break;
                // 碰到'(',push到栈
                case '(':
                    stack.push(c);
                    break;
                // 碰到'+''-',将栈中所有运算符弹出,送到输出队列中
                case '+':
                case '-':
                    while (stack.size() != 0) {
                        temp = stack.pop();
                        if (temp == '(') {
                            stack.push('(');
                            break;
                        }
                        suffix += " " + temp;
                    }
                    stack.push(c);
                    suffix += " ";
                    break;
                // 碰到'*''/',将栈中所有乘除运算符弹出,送到输出队列中
                case '*':
                case '/':
                    while (stack.size() != 0) {
                        temp = stack.pop();
                        if (temp == '(' || temp == '+' || temp == '-') {
                            stack.push(temp);
                            break;
                        } else {
                            suffix += " " + temp;
                        }
                    }
                    stack.push(c);
                    suffix += " ";
                    break;
                // 碰到右括号,将靠近栈顶的第一个左括号上面的运算符全部依次弹出,送至输出队列后,再丢弃左括号
                case ')':
                    while (stack.size() != 0) {
                        temp = stack.pop();
                        if (temp == '(')
                            break;
                        else
                            suffix += " " + temp;
                    }
                    // suffix += " ";
                    break;
                //如果是数字,直接送至输出序列
                default:
                    suffix += c;
            }
        }

        //如果栈不为空,把剩余的运算符依次弹出,送至输出序列。
        while (stack.size() != 0) {
            suffix += " " + stack.pop();
        }
        return suffix;
    }
}

//计算后缀表达式的值

import java.util.*;
public class suffixToArithmetic{
	int suffixToArithmetic(String h) {
		Stack<Integer>stack = new Stack<Integer>();
		String b[] = h.split(" ");//将字符串转化为字符串数组
		for(int i=0;i<b.length;i++){
			String c = b[i];
			if((c.equals("+")||c.equals("-"))||(c.equals("*")||c.equals("÷"))){
				int y = stack.pop();
				int x = stack.pop();
				Caculate z = new Caculate();
                                stack.push(z.Caculate(x,y,c));//将运算结果重新压入栈
			}//是运算符,弹出运算数,计算结果
			else{
				stack.push(Integer.valueOf(c));
			}
		}
		return stack.pop();//弹出栈顶元素就是运算最终结果
	}
}

//判定运算符并进行运算

class Caculate{
	int Caculate(int x,int y,String c) {
        if (c.equals("+"))
            return x + y;
        if (c.equals("-"))
            return x - y;
        if (c.equals("*"))
            return x * y;
        if (c.equals("/")){
		if(x<=y||x==0) return 1;
		else return x / y;
	}
	return 0;
    }
}

完善后四则运算码云链接:链接

三、总结分析与运行截图

结对项目总结与分析

开始以为项目应该很快就能完成,发现缺少好多知识后就很难完成这个项目,不得不将新知识学习后再进行编程,在编程中遇到往中缀表达式加入括号的问题,以及除法计算的问题,遇到左右括号数量不等的情况,遇到括号只括住一个数字或者一个运算符的问题,遇到遇见除法无法输出的问题,遇到无法计算出结果的问题,这些问题都在最后与同伴的讨论中得到部分解决,还是有些问题没有得到解决。程序的UML图将在完善程序后的博客中体现。 除法计算问题的截图:

运行截图体现

简单四则运算的运行截图:

部分完善后的运行截图:

四、结对同伴的评价

结对同伴陈敬勇在完成此次项目中的表现非常出色,我们在遇到问题后都能认真讨论得出答案,避免了一个人完成任务时的思维定式的问题,我们相互鼓励支持,相信在下来的完善代码问题的过程中,我们会做的更好。

五、代码托管

代码托管

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部