结对编程评价队友代码

队友使用C++实现该个人项目,十分地面向过程

1、首先是用户初始化

  

   优点:使用map方便检索

  缺点:增加用户比较麻烦

2、main函数实现 登陆、生成题目、切换题目难度功能

  其中使用while循环来实现各功能界面间切换的功能,第一层while循环是登陆,登陆成功进入第二层循环生成题目,若输入“切换为XX”,但XX不为小学初中高中的任意一个,会进入第三层循环要求输入以上任一难度。

  优点:层次分明,层层递进

  缺点:如果界面数量变多,继续使用该方法会使得代码臃肿,可读性变差

3、使用流水线方式生成一道题目

  操作数的可能性为1~5个,将1个操作数的情况与其余情况分开考虑,其中小学不能生成1个操作数的题目

  只有一个操作数时:

    初中题目会固定生成带有根号或者平方的式子,操作数为1~100

    高中题目会固定生成带有三角函数的式子,不过函数里的数字是从给定的数组中选取,数组如下

    

    然后要保证tan值要存在,即(数字+90°)%180 != 0

  2~5个操作数时,使用流水线的方式生成,即一个一个地生成操作数,在生成操作数的过程中使用随机数不断判断是否插入左右括号、根号、平方,或者判断该操作数是否用三角函数替代。需要保证具体代码如下:

#level是题目难度,其中0代表小学,1代表初中,2代表高中
string GetOneQuestion(int level)
{
    stringstream ss;
    int bracketNum = 0;    //括号的数量,单位为对
    int operateNum;        //操作数
    bool leftBracket;    //判断该操作数前是否有左括号,若有,则在该操作数后不加右括号,因为要避免出现“(?)”的情况
    bool need = false;    //判断是否满足备注要求,初中题目至少一个根号或平方(概率皆为1/2),高中题目至少一个三角函数
    if (level == 0)
    {
        operateNum = 2+rand()%4;    //小学题目2~5个操作数
    }
    else
    {
        operateNum = 1+rand()%5;    //初中和高中题目1~5个操作数
    }

    if (operateNum == 1)
    {
        if (level == 1)
        {
            if (rand()%2 == 0)
            {
                ss << "" << 1+rand()%100;
            }
            else
            {
                ss << 1+rand()%100 << "^2";
            }
        }
        else if (level == 2)
        {
            string fun;
            int num;
            //tan值要存在
            do
            {
                fun = g_triFun[rand()%3];
                num = g_triNum[rand()%46];
            }
            while (fun == "tan(" && (num+90)%180 == 0);
            ss << fun << num << "°" << ')';
        }
    }
    else
    {
        //生成第一个操作数
        if (rand()%4 == 0)
        {
            ss << '(';
            bracketNum++;
        }

        if (level == 1 && rand()%4 == 0)      //根号
        {
            need = true;
            ss <<"";
        }

        if (level == 2 && rand()%4 == 0)      //操作数,或者sin(?)cos(?)tan(?)
        {
            need = true;
            string fun;
            int num;
            //tan值要存在
            do
            {
                fun = g_triFun[rand()%3];
                num = g_triNum[rand()%46];
            }
            while (fun == "tan(" && (num+90)%180 == 0);
            ss << fun << num << "°" << ')';
        }
        else
        {
            ss << 1+rand()%100;
        }

        if (level == 1 && rand()%4 == 0)                  //平方
        {
            need = true;
            ss << "^2";
        }

        //生成后续运算符与操作数
        for (int i = 0; i < operateNum; i++)
        {
            char c = g_operators[rand()%4];                                            //运算符
            ss << c;

            if (level == 1 && (rand()%4 == 0 || (!need && i == operateNum-1 && rand()%2 == 0)))      //根号
            {
                need = true;
                ss <<"";
            }

            leftBracket = false;
            if (rand()%4 == 0 && i != operateNum-1)          //左括号
            {
                ss << '(';
                leftBracket = true;
                bracketNum++;
            }

            if (level == 2 && (rand()%4 == 0 || (!need && i == operateNum-1)))      //操作数,或者sin(?)cos(?)tan(?)
            {
                need = true;
                string fun;
                int num;
                //不能发生除0的情况,并且tan值要存在
                do
                {
                    fun = g_triFun[rand()%3];
                    num = g_triNum[rand()%46];
                }
                while ((c == '/' && ((fun == "sin(" && num%180 == 0) || (fun == "cos(" && (num+90)%180 == 0)))
                        ||(fun == "tan(" && (num+90)%180 == 0));
                ss << fun << num << "°" << ')';
            }
            else
            {
                ss << 1+rand()%100;
            }

            if (level == 1 && rand()%8 == 0)                  //平方在操作数右边
            {
                need = true;
                ss << "^2";
            }
            if (rand()%4 == 0 && bracketNum > 0 && !leftBracket)      //右括号
            {
                ss << ')';
                bracketNum--;
            }
            if (level == 1 && (rand()%8 == 0 || (!need && i == operateNum-1)))                  //平方有可能在括号右边
            {
                need = true;
                ss << "^2";
            }
        }
        while (bracketNum--)
        {
            ss << ')';
        }
    }

    ss << '=';
    if (g_questions.find(ss.str()) != g_questions.end())
    {
        return GetOneQuestion(level);
    }
    else
    {
        g_questions.insert(ss.str());
        return ss.str();
    }
}

  优点:按流程一步步来,清晰明了,有考虑三角函数值能够手算、tan值要存在,当三角函数前一个运算符为除号时,三角函数的值不为0 

  缺点:要按流程仔细考虑,根号、平方、左右括号应该有可能在哪出现都得考虑周全,经常会遗漏某些条件

4、题目查重

  使用set容器实现,将该用户文件夹下所有题目都添加到该集合中,当生成一道题目时,判断是否已保存在集合中,若已存在则再生成一道题目,否则将其输出到文件中并加入到集合里

猜你喜欢

转载自www.cnblogs.com/ling1527/p/11553134.html