zoukankan      html  css  js  c++  java
  • 2018-2019-2 《Java程序设计》结对项目阶段总结《四则运算——整数》(二)

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

    一、需求分析

    实现一个命令行程序,要求:

    • 自动生成小学四则运算题目(加,减,乘,除)
      • 文本支持整数
      • 支持多运算符(例如生成包含n个运算符的题目)
      • 支持真分数(后续实现)
    • 统计正确率

    扩展需求

    • 文件:
      • 处理生成题目并输出到文件
      • 完成题目后从文件读入并判断
    • 多语言支持:简体中文,繁體中文,English
    • 生成题目去重

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

    最开始看到这个结对项目的时候,我觉得,最为第一个项目,应该不会很难。而在真正看到项目的时候,也感觉不是很难。在这一点上,我和我的搭档是同一个想法,都觉得还行。但是越是往后做,就越发现,这怎么这么复杂...其实,是这样的,最开始,我们没有考虑到括号、运算优先级以及多个数字运算的问题,就只是简单设计了一个两个数字简单的四则运算,这个程序呢,我也发出来了,如下:

    //生成随机整数的运算

    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图,我们暂时还未弄好,在后面的结对项目中我们会补上)

    代码运行截图

    四则运算简版运行截图:

    四则运算运行截图:

    四、结对同伴的评价

    在这次项目中,我的搭档张智敏同学是驾驶员的身份,而我是领航员的身份。在这次项目中,我的搭档充分体现了驾驶员的身份,所有代码都是他操控键盘打出来的。并且在遇到问题的时候,他都分析得很仔细认真,所以大多数问题都是他先想出解决办法并最后解决的,所以我认为我的搭档非常棒。在以后的项目中,我们会合作得更好,希望我能帮到我的搭档更多,争取把我们的项目做得更好。

    五、代码托管

    代码托管

  • 相关阅读:
    Python之旅.第八章.网络编程
    Python之旅.第八章网络编程
    Python之旅.第八章.网络编程
    Python之旅.第七章.异常处理
    Python之旅.第六章.面向对象高级
    第五章.面向对象.总结
    Python之旅.第五章.面向对象.
    Python之旅.第五章.面向对象
    Python之旅.第五章.面向对象
    flexible.js
  • 原文地址:https://www.cnblogs.com/cjy-123/p/10707112.html
Copyright © 2011-2022 走看看