软件工程结对作业01

实验要求:

 

 

结对开发    陶雨洁,李慧

 

一、设计思想

 此实验是在JAVA版且连接SQL Server数据库的四则运算上改成网页版的四则运算。

1.首先呢,我们得先建立数据库shiTiKu和数据表shiTiKu02,定义好列。

2.首先可以先设置一个登陆界面jsp,暂时我们先设置一个用户(用户名和密码均为123),用JavaScript来判断输入是否有误。

3.当用户名和密码输入正确后,即进入题目设置界面。此处设置几个参数(包括:题目数量,取值范围,是否由乘除,是否有加减,是否包含括号),进而传递至下一个页面。

4.然后再连接数据库,利用已经写好的java bean,输出题目,然后等用户输入答案之后,用session来传递题目和用户的答案等其他信息至下一个页面。

5.判定题目正确与否,用session得到上一个页面传递而来的题目和用户输入的答案,插入至数据库中,然后判断用户输入的答案是否与正确答案一致。

6.一致时,输出表示√的图片;不一致时,输出×的图片,并输出正确答案。

7.浏览历史错题,即可对数据表中插入一个mask列,值=0,表示√;值=1,表示×。用sql语句,在数据库中查询mask=1,即输出错题。

如果当一个用户变成多个用户,也是这个道理,也是在数据表中加一个user列,用sql语句,在数据库中查询即可。

 

二、源程序代码

 java bean类

package shiti;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

//�������ݿ��װ�࣬
/*
 * ��̬�����л�����ݿ�����ӡ��ر����ݿ�
 */
public class DBUtil {
    private static final String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver";// ����MySQL���ݿ��������Ϣ
    private static final String url = "jdbc:sqlserver://localhost:1433;DatabaseName=shiTiKu";// ����SQL Server���ݿ���û���
    private static final String userName = "sa";// ����SQL Server���ݿ���û���
    private static final String userPwd = "218028";// �������ݿ���û���������
   // private static final String dbName = "shiTiKu";// ���ݿ���
   private static Connection conn=null;
   private static PreparedStatement pstmt=null;
   private static ResultSet rs=null;
    
    public static void main(String[] args) {
      conn = getDBConnection();
      //  PreparedStatement pstmt = null;
       // ResultSet rs = null;
        closeRS(conn, pstmt, rs);
    }
    
