小学四则运算练习题生成器 - 结对编程作业

作者
学生1学号:2352521
学生2学号:2352619
本作业主要由学生1完成,学生2辅助。
作业要求
根据第8周PPT的要求,我们需要开发一个能生成300道四则运算练习题的程序,要求:

  1. 包含两个运算符
  2. 数字在100以内
  3. 不需要写答案(但程序需要能检查答案)
  4. 答案在0-1000之间
  5. 以结对编程方式完成
    开发过程
    我们采用了结对编程的方式完成本次作业,具体过程如下:
    我们首先仔细阅读了PPT中的需求,明确了程序需要实现的功能,讨论了是否需要支持括号运算(决定支持),确定了运算符的优先级处理方式,然后决定了程序的基本结构,确定了使用枚举类型表示运算符,之后就开始编写代码,首先学生1负责编写核心计算逻辑,学生2负责审核,然后再角色互换,在完成了所有的代码后,我们共同调试和测试了程序。
    结果:
    我们采用了输出一道题目完成一道题目的形式完成代码,每当你做完一道题时,程序会输出正确或是错误,如果做题人做错了题目,还会接着输出正确的结果和做题过程,让做题人更加容易理解。

    而在做完所有的题目之后,我们还会输出本次做题的正确率,让做题人更加直接地了解到自己本次的训练情况。
    image
    下面是我们代码的功能说明
    题目生成:随机生成包含两个运算符的四则运算题,随机决定是否添加括号,确保数字在100以内,确保答案在0-1000之间且为整数。
    答案检查:答错时显示正确答案和详细计算过程
    统计功能:记录答题总数和正确数,计算并显示正确率

结对编程作业总结
通过这次小学四则运算练习题生成器的结对编程实践,我们对这种开发模式有了深刻的认识和体会。在为期一周的开发过程中,我们两人密切配合,共同完成了从需求分析到最终实现的全部工作。
在技术层面,我们成功实现了一个功能完整的四则运算题目生成系统。系统能够智能处理运算符优先级和括号运算,自动规避除数为零等异常情况,并确保所有题目答案都在合理范围内。特别值得一提的是,当用户回答错误时,系统会详细展示运算步骤,这个教学功能得到了我们的一致好评。通过这次实践,我们不仅巩固了C++编程技能,更深入理解了表达式求值算法的实现原理。
在协作方面,结对编程模式展现出独特的优势。开发过程中,一个人的编码思路可能会陷入局限,而另一个人的实时审核和建议往往能带来突破。例如在处理运算符优先级时,正是通过两人的反复讨论,我们才找到了最优的实现方案。角色轮换的机制也让双方都能从不同角度理解整个项目,避免了知识盲区的出现。当然,这种模式也需要良好的沟通和耐心,特别是在出现意见分歧时,我们学会了通过理性分析和技术验证来达成共识。
这次作业也让我们认识到一些需要改进的地方。例如,在初期我们对需求的理解不够透彻,导致部分功能需要返工;代码注释的规范性也有待加强。这些经验教训将指导我们在未来的项目中做得更好。

以上便是本次作业的全部内容,源代码为:``

点击查看代码
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <sstream>
#include <vector>
#include <string>
#include <set>
using namespace std;

// 定义运算符类型
enum OperatorType {
    ADD, SUB, MUL, DIV
};

// 将运算符枚举转换为字符
char getOperatorChar(OperatorType op) {
    switch (op) {
        case ADD: return '+';
        case SUB: return '-';
        case MUL: return '*';
        case DIV: return '/';
        default: return '+';
    }
}

// 计算表达式结果
double calculateResult(int a, OperatorType op1, int b, OperatorType op2, int c, bool hasBracket) {
    double result = 0;
    
    if (hasBracket) {
        // 有括号的情况,括号内的运算先进行
        double temp = 0;
        if (op2 == ADD) {
            temp = b + c;
        } else if (op2 == SUB) {
            temp = b - c;
        } else if (op2 == MUL) {
            temp = b * c;
        } else {
            // 除法需要检查除数是否为0
            if (c == 0) return -1; // 表示无效结果
            temp = (double)b / c;
        }
        
        // 计算括号外的运算
        if (op1 == ADD) {
            result = a + temp;
        } else if (op1 == SUB) {
            result = a - temp;
        } else if (op1 == MUL) {
            result = a * temp;
        } else {
            // 除法需要检查除数是否为0
            if (temp == 0) return -1; // 表示无效结果
            result = (double)a / temp;
        }
    } else {
        // 无括号的情况,按照运算符优先级计算
        if (op1 == MUL || op1 == DIV) {
            // 第一个运算符优先级高
            double temp = 0;
            if (op1 == MUL) {
                temp = a * b;
            } else {
                // 除法需要检查除数是否为0
                if (b == 0) return -1; // 表示无效结果
                temp = (double)a / b;
            }
            
            // 计算第二个运算
            if (op2 == ADD) {
                result = temp + c;
            } else if (op2 == SUB) {
                result = temp - c;
            } else if (op2 == MUL) {
                result = temp * c;
            } else {
                // 除法需要检查除数是否为0
                if (c == 0) return -1; // 表示无效结果
                result = temp / c;
            }
        } else if (op2 == MUL || op2 == DIV) {
            // 第二个运算符优先级高
            double temp = 0;
            if (op2 == MUL) {
                temp = b * c;
            } else {
                // 除法需要检查除数是否为0
                if (c == 0) return -1; // 表示无效结果
                temp = (double)b / c;
            }
            
            // 计算第一个运算
            if (op1 == ADD) {
                result = a + temp;
            } else {
                result = a - temp;
            }
        } else {
            // 两个运算符优先级相同,从左到右计算
            double temp = 0;
            if (op1 == ADD) {
                temp = a + b;
            } else {
                temp = a - b;
            }
            
            if (op2 == ADD) {
                result = temp + c;
            } else {
                result = temp - c;
            }
        }
    }
    
    return result;
}

