4网页版四则运算
4
n 详细要求:
n 1、 生成的题目中计算过程不能产生负数,也就是说算术表达式中如果存在形如e1 − e2的子表达式,那么e1 ≥ e2。
n 2、生成的题目中如果存在形如e1 ÷ e2的子表达式,那么其结果应是真分数。
n 3、每道题目中出现的运算符个数不超过3个,括号不限。
n 4、程序一次运行生成的题目不能重复,即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目。
n 例如,23 + 45 = 和45 + 23 = 是重复的题目,6 × 8 = 和8 × 6 = 也是重复的题目。
n 3+(2+1)和1+2+3这两个题目是重复的,由于+是左结合的,1+2+3等价于(1+2)+3,也就是3+(1+2),也就是3+(2+1)。但是1+2+3和3+2+1是不重复的两道题,因为1+2+3等价于(1+2)+3,而3+2+1等价于(3+2)+1,它们之间不能通过有限次交换变成同一个题目。
n 5、把程序变成一个网页程序, 用户通过设定参数,就可以得到各种题目,并可实现在线答题并评判。
在第三次实验的基础上,老师又对此提出了新的要求,实现网页版四则运算。
设计思想:因为是网页版的所以就会使用jsp,html与java文件之间的数据交换
代码:
Test.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="java.util.*" %> <% BinaryTree bTree; %> <% bTree = new BinaryTree(2);%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <% System.out.println("欢迎使用本系统,本系统自动产生四则运算表达式."); //JOptionPane.showMessageDialog(null,"欢迎使用本系统,本系统自动产生四则运算表达式。"); int count1=0;//答对的题目个数 int count2=0;//答错的题目个数 boolean flag;//判断答案的对错*/ double time1=System.currentTimeMillis();%> <form action="BinaryTree.jsp" method="post"> <center> <% for(int i = 0; i < 10; i++) { //这里 bTree.createBTree(); String result = bTree.CalAndVal(); int n=Integer.parseInt(result); System.out.println(bTree.toString() + "=" + "答案:");//result); Scanner in=new Scanner(System.in); int d=in.nextInt(); if(d==n) { flag=true; System.out.println("恭喜你,答对啦!"); ++count1; } else{ flag=false; ++count2; System.out.println("答错啦,再努力!"); } } double time2=System.currentTimeMillis(); int time=(int)((time2-time1)/1000); if(count1>count2){ System.out.println("成绩不错,继续保持!"); } else{ System.out.println("该努力啦,加油~~!"); } System.out.println("答对的题有:"+count1+"个"+"\n"+"答错的题有:"+count2+"个"+"\n"+"所用时间为:"+time+"秒");//最后统计答对题数答错的题目的个数 %> </body> </html>
Ran.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="java.util.Random;" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <% public static char getOperator(){ char operator = 0; Random ran = new Random(); int i = ran.nextInt(4); switch(i){ case 0: operator = '+'; break; case 1: operator = '-'; break; case 2: operator = '*'; break; case 3: operator = '/'; break; } return operator; } /** * 根据输入的范围获取随机数 * * @param max * @return number */ public static int getNumber(int max){ int number = 0; Random ran = new Random(); number = ran.nextInt(max+1); return number; } /** * 根据运算符的个数随机产生子节点的位置 * * @param num * @return childPlace */ public static boolean[] getChildPlace(int num){ int d = 0; int size = 0, j=1; while(num >= (int)Math.pow(2, j)){ j++; } d = (int)Math.pow(2, j) - 1 - num; size = (int)Math.pow(2, j-1); boolean[] k = new boolean[size]; for(int i = 0; i < size; i++){ k[i] = true; } for(int i = 0; i < d; i++){ Random ran = new Random(); int f = ran.nextInt(size); while(k[f] == false) { f = ran.nextInt(size); } k[f] = false; } return k; } %> </body> </html>
BinaryTree.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="java.util.ArrayList;" %> <%private TreeNode root; private int num; private ArrayList<TreeNode> opeList = new ArrayList<TreeNode>(); %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <form action="TreeNode.jsp" method="post"> <center> <form action="BinaryTree.jsp" method="post"> <center> <% {this.num = num; } public int getNum(){ return num; } public void setNum(int num){ this.num = num; } public void setTreeNode(TreeNode root){ this.root = root; } /** * 获取最终的表达式,必须在CalAndVal()方法后调用 * * @return str */ public String toString(){ String str = root.toString(); str = str.substring(1, str.length()-1); return str; } /** * 计算并验证表达式 * * @return result */ public String CalAndVal(){ return root.getResult(); } /** * 计算二叉树的深度(层数) * * @return deep */ public int getDeep(){ int i = this.num; int deep = 2; while(i/2 > 0){ deep++; i /= 2; } return deep; } /** * 生成二叉树 * */ public void createBTree(){ TreeNode lchild, rchild, lnode, rnode; if(num == 1){ lchild = new TreeNode(String.valueOf(Ran.getNumber(10)), null, null); rchild = new TreeNode(String.valueOf(Ran.getNumber(10)), null, null); root = new TreeNode(String.valueOf(Ran.getOperator()), lchild, rchild); } else{ int num1 = 0; int n = getDeep() - 3; boolean[] place = Ran.getChildPlace(num); root = new TreeNode(String.valueOf(Ran.getOperator()), null, null); opeList.add(root); for(int i = 0; i < n; i++){ for(int j = 0; j < (int)Math.pow(2, i); j++, num1++){ lchild = new TreeNode(String.valueOf(Ran.getOperator()), null, null); rchild = new TreeNode(String.valueOf(Ran.getOperator()), null, null); opeList.get(j + num1).setChild(lchild, rchild); opeList.add(lchild); opeList.add(rchild); } } for(int i = 0; i < place.length; i++){ if(place[i]){ lnode = new TreeNode(String.valueOf(Ran.getNumber(10)), null, null); rnode = new TreeNode(String.valueOf(Ran.getNumber(10)), null, null); if(i%2 == 0){ lchild = new TreeNode(String.valueOf(Ran.getOperator()), lnode, rnode); opeList.add(lchild); opeList.get(num1).setLchild(lchild); } else{ rchild = new TreeNode(String.valueOf(Ran.getOperator()), lnode, rnode); opeList.add(rchild); opeList.get(num1).setRchild(rchild); } } else{ if(i%2 == 0){ lchild = new TreeNode(String.valueOf(Ran.getNumber(10)), null, null); opeList.get(num1).setLchild(lchild); } else{ rchild = new TreeNode(String.valueOf(Ran.getNumber(10)), null, null); opeList.get(num1).setRchild(rchild); } } num1 = num1 + i%2; } } %> </body> </html>
TreeNode.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <% private String str; private TreeNode rchild = null; private TreeNode lchild = null; // public TreeNode(String str) { this.str = str; } // public TreeNode(String str, TreeNode lchild, TreeNode rchild) { this.str = str; this.rchild = rchild; this.lchild = lchild; } public void setChild(TreeNode lchild, TreeNode rchild){ this.lchild = lchild; this.rchild = rchild; } public TreeNode getRchild() { return rchild; } public void setRchild(TreeNode rchild) { this.rchild = rchild; } public TreeNode getLchild() { return lchild; } public void setLchild(TreeNode lchild) { this.lchild = lchild; } public String getStr(){ return str; } /** * 获取每个节点的运算结果,并检验除法 * 1)除数为0 * 2)不能整除 * 出现以上两种情况的话将该运算符转换成其他三种运算符 * * @return result */ public String getResult(){ if(hasChild()){ switch(str){ case "+": return String.valueOf(Integer.parseInt(getLchild().getResult()) + Integer.parseInt(getRchild().getResult())); case "-": return String.valueOf(Integer.parseInt(getLchild().getResult()) - Integer.parseInt(getRchild().getResult())); case "*": return String.valueOf(Integer.parseInt(getLchild().getResult()) * Integer.parseInt(getRchild().getResult())); case "/": if(getRchild().getResult().equals("0")){ while(str.equals("/")){ str = String.valueOf(Ran.getOperator()); } return this.getResult(); } else if(Integer.parseInt(getLchild().getResult()) % Integer.parseInt(getRchild().getResult()) != 0){ while(str.equals("/")){ str = String.valueOf(Ran.getOperator()); } return this.getResult(); } else return String.valueOf(Integer.parseInt(getLchild().getResult()) / Integer.parseInt(getRchild().getResult())); } } return str; } /** * 先对每个运算式添加括号,然后根据去括号法则,去掉多余的子式的括号 * * @return string */ public String toString(){ String Lstr = "", Rstr = "", Str = ""; if(hasChild()){ //右子树如果有孩子,说明右子树是一个表达式,而不是数字节点。 if(getRchild().hasChild()){ //判断左邻括号的运算符是否为'/' if(str.equals("/")){ //获取右子树的表达式,保留括号 Rstr = getRchild().toString(); } //判断左邻括号的运算符是否为'*'或'-' else if(str.equals("*") || str.equals("-")){ //判断op是否为'+'或'-' if(getRchild().str.equals("+") || getRchild().str.equals("-")){ Rstr = getRchild().toString(); } else{ //获取右子树的表达式,并且去括号 Rstr = getRchild().toString().substring(1, getRchild().toString().length()-1); } } else{ //右子树除此之外都是可以去括号的。 Rstr = getRchild().toString().substring(1, getRchild().toString().length()-1); } } else{ Rstr = getRchild().str; } //左子树的情况同右子树类似 if(getLchild().hasChild()){ if(str.equals("*") || str.equals("/")){ if(getLchild().str.equals("+") || getLchild().str.equals("-")){ Lstr = getLchild().toString(); } else{ Lstr = getLchild().toString().substring(1, getLchild().toString().length()-1); } } else{ Lstr = getLchild().toString().substring(1, getLchild().toString().length()-1); } } else{ Lstr = getLchild().str; } //获取当前的运算式,并加上括号 Str = "(" + Lstr + str + Rstr + ")"; } else{ //若没有孩子,说明是数字节点,直接返回数字 Str = str; } return Str; } public boolean hasChild(){ if(lchild == null && rchild == null) return false; else return true; } %> </body> </html>
截图:
总结:不出现重复,没有实现。有些地方没有转换好程序无法运行,一些功能不知道怎样实现,还需要继续学习