    public static Connection getDBConnection() {
        // ��������URL
       // String url1 = "jdbc:jtds:sqlserver://localhost:1433/" + dbName;
        //String url2 = "?user=" + userName + "&password=" + userPwd;
        //String url3 = "&useUnicode=true&characterEncoding=UTF-8";
        //String url = url1 + url2 + url3;

        //Connection conn = null;

        try {
            Class.forName(driverName);// ע������
            conn = DriverManager.getConnection(url,userName,userPwd);// �������
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return conn;

    }

    // �ͷ���Դ
    public static void closeRS(Connection conn, PreparedStatement pstmt, ResultSet rs) {

        try {
            if (rs != null) {
                rs.close();
            }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
                try {
                    if (conn != null) {
                        conn.close();
                    }
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
}
DBUtil.java
package shiti;

public class FenShu {
    private int denominator, numerator;
    private boolean chengLi;

    public int getDenominator() {
        return denominator;
    }

    public void setDenominator(int denominator) {
        this.denominator = denominator;
    }

    public int getNumerator() {
        return numerator;
    }

    public void setNumerator(int numerator) {
        this.numerator = numerator;
    }

    public boolean isChengLi() {
        return chengLi;
    }

    public void setChengLi(boolean chengLi) {
        this.chengLi = chengLi;
    }

    public FenShu(int numerator, int denominator) {
        this.numerator = numerator;
        this.denominator = denominator;
        if (denominator == 0) {
            this.chengLi = false;
        } else {

            this.chengLi = true;
            yueJian();
        }
    }

    // 根据字符串构造分数
    public FenShu(String str) {
        if(str == null)
        {
            this.chengLi = false;
        }
        int index = str.indexOf("/");
        if (index == -1) {
            this.numerator = Integer.parseInt(str);
            this.denominator = 1;
            this.chengLi = true;

        } else {
            this.denominator = Integer.parseInt(str.substring(index + 1));
            if (this.denominator == 0) {
                chengLi = false;
            } else {
                chengLi = true;
                int zhengShu = str.indexOf("'");
                if (zhengShu == -1) {
                    // 没有整数部分
                    this.numerator = Integer.parseInt(str.substring(0, index));
                } else {
                    // 有整数部分
                    this.numerator = Integer.parseInt(str.substring(0, zhengShu)) * this.denominator
                            + Integer.parseInt(str.substring(zhengShu + 1, index));
                }
                yueJian();
            }
        }
    }

    public FenShu() {
    }

    // 约简
    private void yueJian() {
        int y = 1;
        for (int i = numerator; i > 1; i--) {
            if (numerator % i == 0 && denominator % i == 0) {
                y = i;
                break;
            }
        }
        // int nc = numerator,dc = denominator;
        // if(nc != 0){
        // while(nc != dc - nc){
        // y = dc - nc;
        // if(nc > y){
        // dc = nc;
        // nc = y;
        // }else{
        // dc = y;
        // }
        // }
        // y = nc;
        //
        numerator /= y;
        denominator /= y;

    }

    //
    public FenShu add(FenShu b) {

        FenShu c = null;
        if (this.chengLi && b.isChengLi()) {
            int nNumerator = this.numerator * b.getDenominator() + this.denominator * b.getNumerator();
            int nDenominator = this.denominator * b.getDenominator();
            c = new FenShu(nNumerator, nDenominator);
        } else {
            c = new FenShu();
            c.setChengLi(false);
        }
        return c;
    }

    //
    public FenShu subtract(FenShu b) {
        FenShu c = null;
        if (this.chengLi && b.isChengLi()) {
            int nNumerator = this.numerator * b.getDenominator() - this.denominator * b.getNumerator();
            int nDenominator = this.denominator * b.getDenominator();
            c = new FenShu(nNumerator, nDenominator);
        } else {
            c = new FenShu();
            c.setChengLi(false);
        }
        return c;
    }

    //
    public FenShu multiply(FenShu b) {
        FenShu c = null;
        if (this.chengLi && b.isChengLi()) {

            int nNumerator = this.numerator * b.getNumerator();
            int nDenominator = this.denominator * b.getDenominator();
            c = new FenShu(nNumerator, nDenominator);
        } else {
            c = new FenShu();
            c.setChengLi(false);
        }
        return c;
    }

    //
    public FenShu divide(FenShu b) {
        FenShu c = null;
        if (this.chengLi && b.isChengLi() && (b.getNumerator() != 0)) {

            int nNumerator = this.numerator * b.getDenominator();
            int nDenominator = this.denominator * b.getNumerator();
            c = new FenShu(nNumerator, nDenominator);
        } else {
            c = new FenShu();
            c.setChengLi(false);
        }
        return c;
    }

    // 输出分数形式
    public String toString() {
        if (this.chengLi) {
            if (numerator != 0) {
                if (numerator % denominator == 0)
                    return "" + numerator / denominator;
                else if (numerator > denominator) {
                    return (numerator / denominator) + "'" + (numerator % denominator) + "/" + denominator;
                }
                return numerator + "/" + denominator;
            }
            return "0";
        }
        return "ERROR";
    }
    

}
FenShu.java
package shiti;

public class MyException extends Exception {
    public MyException(String msg) {
        // TODO Auto-generated constructor stub
        super(msg);
    }
}
MyException.java
package shiti;

import java.util.Stack;

public class ShiTi {
    private int id;
    private String tiMu;// 题目
    private String answer;// 答案
    private String calculateOrder;// 运算式计算顺序,(后缀表达式)
    private int countNumber;// 运算符个数
    private String userAnswer;
    private int mask;

    public String getuserAnswer() {
        return userAnswer;
    }

    public void setuserAnswer(String userAnswer) {
        this.userAnswer = userAnswer;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTiMu() {
        return tiMu;
    }

    public void setTiMu(String tiMu) {
        this.tiMu = tiMu;
        try {
            expressCalculate();
        } catch (MyException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }// 计算答案
        this.countNumber = (tiMu.split(" ").length + 1) / 2;
    }

    public String getAnswer() {
        return answer;
    }

    public void setAnswer(String answer) {
        this.answer = answer;
    }

    public String getCalculateOrder() {
        return calculateOrder;
    }

    public void setCalculateOrder(String calculateOrder) {
        this.calculateOrder = calculateOrder;
    }

    public int getCountNumber() {
        return countNumber;
    }

    public void setCountNumber(int countNumber) {
        this.countNumber = countNumber;
    }

       public int getMask(){return mask;}
    
    public void setMask(int mask){this.mask=mask;}
    public ShiTi() {

    }

    // 表达式计算,参数为字符串类型的运算式
    private void expressCalculate() throws MyException {
        if(this.tiMu == null)
        {
            throw new MyException("试题无效");
        }
        String express = this.tiMu;
        
        
        Stack<String> num = new Stack<String>();
        Stack<String> symbolS = new Stack<String>();
        symbolS.push("#");
        express += "#";
        String order = "";
        char ch;
        int i = 0;
        ch = express.charAt(i);
        while ((!symbolS.peek().equals("#")) || (ch != '#')) {// while循环开始
            if (isNumber(ch)) {// 读到的不是空格,说明开始读运算数
                String readNumStr = "";
                while (true) {
                    readNumStr += ch;
                    ch = express.charAt(++i);
                    if (ch == ' ' || ch == '#' || ch == ')') {// 读到的是空格,或,说明运算数结束
                        break;
                    }
                }
                num.push(readNumStr);
            } else if (ch == ' ') {
                if ((i + 1) < express.length()) {// 未到字符串末尾
                    ch = express.charAt(++i);
                }
            }else {// 读到的是运算符
                char compare = priorityCompare(symbolS.peek(), ch + "");

                if (compare == '=') {// 若优先级相等,则说明ch是右括号,栈顶为左括号,此时将栈顶弹出,读取下一个字符
                    symbolS.pop();
                    ch = express.charAt(++i);
                } else if (compare == '>') {// ch的优先级小于栈顶的优先级,要说明栈顶的运算符应该先计算,所以应弹栈运算
                                            // 弹出两个运算数,弹出一个运算符
                    String bStr = num.pop();
                    String aStr = num.pop();
                    String symbolT = symbolS.pop();
                    // 计算该字表达式
                    String c = yunSuan(aStr, bStr, symbolT);
                    if (c.equals("ERROR")) {// 如果计算函数返回error则说明计算过程出现了负数,说明该运算式不符合要求,停止计算,计算结果为error,返回;
                        this.answer = "ERROR";
                        return;
                    } else {// 计算过程正常,则将计算结果压栈
                        order += aStr + "," + symbolT + "," + bStr + ",";// 将运算的子表达式加进运算顺序字符串中,操作数和操作符用逗号隔开
                        num.push(c);
                    }
                } else if(compare == 'E')
                {
                    this.answer = "ERROR";
                    return;
                } else {// 说明ch优先级大于栈顶元素的优先级,则应将ch压栈,读取下一个运算符
                    symbolS.push(ch + "");
                    if ((i + 1) < express.length()) {
                        ch = express.charAt(++i);
                    }
                }

            }
        }
        this.answer = num.pop();
        this.calculateOrder = order;
    }

    // 判断ch是否为数字
    private boolean isNumber(char ch) {
        if (ch >= '0' && ch <= '9') {
            return true;
        }
        return false;
    }

    /*
     * 子表达式计算,参数为两个运算数的字符串形式,和一个运算符,也为字符串类型 返回计算结果的字符串形式
     * 如果减法运算出现负数,或除数为0,或分数的分母为0则返回ERROR
     * 
     */
    private String yunSuan(String aStr, String bStr, String symbol) throws MyException {
        if(aStr == null || bStr == null || symbol == null)
        {
            throw new MyException("子表达式出现错误!");
        }
        int adivIndex = aStr.indexOf("/");
        int bdivIndex = bStr.indexOf("/");
        if ((adivIndex == -1) && (bdivIndex == -1)) {// a.b都是整数
            int a = Integer.parseInt(aStr);
            int b = Integer.parseInt(bStr);
            switch (symbol.charAt(0)) {
            case '+':
                return a + b + "";
            case '-': {
                if (a < b) {
                    return "ERROR";
                }
                return a - b + "";
            }
            case '×': {
                return a * b + "";
            }
            case '÷': {
                if (b == 0) {
                    return "ERROR";
                } else if (a % b == 0) {
                    return a / b + "";
                }
                return new FenShu(a, b).toString();
            }
            default:
                return "ERROR";
            }
        } else {// a,b中存在分数,则将a,b都当做分数进行运算
            FenShu a = new FenShu(aStr);
            FenShu b = new FenShu(bStr);
            switch (symbol.charAt(0)) {
            case '+':
                return a.add(b).toString();
            case '-':
            {
                FenShu c = a.subtract(b);
                if(c.getNumerator() < 0)
                {
                    return "ERROR";
                }
                return c.toString();
            }
            case '×':
                return a.multiply(b).toString();
            case '÷':
                return a.divide(b).toString();
            default:
                return "ERROR";
            }
        }
    }

    // 判断运算符优先级
    private char priorityCompare(String a, String b) {
        char[][] priority = { { '>', '>', '<', '<', '<', '>', '>' }, { '>', '>', '<', '<', '<', '>', '>' },
                { '>', '>', '>', '>', '<', '>', '>' }, { '>', '>', '>', '>', '<', '>', '>' },
                { '<', '<', '<', '<', '<', '=', '>' }, { '>', '>', '>', '>', ' ', '>', '>' },
                { '<', '<', '<', '<', '<', ' ', '=' } };
        int a_index = index_symbol(a);
        int b_index = index_symbol(b);
        if(a_index == -1 || b_index == -1)
        {
            return 'E';
        }
        return priority[a_index][b_index];
    }

    // 获取运算符对应的下标
    private int index_symbol(String a) {
        String p = "+-×÷()#";
        // System.out.println("判断运算符对应的下标:" + a);
        return p.indexOf(a);
    }

}
ShiTi.java
package shiti;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

//试题数据库操作类,即对数据库进行增删改查的操作的类
public class ShiTiDAO {
    private String INSERT_SQL = "insert into shiTiKu02(tiMu,answer,calculateOrder,countNumber,userAnswer,mask) values(?,?,?,?,?,?)";
    private String SELECTBYNUMBERCOUNT_SQL = "select * from shiTiKu02 where countNumber=?";
    private String SELECTBYMASK_SQL = "select * from shiTiKu02 where mask=?";//寻找错题
    private String SELECTALL = "select * from shiTiKu02";
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        ShiTiDAO dao=new ShiTiDAO();
        Connection conn = null;

        conn = DBUtil.getDBConnection();// 获取连接

    }
    // 向数据库中插入一条记录
    public void insert(ShiTi stb) throws SQLException, MyException {
        if(stb == null)
        {
            throw new MyException("试题无效!");
        }
        
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;

        conn = DBUtil.getDBConnection();// 获取连接

        pstmt = conn.prepareStatement(INSERT_SQL);// 获取操作对象

        // 设置字段值
        pstmt.setString(1, stb.getTiMu());
        pstmt.setString(2, stb.getAnswer());
        pstmt.setString(3, stb.getCalculateOrder());
        pstmt.setInt(4, stb.getCountNumber());

        // 执行
        pstmt.executeUpdate();
        // 释放资源
        DBUtil.closeRS(conn, pstmt, rs);

    }

    // 向数据库中插入多条记录,参数为list
    public void insert(List<ShiTi> list) throws SQLException, MyException{
        if(list == null)
        {
            throw new MyException("试题无效!");
        }

        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;

        conn = DBUtil.getDBConnection();// 获取连接

        pstmt = conn.prepareStatement(INSERT_SQL);// 获取操作对象

        // 设置字段值
        for (ShiTi stb : list) {
            pstmt.setString(1, stb.getTiMu());
            pstmt.setString(2, stb.getAnswer());
            pstmt.setString(3, stb.getCalculateOrder());
            pstmt.setInt(4, stb.getCountNumber());
            pstmt.setString(5,stb.getuserAnswer());
            pstmt.setInt(6,stb.getMask());
            pstmt.executeUpdate();
        }

        // 执行
        // 释放资源
        DBUtil.closeRS(conn, pstmt, rs);

    }

    // 根据运算数个数查询,返回结果为list
    public List<ShiTi> selectByNumbercount(int count) throws SQLException, MyException {
        if(count < 2)
        {
            throw new MyException("运算数个数应大于等于2");
        }
        
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        List<ShiTi> list = new ArrayList<ShiTi>();

        conn = DBUtil.getDBConnection();// 获取连接

        pstmt = conn.prepareStatement(SELECTBYNUMBERCOUNT_SQL);// 获取操作对象

        // 设置字段值
        pstmt.setInt(1, count);

        // 执行
        rs = pstmt.executeQuery();
        // 结果处理
        ShiTi stb = null;
        while (rs.next()) {
            stb = new ShiTi();
            stb.setTiMu(rs.getString("tiMu"));
            stb.setAnswer(rs.getString("answer"));
            stb.setCalculateOrder(rs.getString("calculateOrder"));
            stb.setCountNumber(rs.getInt("countNumber"));
            stb.setuserAnswer(rs.getString("userAnswer"));
            stb.setMask(rs.getInt("mask"));
            list.add(stb);
        }

        // 释放资源
        DBUtil.closeRS(conn, pstmt, rs);
        return list;

    }
    
    public List<ShiTi> selectByMask(int mask) throws SQLException, MyException {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        List<ShiTi> list = new ArrayList<ShiTi>();

        conn = DBUtil.getDBConnection();// 获取连接

        pstmt = conn.prepareStatement(SELECTBYMASK_SQL);// 获取操作对象

        // 设置字段值
        pstmt.setInt(1, mask);

        // 执行
        rs = pstmt.executeQuery();
        // 结果处理
        ShiTi stb = null;
        while (rs.next()) {
            stb = new ShiTi();
            stb.setTiMu(rs.getString("tiMu"));
            stb.setAnswer(rs.getString("answer"));
            stb.setCalculateOrder(rs.getString("calculateOrder"));
            stb.setCountNumber(rs.getInt("countNumber"));
            stb.setuserAnswer(rs.getString("userAnswer"));
            stb.setMask(rs.getInt("mask"));
            list.add(stb);
        }

        // 释放资源
        DBUtil.closeRS(conn, pstmt, rs);
        return list;

    }
    
    
    
    
    //查询数据库中的全部记录
    public List<ShiTi> selectAll() throws SQLException {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        List<ShiTi> list = new ArrayList<ShiTi>();

        conn = DBUtil.getDBConnection();// 获取连接

        pstmt = conn.prepareStatement(SELECTALL);// 获取操作对象


        // 执行
        rs = pstmt.executeQuery();
        // 结果处理
        ShiTi stb = null;
        while (rs.next()) {
            stb = new ShiTi();
            stb.setTiMu(rs.getString("tiMu"));
            stb.setAnswer(rs.getString("answer"));
            stb.setCalculateOrder(rs.getString("calculateOrder"));
            stb.setCountNumber(rs.getInt("countNumber"));
            stb.setuserAnswer(rs.getString("userAnswer"));
            stb.setMask(rs.getInt("mask"));
            list.add(stb);
        }

        // 释放资源
        DBUtil.closeRS(conn, pstmt, rs);
        return list;

    }


}
ShiTiDAO
package shiti;

import java.util.Random;

//试题类,
/*
 * 方法有:生成一个试题,计算试题答案,
 * 
 * 
 */
public class ShiTiOperator {
/*    // 获取一个运算式
    public static void main(String[] args) {
        ShiTi a = new ShiTi();
        a.setTiMu("4 + 2 / 3 - 1");//设置题目a
        System.out.println("答案为:" + a.getAnswer());
//        ShiTi b = new ShiTi();
//        b.setTiMu("2 + 1 + 4 + 3");//设置题目b
//        System.out.println("是否重复判断结果为:" + calculateOrderSame(a, b));
        
    }*/
    
    
    public static ShiTi getExpress(int maxNum, int hasChengChu,int hasKuoHao, int type) throws MyException {

        if(maxNum <= 0)
        {
            throw new MyException("最大数值应为正数");
        }
        
        ShiTi stb = new ShiTi();

        Random rd = new Random();
        char[] fuHao = { '+', '-', '×', '÷' };
        int fuHaoFanWei = 2 + 2 * hasChengChu;
        while (true) {
            int[] bracket = null;// 存储括号位置
            int expressLength = rd.nextInt(3) + 2;// 随机生成一个2~4之间的整数作为该运算式的运算数的个数
            stb.setCountNumber(expressLength);
            String[] number = new String[expressLength];// 存储运算数的数组
            String[] symbol = new String[expressLength - 1];// 存储运算符的数组

            String express = "";
            number[0] = getOperatorNumber(type, maxNum);
            for (int i = 0; i < expressLength - 1; i++) {
                symbol[i] = fuHao[rd.nextInt(fuHaoFanWei)] + "";// 生成运算符
                number[i + 1] = getOperatorNumber(type, maxNum);
            }

            if (hasKuoHao == 1) {
                // 需要加括号
                bracket = randomAddBracket(expressLength);
            }

            // 构建表达式
            for (int i = 0; i < expressLength; i++) {
                // 添加左括号
                if (hasKuoHao == 1) {
                    for (int j = 0; j < bracket[i]; j++) {
                        express += "(";
                    }
                }

                express += number[i];// 加上运算数

                // 添加右括号
                if (hasKuoHao == 1) {
                    for (int j = 0; j > bracket[i]; j--) {
                        express += ")";
                    }
                }

                if (i != expressLength - 1) {
                    express += " " + symbol[i] + " ";// 加运算符,并在两侧加空格来与运算数分隔
                }

            }
            stb.setTiMu(express);
            if (!(stb.getAnswer().equals("ERROR"))) {
                // System.out.println("生成的运算式为:" + express + "=" + result[0]);
                return stb;
            }
        }

    }

    // 随机生成括号,参数为运算式的运算数的个数
    private static int[] randomAddBracket(int length) throws MyException {
        if(length <= 1)
        {
            throw new MyException("运算式长度不能小于2");
        }
        int[] brackets = new int[length];
        for (int i = 0; i < brackets.length; i++)
            brackets[i] = 0;
        Random rd = new Random();
        for (int i = 2; i < length; i++) {// 添加的括号长度(括号包围的运算数的个数)
            for (int j = 0; j < length - i + 1; j++) {
                int t = rd.nextInt(2);// 随机生成0或1,0代表不加括号,1代表加括号
                if (t == 1) {
                    if (brackets[j] >= 0 && brackets[j + i - 1] <= 0) {// 要加的括号的第一个运算数周围没有右括号,且
                                                                        // 最后一个运算数周围没有左括号
                        int counteract1 = 0,counteract2 = 0,counteract3 = 0;
                        for (int k = j; k < j + i; k++) {// 将要加的括号之间的所有运算数对应的brackets相加,
                                                            // 如果和为0说明这个括号之间的括号是匹配的,不会出现括号交叉现象
                            counteract1 += brackets[k];
                        }
                        for (int k = 0; k < j - 1; k++) {// 将要加的括号之前的所有运算数对应的brackets相加,
                            // 如果和为0说明这个括号之间的括号是匹配的,不会出现括号交叉现象
                            counteract2 += brackets[k];
                        }
                        for (int k = j + i; k < length; k++) {// 将要加的括号之后的所有运算数对应的brackets相加,
                            // 如果和为0说明这个括号之间的括号是匹配的,不会出现括号交叉现象
                            counteract3 += brackets[k];
                        }
                        
                        if (counteract1 == 0 && counteract2 == 0 && counteract3 == 0) {
                            brackets[j]++;
                            brackets[j + i - 1]--;
                            j += i;
                        }
                    }
                }
            }
        }
        return brackets;
    }

    // 随机生成一个运算数( type==0代表生成整数,type==1代表生成真分数,maxNum代表数值范围 0~(maxNum-1) )
    private static String getOperatorNumber(int type, int maxNum) throws MyException {
        if(maxNum <= 0)
        {
            throw new MyException("最大数值应为正数");
        }
        Random rd = new Random();
        int a;
        while (true) {
            a = rd.nextInt(maxNum);
            if (type == 0) {// 随机生成一个整数
                return "" + a;
            } else {// 随机生成一个真分数
                if (a == 0) {
                    continue;
                }
                int b = rd.nextInt(a);
                FenShu c = new FenShu(b, a);
                return c.toString();
            }
        }
    }
    
//--------------------------------------------------
    
    public static boolean calculateOrderSame(ShiTi a, ShiTi b) throws MyException {

        if(a == null || b == null)
        {
            throw new MyException("试题无效!");
        }
        //比较两个运算式的运算数个数
        if(a.getCountNumber() != b.getCountNumber())
        {
            return false;
        }
        
        //比较两运算式的答案是否相同
        if(!a.getAnswer().equals(b.getAnswer()))
        {
            return false;
        }
        
        // 取出运算式的运算顺序字符串,
        String aorder = a.getCalculateOrder();
        String border = b.getCalculateOrder();

        // 将a,b运算式的运算顺序字符串进行分割,按序取出每一个运算数和运算符
        String[] asplit = aorder.split(",");
        String[] bsplit = border.split(",");

        int n = a.getCountNumber() - 1;//共有n组子表达式
        
        for(int i = 0;i < n;i++)
        {
            //取a运算式该子表达式的两个运算数a1,a2,运算符af,运算结果ar
            String a1 = asplit[0 + i * 3];
            String af = asplit[1 + i * 3];
            String a2 = asplit[2 + i * 3];
            //取b运算式该子表达式的两个运算数b1,b2,运算符bf,运算结果br
            String b1 = bsplit[0 + i * 3];
            String bf = bsplit[1 + i * 3];
            String b2 = bsplit[2 + i * 3];

            if(af.equals(bf))
            {
                //两子表达式符号相同
                if(a1.equals(b1) && a2.equals(b2))
                {
                    continue;//该子表达式相同,继续判断下一个子表达式
                }
                else if(  (af.equals("+") || af.equals("×"))   &&   a1.equals(b2)  && a2.equals(b1)   )
                {
                    continue;//该子表达式相同,继续判断下一个子表达式
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }
        return true;
    }
    
    //--------------------------------------------------

    
    

    

}
ShiTiOperator.java
package shiti;

import java.util.ArrayList;
import java.util.List;
/*
 * 随机生成四则运算式3
 * 
 * 
 */

public class SiZe3 {

    
    // 生成整数计算式添加限制条件,type为运算式类型 0代表整数式,1代表真分数式
    public static List<ShiTi> createYunSuanShi(int hasChengChu,int hasKuoHao, int maxNum, int n, int type) throws MyException {
        int i = 0;
        if(n <= 0)
        {
            throw new MyException("运算数个数设置错误,应为正数");
        }
        List<ShiTi> list = new ArrayList<ShiTi>();
        ShiTi stb = null;
        // ShiTiDAO std = new ShiTiDAO();
        while (i < n) {
            stb = ShiTiOperator.getExpress(maxNum, hasChengChu,hasKuoHao, type);

            // 检验重复
            boolean chongFu = false;
            for (int j = 0; j < i; j++) {
                ShiTi t = list.get(j);
                if (ShiTiOperator.calculateOrderSame(stb, t)) {
                    chongFu = true;
                    System.out.println("出现重复:计算式一:" + t.getTiMu() + " = " + t.getAnswer() + " 运算顺序:"
                            + t.getCalculateOrder() + " 运算数个数:" + t.getCountNumber());
                    System.out.println("出现重复:计算式二:" + stb.getTiMu() + " = " + stb.getAnswer() + " 运算顺序:"
                            + stb.getCalculateOrder() + " 运算数个数:" + stb.getCountNumber());
                    System.out.println("\n\n");
                    break;
                }
            }
            if (chongFu == false) {
                list.add(stb);
                i++;
            }
        }
        return list;
    }

}
SiZe3.java

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>
<style type="text/css">
<!--
body,td,th {
    font-family: Times New Roman, Times, serif;
    color: #000000;
}
body {
    background-color: #FFFFFF;
}
-->
</style>
<script type="text/javascript">
    function checkNull()
    {
        if(document.getElementById("name").value==""){
            alert("未填用户名!");
            return false;
        }    
        if(document.getElementById("passwd").value==""){
            alert("未填密码!");
            return false;
        }
        if((document.getElementById("passwd").value=="123") && (document.getElementById("name").value=="123")){
            alert("登陆成功!");
            return true;
        }
        if((document.getElementById("passwd").value!="123") || (document.getElementById("name").value!="123")){
            alert("登陆失败!");
            return false;
        }
    }
    </script>
</head>
<body>

<form name="form1" method="post" action="SET.jsp">
 <center>
 <table width="460" height="210" border="1" cellpadding="0" cellspacing="5" bordercolor="#FFFFFF" bgcolor="#FFFFFF">
   <tr bgcolor="#CCFF99">
     <th height="60" bordercolor="#FFFFFF" scope="col"> <label>登陆</label></th>
   </tr>
   <tr bgcolor="#CCFF99">
     <th height="41" bordercolor="#FFFFFF" scope="col"> <label><span class="STYLE1"> 用户名
           <input id="name" type="text" name="name"  style="width:200px; height:18px;" size="20">
     </span></label></th>
   </tr>
   <tr bgcolor="#CCFF99">
     <th height="41" bordercolor="#FFFFFF" scope="col"> <label><span class="STYLE1">&nbsp;&nbsp;&nbsp;<input id="passwd" type="password" name="passwd"  style="width:200px; height:18px;" size="20">
     </span></label></th>
   </tr>
   <tr bgcolor="#CCFF99">
     <th height="41" bordercolor="#FFFFFF" scope="col"> <label><span class="STYLE1">
       <input type="submit" name="submit" value="登陆" onClick="return checkNull()">
       <input type="reset" name="reset" value="重置">
     </span></label></th>
   </tr>
      <tr bgcolor="#CCFF99">
     <th height="27" bordercolor="#FFFFFF" scope="col"> <label>如果还没有账号,请<a href="sign.jsp">注册</a>...</label></th>
   </tr>
 </table>
 </center>
</form>
</body>
</html>
login.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>
<center>
  还未实现此功能,点击跳转至<a href="login.jsp">登陆</a>界面......
</center>

</body>
</html>
sign.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>
<script type="text/javascript">
    function checkNull()
    {
        if(document.getElementById("number").value==""){
            alert("题目数不能为空!");
            return false;
        }    
        if(document.getElementById("range").value==""){
            alert("数值范围不能为空!");
            return false;
        }
    }
    </script>
<style type="text/css">
<!--
.STYLE1 {font-size: large}
.STYLE3 {
    color: #FF0033;
    font-family: "Times New Roman", Times, serif;
    font-style: italic;
}
-->
</style>
</head>
<body>
<%
request.setCharacterEncoding("utf-8");
String name=(String)request.getParameter("name");
String passwd=(String)request.getParameter("passwd");
%>
<form name="form1" method="post" action="Dati.jsp">
<h5 align="center" class="STYLE3">欢迎用户<%=name%>进入答题系统~&nbsp;</h5>
<h5 align="center" class="STYLE3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &nbsp;    &nbsp;    &nbsp;&nbsp;  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;    &nbsp;  &nbsp;  &nbsp;    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;     
                &nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  
                &nbsp;  &nbsp;    &nbsp;    &nbsp;  &nbsp;  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &nbsp;  &nbsp;    &nbsp;  &nbsp; 
                 &nbsp;  &nbsp;  &nbsp;    &nbsp;  &nbsp;  &nbsp;&nbsp;&nbsp; 
                 <a href="person.jsp">查看历史错题</a>.<a href="https://www.baidu.com/">帮助</a><a href="login.jsp">.退出</a></h5>
<table align="center" width="460" height="39" border="1" cellpadding="0" cellspacing="5" bordercolor="#FFFFFF" bgcolor="#FFFFFF">
   <tr bgcolor="#CCFF99">
     <th height="27" colspan="2" bordercolor="#FFFFFF" scope="col"> <label><span class="STYLE1">四则运算题目设置</span></label></th>
   </tr>
   <tr bgcolor="#CCFF99">
     <td height="27" colspan="2" align="center" bordercolor="#FFFFFF" scope="col"> <label><span class="STYLE1"> * 题目数量
           <input id="number" type="text" name="number"  style="width:60px; height:18px;" size="7">
     </span></label></td>
   </tr>
   <tr bgcolor="#CCFF99">
     <td height="27" colspan="2" align="center" bordercolor="#FFFFFF" scope="col"> <label><span class="STYLE1"> * 数值范围
       <input id="range" type="text" name="range"  style="width:60px; height:18px;" size="7">
     </span></label></td>
   </tr>
   <tr bgcolor="#CCFF99">
     <td height="27" colspan="2" align="center" bordercolor="#FFFFFF" scope="col"> <label> </label>
         <span class="STYLE1">
           <label>
         <input name="type" type="radio" value="0" checked>
             整数式</label>
           <label>
           <input name="type" type="radio" value="1">
             分数式</label>
      </span></td>
   </tr>
   <tr bgcolor="#CCFF99">
     <td height="27" colspan="2" align="center" bordercolor="#FFFFFF" scope="col"> <label> </label>
         <span class="STYLE1">
           <label>
         <input name="cc" type="radio" value="0" checked>
             无乘除</label>
           <label>
             <input name="cc" type="radio" value="1">
             有乘除</label>
      </span></td>
   </tr>
   <tr bgcolor="#CCFF99">
     <td height="27" colspan="2" align="center" bordercolor="#FFFFFF" scope="col"> <label></label>
         <span class="STYLE1">
         <label>
         <input name="checkbox" type="radio" value="1">
           有括号</label>
           <label>
         <input name="checkbox" type="radio" value="0" checked>
             无括号</label>
      </span></td>
   </tr>
   <tr bgcolor="#CCFF99">
     <td height="27" colspan="2" align="center" bordercolor="#FFFFFF" scope="col"> <label><span class="STYLE1">
       <input type="submit" name="submit" value="生成题目" onClick="return checkNull()">
       <input type="reset" name="reset" value="重置">
     </span></label></td>
   </tr>
 </table>
 </center>
</form>
</body>
</html>
SET.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
   import="java.util.*,shiti.*" pageEncoding="gb2312"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
    
<!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>

<style type="text/css">
<!--
#Layer1 {
    position:absolute;
    width:583px;
    height:233px;
    z-index:1;
    left: 357px;
    top: 58px;
}
.STYLE1 {font-size: medium}
-->
</style>
</head>
<body>
     <p>
  <!-- 从前一个页面中获得信息 -->
<%
request.setCharacterEncoding("utf-8");
int number=Integer.parseInt(request.getParameter("number"));
int range=Integer.parseInt(request.getParameter("range"));
int type=Integer.parseInt(request.getParameter("type"));
int cc=Integer.parseInt(request.getParameter("cc"));
int checkbox=Integer.parseInt(request.getParameter("checkbox"));
%>
<!-- 将试题个数number和试题list存入session对象中,用于在判断试题页面使用 -->
<%
List<ShiTi> list = SiZe3.createYunSuanShi(cc,checkbox, range, number, type);
session.setAttribute("number", number);
session.setAttribute("list", list);
%>
</p>
 <center>
<table width="460" height="60" border="1" cellpadding="0" cellspacing="5" bordercolor="#FFFFFF" bgcolor="#FFFFFF">
 <tr bgcolor="#CCFF99">
    <th height="48" colspan="2" bordercolor="#FFFFFF" scope="col">
      <label><span class="STYLE4">开始答题</span></label></th>
    </tr>
    </table>
</center>
 <form name="form1" method="post" action="judge_Dati.jsp">
<%
for(int i=0;i<number;i++)
{
 ShiTi a=list.get(i);
 String s=a.getTiMu();
 %>
 <center>
<table width="460" height="39" border="1" cellpadding="0" cellspacing="5" bordercolor="#FFFFFF" bgcolor="#FFFFFF">
<tr align="left" bgcolor="#CCFF99">
    <th width="56" height="27" align="center" valign="baseline" bordercolor="#FFFFFF" scope="col"><div align="center">
      <%out.print(i+1);%>
    </div></th>
    <td width="375" valign="baseline" nowrap bordercolor="#FFFFFF" scope="col"><%out.print(s+" = ");%>
      <label>
      <input type="text" name="<%=(i + 1) %>" style="width:60px; height:18px;" size="7">
      </label></td></tr>
</table>
     <%
     }
%> 
<table width="460" height="39" border="1" cellpadding="0" cellspacing="5" bordercolor="#FFFFFF" bgcolor="#FFFFFF">
 <tr bgcolor="#CCFF99">
    <td height="27" colspan="2" align="center" bordercolor="#FFFFFF" scope="col">
     <label>
     <input type="submit" name="submit" style="width:60px; height:20px;" value="确认交卷">
     </label>     </td>
  </tr>
    </table>
 </center>
 </form>
</body>
</html>
Dati.jsp
<%@ page language="java" contentType="text/html; charset=utf-8" import="java.util.*,shiti.*,java.sql.*"
    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>
<style type="text/css">
<!--
.STYLE2 {font-size: xx-small}
.STYLE4 {font-size: large}
-->
</style>
</head>
<body>
<%
/* 获取session中的试题信息(试题总数和试题list) */
request.setCharacterEncoding("utf-8");
int number=(Integer)(session.getAttribute("number"));
List<ShiTi> list = (List<ShiTi>) session.getAttribute("list");
/* 将试题信息从session中删除 */
session.removeAttribute("number");
session.removeAttribute("list");

/* 创建新的试题list2存用户的答案和题目 */
List<ShiTi> list2 = new ArrayList<ShiTi>(); 
%>
 <center>
<table width="460" height="60" border="1" cellpadding="0" cellspacing="5" bordercolor="#FFFFFF" bgcolor="#FFFFFF">
 <tr bgcolor="#CCFF99">
    <th height="48" colspan="2" bordercolor="#FFFFFF" scope="col">
      <span class="STYLE4">
      <label>答题评判</label>
      </span></th>
    </tr>
   </table>
</center>

<!-- 判断答案的正确与错误 -->
<%
String[] msg=new String[number];
String[] tii=new String[number];
int wrong=0;
for(int i=0;i<number;i++)
{
    String userAnswer=request.getParameter((i+1)+"");
    int mask;
    ShiTi st=list.get(i);
    if(st.getAnswer().equals(userAnswer))
    {
        msg[i]="dui";
        tii[i]="";
        mask=0;
        }
    else
    {
        msg[i]="cuo";
        tii[i]="  THE KEY = "+st.getAnswer();/* 正确答案 */
        mask=1;
        wrong++;
        }
 %>
 
<!--  将新的信息存入数据库中 -->
<%
st.setuserAnswer(userAnswer);//将用户的答案存入试题对象
st.setMask(mask);
list2.add(st);//将试题对象存入试题list2,
}//for
%>
<!-- 连接数据库方法1 -->
 <!-- 将添加用户答案后的试题信息shiTiList2存入数据库 -->
<%
ShiTiDAO stdao = new ShiTiDAO();//构建一个操作数据库的对象
stdao.insert(list2);//调用操作数据库对象的插入方法将试题信息插入到数据库
%>
<!-- 页面上展示 -->
<%
for(int i=0;i<number;i++)
{
    ShiTi st = list2.get(i);
    %>
<center>
<table width="460" height="39" border="1" cellpadding="0" cellspacing="5" bordercolor="#FFFFFF" bgcolor="#FFFFFF">
<tr align="center" bgcolor="#CCFF99">
    <th width="56" height="27" valign="baseline" bordercolor="#FFFFFF" scope="col">
    <div align="center"><%out.print(i+1);%> </div></th>
    <td width="375" valign="baseline" nowrap bordercolor="#FFFFFF" scope="col">
    <div align="left"><%out.print(st.getTiMu()+" = "+st.getuserAnswer());%> 
    <div align="right"><img src="images/<%=msg[i] %>.png"><span class="STYLE2"><%=tii[i] %></span></div>
    </div></td>      
    </tr>
</table>
<%
}
%>
<table width="460" height="39" border="1" cellpadding="0" cellspacing="5" bordercolor="#FFFFFF" bgcolor="#FFFFFF">
 <tr bgcolor="#CCFF99">
    <th height="27" colspan="2" bordercolor="#FFFFFF" scope="col">
     <form name="form1" method="post" action="SET.jsp">
        <label>
      <input type="submit" name="submit" style="width:60px; height:18px;" value="返回">
      </label>  
   </form>
     </th>
  </tr>
   </table>
</center>
</body>
</html>
judge_Dati.jsp
<%@ page language="java" contentType="text/html; charset=utf-8" import="java.util.*,shiti.*,java.text.DecimalFormat"
    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>
<style type="text/css">
<!--
.STYLE2 {
    font-size: x-small;
    color: #006600;
}
.STYLE3 {color: #FF0000}
.STYLE4 {color: #330000}
-->
</style>
</head>
<body>
<!-- 从试题库中查询错题 -->
<%
request.setCharacterEncoding("utf-8");
ShiTiDAO stdao = new ShiTiDAO();//构建一个操作数据库的对象
List<ShiTi> list3=stdao.selectByMask(1);
int wrongNum=list3.size();
List<ShiTi> list=stdao.selectAll();
int number=list.size();
float f=wrongNum*100/number;
%>
<center>
<table width="460" height="99" border="1" cellpadding="0" cellspacing="5" bordercolor="#FFFFFF" bgcolor="#FFFFFF">
 <tr bgcolor="#CCFF99">
    <th height="48" colspan="2" bordercolor="#FFFFFF" scope="col">
      <label><span class="STYLE4"><span class="STYLE3">错题集</span><br>
    <div align="right">  <span class="STYLE2">[</span><span class="STYLE2">错误率:<%=f %>%]</span></div></label></th>
    </tr>
    
   <!--  循环的内容 -->
   <%
   for(int i=0;i<wrongNum;i++){
       ShiTi st=list3.get(i);
       %>
<table width="460" height="39" border="1" cellpadding="0" cellspacing="5" bordercolor="#FFFFFF" bgcolor="#FFFFFF">
<tr align="center" bgcolor="#CCFF99">
    <th width="56" height="27" valign="baseline" bordercolor="#FFFFFF" scope="col">
    <div align="center"><%out.print(i+1);%> </div></th>
    <td width="375" valign="baseline" nowrap bordercolor="#FFFFFF" scope="col">
    <div align="left"><%out.print(st.getTiMu()+" = "+st.getAnswer());%> 
    </div></td>      
    </tr>
</table>
<%
}
%>
<table width="460" height="39" border="1" cellpadding="0" cellspacing="5" bordercolor="#FFFFFF" bgcolor="#FFFFFF">
 <tr bgcolor="#CCFF99">
    <th height="27" colspan="2" bordercolor="#FFFFFF" scope="col">
     <form name="form1" method="post" action="SET.jsp">
        <label>
      <input type="submit" name="submit" style="width:60px; height:18px;" value="返回">
      </label>  
   </form>     </th>
  </tr>
   </table>
  </table>
</center>
</body>
</html>
person.jsp

 

三、运行结果截图

 开始进入主页面(登陆界面,login.jsp,界面比较简陋)

然后输入用户名和密码(因为还没实现用户注册和登陆功能,所以先只设定了一个用户,其用户名和密码均为123)

如果错误将会出现提示

 

 如果需要注册,则出现如下界面(sign.jsp)

登陆成功之后,则进入题目设置界面(SET.jsp)

此处进行题目设置,还可以浏览历史错题(错题集,并统计错误率);帮助链接至百度页面;退出链接至登陆界面。

 首先,我们先进行题目设置吧~

然后点击生成题目,进入答题界面(Dati.jsp)

 

 输入答案,之后,点击确认交卷,即进入评判界面(judge_Dati.jsp)

 

接着,返回到题目设置界面(SET.jsp),此处,我们可以试着点击查看历史错题(person.jsp)

 点击底端的返回按钮,就重新回到了SET.jsp页面。

 

数据表显示如下

 

 

四、编程总结

①补充:其实可以实现多个用户登录注册的功能。就是再新建一个用户的数据表,进行增删改查,然后在试题的数据表中增加用户这一列,用SQL语句就可以实现加入多个用户后的四则运算功能。

②此程序的JAVA类其实不完全是我们写的,我们写的JAVA类的实现的四则运算的功能很少,但此次实验的主要目的就是将JAVA版的四则运算改成网页版的。我们之后,会再学习四则运算的JAVA代码。

posted @ 2017-04-06 10:36  夏小暑  阅读(385)  评论(0编辑  收藏  举报