软件工程个人作业04
【结对成员】张更、陈昌
【设计思路】
定义了4个数组,分别是bracket[4]、numberzi[4]、numberm[4]、sign[4]。Bracket用于存储括号,2代表左双,1代表错括号,-1代表右括号,-2代表右双,0没有括号,初始为0;numberzi用于存储分子,numbermu存储分母,sign存储符号。定义整型sui,用于限制式子的长度,随机生成,取值2-4.。定义整型type,取值范围0-1,1代表分数运算。对于每个式子都随机生成的式子长度sui,for循环sui,生成numberzi[i]、numbermu[i](当为整数时,取1)、sign[i](从i>0开始随机取值,范围0-1,生成符号时,判断是否需要乘除,是,再将取值范围扩大到0-3)。生成分数时,分母的取值范围为numberzi-high(最大值)。当循环次数大于一时,判断符号和运算符前后两个数的大小,看是否需要交换二者的位置(满足减法无负数,除法正分数)。
约分:当为分数时(numbermu==1),将分子赋值给整形变量cc,for循环cc--,直到分子与分母都能整除cc,运算除法,然后break;
加括号:这部分用的是死方法,将所有的情况都考虑到。当运算输有四个数时,此时分三种情况,1.双括号:双括号有四种位置,第一个数前,bracket【0】=2,【1】=-1,【2】=-1。第二个数前,第三个数后,第四个数后。2.单括号:前两个数,前三个数,后两个数,中间两个数,后面三个数,前俩个数和后两个数。3.没有括号。当运算数为三个数时,此时只有两种情况:1.只有一个括号,前两个数,后两个数2.没有括号。当运算数为2时,没有括号。
式子输出:for循环sui,当i=0时,不输出sign;判断type的值,确定式子的格式,整数只输出numberzi,分数全部输出。
计算:首先判断括号的情况,单双((a b) (c d)算但括号)。双括号分左双和右双,左双:从双括号开始,寻找下一个右括号,计算括号中的运算(先乘除,后加减),然后将结果存储在前一个数的位置,依次将后面的数向前移动(bracket、sign、numberzi、numbermu全移),然后再次计算,直至计算完括号中运算,然后寻找下一个后括号,一样运算直指没有右括号;右括号类似。单括号:计算括号中的运算,将后面的数前移,直至没有右括号。每进行一次运算,将sui--。没有括号:for循环sui,直接运算(先乘除,后加减)。数组前移。(注:单括号与双括号为同一层次,二者最后都会进行没有括号的运算)
结果输出:化简numberzi【0】与numbermu【0】,判断如果numbermu【0】=1,则结果为整数,输出numberzi【0】否则输出numberzi【0】与numbermu【0】。
结果验证:将结果转化成字符串的格式(已化简),用户输入的结果保存在一个字符串中,比较二者。
[程序代码]
custominput.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"> <script language="javascript"> function isValidate(form) { sum=form.sum.value; high=form.high.value; low=form.low.value; if(!isNotNull(sum)) { alert("请输入要生成题目数量!"); form.sum.focus(); return false; } if(!isNumber(sum)) { alert("输入不合法,请输入正整数!"); return false; } if(!isNotNull(high)) { alert("请输入取值上限!"); form.high.focus(); return false; } if(!isNumber(high)) { alert("输入不合法,请输入整数!"); return false; } if(!isNotNull(low)) { alert("请输入取值下限!"); form.low.focus(); return false; } if(!isNumber(low)) { alert("输入不合法,请输入整数!"); return false; } return true; } function isNotNull(str) { if(str.length==0) return false; else return true; } function isNumber(str) { for(i=0;i<str.length;i++) { // 每一位都是0~9的数字,如果是第1位,则可以是“-”号 if(str.charAt(i)>='0' && str.charAt(i)<='9' ) //|| str.charAt(i)== '-' && i==0) continue; else return false; } return true; } </script> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>首页</title> </head> <body background="D:\Myworkspace\Arithmetic\WebContent\image/20140331222058_m8QBC.jpeg"> <form name="form1" method="post"action="Generate.jsp" onsubmit="return isValidate(form1)"> <center><h3>四则运算参数定制</h3></center> <table align="center"> <tr> <td> 请输入要出题的题目数量: </td> <td> <input name="sum" type="text" id="sum" maxlength="5" ></td> </tr> <tr> <td> 请输入要出题的上限值: </td> <td> <input name="high" type="text" id="high"maxlength="5"> </td> </tr> <tr> <td> 请输入要出题的下限值: <td> <input name="low" type="text" id="low"maxlength="5"> </td> </tr> <tr> <td>请选择计算的类型: </td> <td> <select name="complex"> <option value=0>无乘除法</option> <option value=1>有乘除法</option> </select> </td> </tr> </table> <center> <td> <input type="reset" value="重新选择"></td> <td> <input type="submit" value="开始答题"></td> </center> </form> </body> </html>
Generate.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 background="D:\Myworkspace\Arithmetic\WebContent\image/137-140514100T2.jpg"> <% String n=request.getParameter("sum");//运算式的数量 int sum=Integer.valueOf(n); String h=request.getParameter("high");//数值上限 int high=Integer.valueOf(h); String l=request.getParameter("low");//数值下限.,./f int low=Integer.valueOf(l); String[] array = new String[sum];//存储运算题 for(int i=0;i<sum;i++) { array[i]=""; } String[] answer = new String[sum]; //题目的答案 String[] canswer = new String[sum];//用户输入的答案 for(int i=0;i<sum;i++) //生成数据 { canswer[i]="name"+i; int numberzi[]=new int [4];//用于存分子 int numbermu[]=new int [4];//用于存分母。如果是整数,分母为1 int bracket[]=new int [4];//用于记录括号的数量与情况 int sign[]=new int [4];//用于存储符号 sign[0]=5;//第一个位置不使用 int sui;//用于随机生成式子的运算数个数 sui=(int)(Math.random()*3)+2; int type=(int)(Math.random()*2); for(int j=0;j<sui;j++) { numberzi[j]=(int)(Math.random()*(high-low))+low; numbermu[j]=1; if(type==1)//分数 { numbermu[j]=(int)(Math.random()*(high-low))+low; while(numbermu[j]==numberzi[j]) numbermu[j]=(int)(Math.random()*(high-low))+low; if(numbermu[j]<numberzi[j])//生成真分数 { int temp=numbermu[j]; numbermu[j]=numberzi[j]; numberzi[j]=temp; } } if(j!=0) { int rule=1;//运算法则 rule=(int)(Math.random()*2); sign[j]=rule; String c=request.getParameter("complex"); if(Integer.parseInt(c)==1)//有乘除 { rule=(int)(Math.random()*4);//O:+ 1:- 2:* 3:/ sign[j]=rule; } if(type==1)//分数 { if(sign[j]==1 && (numberzi[j-1]*numbermu[j])<(numberzi[j]*numbermu[j-1]))//减法无负数 { //分子交换 int temp=numberzi[j-1]; numberzi[j-1]=numberzi[j]; numberzi[j]=temp; temp=numbermu[j-1]; numbermu[j-1]=numbermu[j]; numbermu[j]=temp; } else if(sign[j]==3 && (numberzi[j-1]*numbermu[j])>(numberzi[j]*numbermu[j-1]))//除法真分数 { //分子交换 int temp=numberzi[j-1]; numberzi[j-1]=numberzi[j]; numberzi[j]=temp; //分母交换 temp=numbermu[j-1]; numbermu[j-1]=numbermu[j]; numbermu[j]=temp; } } else if(type==0)//整数 { if(sign[j]==1 && (numberzi[j-1]<numberzi[j]))//减法无负数 { //交换整数 int temp=numberzi[j-1]; numberzi[j-1]=numberzi[j]; numberzi[j]=temp; } if(sign[j]==3 && (numberzi[j-1]>numberzi[j]))//除法真分数 { //交换整数 int temp=numberzi[j-1]; numberzi[j-1]=numberzi[j]; numberzi[j]=temp; } } } }//生成式子 //////////////////////////////////////////////////////////////////////////////////// //约分 for(int j=0;j<sui;j++) { if(numbermu[j]!=1) { for(int cc=numberzi[j];cc>1;cc--) { if(numberzi[j]%cc==0&&numbermu[j]%cc==0) { numberzi[j]=numberzi[j]/cc; numbermu[j]=numbermu[j]/cc; break; } } } } //////////////////////////////////////////////////////////////////////////////////// //加括号 if(sui==4)//四个运算数 { int IsDoS=(int)(Math.random()*3); if(IsDoS==1)//只有一个括号 { int Iswhere=(int)(Math.random()*6); if(Iswhere<3) { bracket[Iswhere]=1; bracket[Iswhere+1]=-1; } else if(Iswhere==3 || Iswhere==4) { bracket[Iswhere-3]=1; bracket[Iswhere-1]=-1; } else { bracket[0]=1; bracket[1]=-1; bracket[2]=1; bracket[3]=-1; } } else if(IsDoS==2)//两个括号 { int IsDb=(int)(Math.random()*4); if(IsDb==0)//双括号在第一个数前 { bracket[0]=2; bracket[2]=-1; bracket[1]=-1; } else if(IsDb==1)//双括号在第二个数前 { bracket[1]=2; bracket[2]=-1; bracket[3]=-1; } else if(IsDb==2)//双括号在第三个数前 { bracket[0]=1; bracket[1]=1; bracket[2]=-2; } else { bracket[3]=-2; bracket[1]=1; bracket[2]=1; } } } else if(sui==3)//三个运算数 { int Iswhere=(int)(Math.random()*2); if(Iswhere==0) { bracket[0]=1; bracket[1]=-1; } else { bracket[1]=1; bracket[2]=-1; } } ////////////////////////输出 for(int k=0;k<sui;k++) { String changeS; switch(sign[k]) { case(0):changeS="+";break; case(1):changeS="-";break; case(2):changeS="*";break; case(3):changeS="/";break; default:changeS="";break; } if(type==1)//分数 { if(k!=0) { array[i]+=changeS; } if(bracket[k]==2) array[i]+="(("; if(bracket[k]==1) array[i]+="("; array[i]+="("+numberzi[k]+"/"+numbermu[k]+")"; if(bracket[k]==-2) array[i]+="))"; if(bracket[k]==-1) array[i]+=")"; } else { if(k!=0) { array[i]+=changeS; } if(bracket[k]==2) array[i]+="(("; if(bracket[k]==1) array[i]+="("; array[i]+=numberzi[k]; if(bracket[k]==-2) array[i]+="))"; if(bracket[k]==-1) array[i]+=")"; } } ///////////////////////////////////////////////////////////////////////////////////// //计算 int temp=0; for(int Isdas=0;Isdas<sui;Isdas++) { if(bracket[Isdas]==1) { temp++; } else if(bracket[Isdas]==2 || bracket[Isdas]==-2) { temp=2; break; } } if(bracket[0]==1&&bracket[2]==1)//面对(a b) (c d) 的情况 temp=1; if(temp==2) { int rec=sui;//定义临时变量表示数组长度 for(int j=0;j<sui-1;j++)//寻找双括号 { if(bracket[j]==2)//左双括号位置为j { for(int k=j+1;k<sui;k++)//从左双括号的下一个位置开始寻找右括号 { if(bracket[k]==-1)//第一个右括号的位置为k { for(int s=j;s<k;s++)//计算括号内的乘除运算式,s初始为双括号内第一个数 { if(sign[s+1]==2)//乘法 { numberzi[s]*=numberzi[s+1]; numbermu[s]*=numbermu[s+1]; rec--;//发生一次运算 } else if(sign[s+1]==3)//除法 { if(numberzi[s+1]==0)//如果下一个数的分子为零,舍弃这个式子,式子的数量循环值减一 { i--; continue; } numberzi[s]*=numbermu[s+1]; numbermu[s]*=numberzi[s+1]; rec--;//发生一次运算 } if(rec!=sui)//如果发生过一次运算 { for(int zg=s+1;zg<sui-1;zg++)//zg初始为参与运算的后面的数 { numberzi[zg]=numberzi[zg+1]; numbermu[zg]=numbermu[zg+1]; sign[zg]=sign[zg+1]; bracket[zg]=bracket[zg+1]; } sui--;//数组长度减一 k--;//括号的位置改变 s--;//重新从参与运算的前面的数开始循环 } } for(int s=j;s<k;s++)//计算括号内的加减运算式,s初始为双括号内第一个数 { if(sign[s+1]==0) { numberzi[s]=numberzi[s]*numbermu[s+1]+numberzi[s+1]*numbermu[s]; numbermu[s]*=numbermu[s+1]; rec--; } else if(sign[s+1]==1)//减法 { numberzi[s]=numberzi[s]*numbermu[s+1]-numberzi[s+1]*numbermu[s]; numbermu[s]*=numbermu[s+1]; rec--; } if(rec!=sui) { for(int zg=s+1;zg<sui-1;zg++)//数组前移 { numberzi[zg]=numberzi[zg+1]; numbermu[zg]=numbermu[zg+1]; sign[zg]=sign[zg+1]; bracket[zg]=bracket[zg+1]; } sui--;//数组长度减一 k--;//括号的位置改变 s--;// } } } } }//左双括号 else if(bracket[j]==-2)//右双括号位置为j { for(int k=j-1;k>=0;k--)//从右双括号的前一个位置开始寻找左括号 { if(bracket[k]==1)//左括号位置为k { for(int s=k;s<j;s++)//计算括号内的乘除法,s初始为括号内的第一个数的位置 { if(sign[s+1]==2)//乘法 { numberzi[s]*=numberzi[s+1]; numbermu[s]*=numbermu[s+1]; rec--; } else if(sign[s+1]==3)//除法 { if(numberzi[s+1]==0)//如果下一个数的分子为零,舍弃这个式子,式子的数量循环值减一 { i--; continue; } numberzi[s]*=numbermu[s+1]; numbermu[s]*=numberzi[s+1]; rec--; } if(rec!=sui)//如果发生乘除运算 { for(int zg=s+1;zg<sui-1;zg++)//zg代表参与运算的后一个数,数组前移 { numberzi[zg]=numberzi[zg+1]; numbermu[zg]=numbermu[zg+1]; sign[zg]=sign[zg+1]; bracket[zg]=bracket[zg+1]; } sui--;//数组长度减一 //k--;//括号的位置改变 // } } for(int s=k;s<j;s++) { if(sign[s+1]==0)//加法 { numberzi[s]=numberzi[s]*numbermu[s+1]+numberzi[s+1]*numbermu[s]; numbermu[s]*=numbermu[s+1]; rec--; } else if(sign[s+1]==1)//减法 { numberzi[s]=numberzi[s]*numbermu[s+1]-numberzi[s+1]*numbermu[s]; numbermu[s]*=numbermu[s+1]; rec--; } if(rec!=sui)//发生加减运算 { for(int zg=s+1;zg<sui-1;zg++)//zg为发生运算的后面的数,数组前移 { numberzi[zg]=numberzi[zg+1]; numbermu[zg]=numbermu[zg+1]; sign[zg]=sign[zg+1]; bracket[zg]=bracket[zg+1]; } sui--;//数组长度减一 //k--;//括号的位置改变 // } } } } } } } else if(temp==1) { int rec=sui; for(int j=0;j<sui-1;j++) { if(bracket[j]==1)//查找左括号的位置 { for(int k=j+1;k<sui;k++)//从左括号的下一个位置起查找右括号的位置 { if(bracket[k]==-1) { for(int s=j;s<k;s++)//计算括号内的乘除运算式,s初始为双括号内第一个数 { if(sign[s+1]==2)//乘法 { numberzi[s]*=numberzi[s+1]; numbermu[s]*=numbermu[s+1]; rec--;//发生一次运算 } else if(sign[s+1]==3)//除法 { if(numberzi[s+1]==0)//如果下一个数的分子为零,舍弃这个式子,式子的数量循环值减一 { i--; continue; } numberzi[s]*=numbermu[s+1]; numbermu[s]*=numberzi[s+1]; rec--;//发生一次运算 } if(rec!=sui)//如果发生过一次运算 { for(int zg=s+1;zg<sui-1;zg++)//zg初始为参与运算的后面的数 { numberzi[zg]=numberzi[zg+1]; numbermu[zg]=numbermu[zg+1]; sign[zg]=sign[zg+1]; bracket[zg]=bracket[zg+1]; } sui--;//数组长度减一 k--;//括号的位置改变 s--;//重新从参与运算的前面的数开始循环 } } for(int s=j;s<k;s++)//计算括号内的加减运算式,s初始为双括号内第一个数 { if(sign[s+1]==0) { numberzi[s]=numberzi[s]*numbermu[s+1]+numberzi[s+1]*numbermu[s]; numbermu[s]*=numbermu[s+1]; rec--; } else if(sign[s+1]==1)//减法 { numberzi[s]=numberzi[s]*numbermu[s+1]-numberzi[s+1]*numbermu[s]; numbermu[s]*=numbermu[s+1]; rec--; } if(rec!=sui) { for(int zg=s+1;zg<sui-1;zg++)//数组前移 { numberzi[zg]=numberzi[zg+1]; numbermu[zg]=numbermu[zg+1]; sign[zg]=sign[zg+1]; bracket[zg]=bracket[zg+1]; } sui--;//数组长度减一 k--;//括号的位置改变 s--;// } } } } } } } /////////////////////////////////////////////////////////没有任何括号的运算 int rec=sui; for(int s=0;s<sui-1;s++)//计算括号内的乘除运算式,s初始为双括号内第一个数 { if(sign[s+1]==2)//乘法 { numberzi[s]*=numberzi[s+1]; numbermu[s]*=numbermu[s+1]; rec--;//发生一次运算 } else if(sign[s+1]==3)//除法 { if(numberzi[s+1]==0)//如果下一个数的分子为零,舍弃这个式子,式子的数量循环值减一 { i--; continue; } numberzi[s]*=numbermu[s+1]; numbermu[s]*=numberzi[s+1]; rec--;//发生一次运算 } if(rec!=sui)//如果发生过一次运算 { for(int zg=s+1;zg<sui-1;zg++)//zg初始为参与运算的后面的数 { numberzi[zg]=numberzi[zg+1]; numbermu[zg]=numbermu[zg+1]; sign[zg]=sign[zg+1]; bracket[zg]=bracket[zg+1]; } sui--;//数组长度减一 //k--;//括号的位置改变 s--;//重新从参与运算的前面的数开始循环 } } for(int s=0;s<sui-1;s++)//计算括号内的加减运算式,s初始为双括号内第一个数 { if(sign[s+1]==0) { numberzi[s]=numberzi[s]*numbermu[s+1]+numberzi[s+1]*numbermu[s]; numbermu[s]*=numbermu[s+1]; rec--; } else if(sign[s+1]==1)//减法 { numberzi[s]=numberzi[s]*numbermu[s+1]-numberzi[s+1]*numbermu[s]; numbermu[s]*=numbermu[s+1]; // System.out.println("\n"+s +" numberzi[s]:"+numberzi[s]+" numbermu[s]:"+numbermu[s]); rec--; } if(rec!=sui) { for(int zg=s+1;zg<sui-1;zg++)//数组前移 { numberzi[zg]=numberzi[zg+1]; numbermu[zg]=numbermu[zg+1]; sign[zg]=sign[zg+1]; bracket[zg]=bracket[zg+1]; } sui--;//数组长度减一 //k--;//括号的位置改变 s--;// } } ///////////////////////////////////////////////////////////////////////////////// //约分 if(numberzi[0]==0) numbermu[0]=1; if(numbermu[0]!=1) { int temp1=(numberzi[0]<0)?(-numberzi[0]):numberzi[0];//将负分子转换成正 int temp2=(numbermu[0]<0)?(-numbermu[0]):numbermu[0];//将负分母转换成正 temp1=(temp1<temp2)?temp1:temp2; for(int cc=temp1;cc>1;cc--) { if(numberzi[0]%cc==0&&numbermu[0]%cc==0) { numberzi[0]=numberzi[0]/cc; numbermu[0]=numbermu[0]/cc; break; } } } if(numbermu[0]==1) { answer[i] = (numberzi[0]+""); } else { answer[i] = (numberzi[0]+"/"+numbermu[0]); } array[i]+="="; out.print(array[i]); %> <br> <form name="form2"method="post"action="Judge.jsp" > 请输入你的答案:<input name="<%=canswer[i] %>" type="text" id="canswer"maxlength="5"> <br> <% } %> <% session.setAttribute("v1",array); session.setAttribute("v2",answer); %> <input type="submit" value="确定"> </form> </body> </html>
Judge.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>结果</title> </head> <body background="D:\Myworkspace\Arithmetic\WebContent\image/judge.jpg"> <% String[] array = (String[])session.getAttribute("v1"); String[] answer = (String[])session.getAttribute("v2"); String[] canswer = new String[array.length]; %> <table border="1" width="80%" align="center" > <th>题号<th>题目<th>正确答案<th>你的答案<th>批阅 <% for(int i=0;i<array.length;i++) { canswer[i]=request.getParameter("name"+i); %> <tr> <td align="center"><%=i+1 %></td> <td align="center"><%=array[i] %></td> <td align="center"><%=answer[i] %></td> <td align="center"><%=canswer[i] %></td> <% if(canswer[i].equals(answer[i])) { %> <td align="center"><img src="D:\Myworkspace\Arithmetic\WebContent\image/true.png"/></td> <% } else { %> <td align="center"><img src="D:\Myworkspace\Arithmetic\WebContent\image/false.png"/></td> <% } %> </tr> <% } %> </table> </body> </html>
[结果截图]
输入错误:
答案输入:
结果:
【时间记录表】
日期 | 开始时间 | 结束时间 | 总计 | 活动 | 备注 |
2016.3.28 | 8.00 | 10.00 | 100 | 上课 | |
2016.3.29 | 15.20 | 18.00 | 150 | 看书讨论 | 先写出来,在写成网页版 |
2016.3.30 | 15.00 | 17.00 | 120 | 设计程序 | |
2016.3.31 | 15.30 | 17.40 | 130 | 编程 | Java |
2016.4.4 | 19.00 | 21.00 | 120 | 编程 | Java |
2016.4.5 | 19.00 | 21.30 | 150 | 编程 | Java |
2016.4.6 | 15.00 | 21.00 | 240 | 编程,找错 | 吃饭 |
2016.4.7 | 15.30 | 21.00 | 200 | 找错 | 吃饭 |
2016.4.9 | 15.00 | 21.00 | 200 | 改错 | 吃饭 |
2016.4.10 | 15.00 | 19.00 | 200 | 将程序写成网页版 | jsp |
2016.4.11 | 8.00 | 10.00 | 100 | 上课 | |
2016.4.12 | 15.00 | 21.00 | 240 | 继续将程序改成网页版 |