// 生成一道题目
string generateQuestion(int& answer, bool& hasBracket, int& a, int& b, int& c, OperatorType& op1, OperatorType& op2) {
    double result;
    
    do {
        // 生成100以内的随机数
        a = rand() % 100 + 1;
        b = rand() % 100 + 1;
        c = rand() % 100 + 1;
        
        // 生成随机运算符
        op1 = (OperatorType)(rand() % 4);
        op2 = (OperatorType)(rand() % 4);
        
        // 随机决定是否添加括号
        hasBracket = (rand() % 2 == 0);
        
        // 计算结果
        result = calculateResult(a, op1, b, op2, c, hasBracket);
        
        // 检查结果是否有效且在0-1000范围内
    } while (result < 0 || result > 1000 || result != (int)result);
    
    // 设置答案
    answer = (int)result;
    
    // 构造题目字符串
    string question;
    if (hasBracket) {
        stringstream ss;
        ss << a << " " << getOperatorChar(op1) << " (" 
           << b << " " << getOperatorChar(op2) << " " 
           << c << ") = ";
        question = ss.str();
    } else {
        stringstream ss;
        ss << a << " " << getOperatorChar(op1) << " " 
           << b << " " << getOperatorChar(op2) << " " 
           << c << " = ";
        question = ss.str();
    }
    
    return question;
}

int main() {
    // 初始化随机数生成器
    srand(time(NULL));
    
    cout << "小学四则运算练习题(共300题)" << endl;
    cout << "请回答每道题目,输入答案后按回车键。" << endl;
    cout << "======================================" << endl << endl;
    
    int totalQuestions = 300;
    int correctCount = 0;
    
    for (int i = 0; i < totalQuestions; i++) {
        int answer;
        bool hasBracket;
        int a, b, c;
        OperatorType op1, op2;
        
        string question = generateQuestion(answer, hasBracket, a, b, c, op1, op2);
        
        cout << i + 1 << ". " << question;
        
        int userAnswer;
        cin >> userAnswer;
        
        if (userAnswer == answer) {
            cout << "正确!" << endl << endl;
            correctCount++;
        } else {
            cout << "错误!正确答案是:" << answer << endl;
            
            // 解释计算过程
            cout << "计算过程:";
            if (hasBracket) {
                double bracketResult;
                if (op2 == ADD) {
                    bracketResult = b + c;
                    cout << "先计算括号内 " << b << " + " << c << " = " << bracketResult << endl;
                } else if (op2 == SUB) {
                    bracketResult = b - c;
                    cout << "先计算括号内 " << b << " - " << c << " = " << bracketResult << endl;
                } else if (op2 == MUL) {
                    bracketResult = b * c;
                    cout << "先计算括号内 " << b << " * " << c << " = " << bracketResult << endl;
                } else {
                    bracketResult = (double)b / c;
                    cout << "先计算括号内 " << b << " / " << c << " = " << bracketResult << endl;
                }
                
                cout << "然后计算 " << a << " " << getOperatorChar(op1) << " " << bracketResult << " = " << answer << endl << endl;
            } else {
                if (op1 == MUL || op1 == DIV || (op1 == ADD || op1 == SUB) && (op2 == ADD || op2 == SUB)) {
                    double firstResult;
                    if (op1 == ADD) {
                        firstResult = a + b;
                        cout << "先计算 " << a << " + " << b << " = " << firstResult << endl;
                    } else if (op1 == SUB) {
                        firstResult = a - b;
                        cout << "先计算 " << a << " - " << b << " = " << firstResult << endl;
                    } else if (op1 == MUL) {
                        firstResult = a * b;
                        cout << "先计算 " << a << " * " << b << " = " << firstResult << endl;
                    } else {
                        firstResult = (double)a / b;
                        cout << "先计算 " << a << " / " << b << " = " << firstResult << endl;
                    }
                    
                    cout << "然后计算 " << firstResult << " " << getOperatorChar(op2) << " " << c << " = " << answer << endl << endl;
                } else {
                    double secondResult;
                    if (op2 == MUL) {
                        secondResult = b * c;
                        cout << "先计算 " << b << " * " << c << " = " << secondResult << endl;
                    } else {
                        secondResult = (double)b / c;
                        cout << "先计算 " << b << " / " << c << " = " << secondResult << endl;
                    }
                    
                    cout << "然后计算 " << a << " " << getOperatorChar(op1) << " " << secondResult << " = " << answer << endl << endl;
                }
            }
        }
    }
    
    cout << "练习完成!" << endl;
    cout << "总题数:" << totalQuestions << ",正确数:" << correctCount << endl;
    cout << "正确率:" << (double)correctCount / totalQuestions * 100 << "%" << endl;
    
    return 0;
}
posted @ 2025-04-16 20:34  绿龙第一突破手donk  阅读(23)  评论(0)    收藏  举报