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>
截图:
总结:不出现重复,没有实现。有些地方没有转换好程序无法运行,一些功能不知道怎样实现,还需要继续学习。
PSP表格:
日期 | 时间 |
| 工作 |
3.29 | 7:00-9:00 |
| 分析原来的java文件 |
3. 31 | 6:30-10:30 |
| 查看web有关知识 |
4.01 | 7:30-10:30 |
| 查找网页版四则运算例子 |
4.02 | 8:00-10:00 |
| 分析例子 |
4.03 | 8:00-10:00 |
| 看例子改自己的原java文件 |
4.05-4.08 |
|
| 写课堂作业 |
4.09 | 14:30-17:30 18:30-22:00 |
| 写Ran.Jsp和B.jsp和Tree.jsp |
4.10 | 15:00-19:00 |
| 编写程序(由java到jsp) |