结对编码

本次结对编码是由我和2352437同学共同完成 主题是完成四则运算的编码设计
项目背景:在我们平时的学习和教学中,经常需要为学生提供大量的数学题目进行练习。然而,手动生成这些题目不仅耗时耗力,而且难以保证题目的随机性和多样性。为了简化这个过程,我们决定编写一个程序,自动生成四则运算的题目,并确保它们符合一定的范围要求(即操作数在1到100之间,答案在0到1000之间)。
结果截图:

主要代码:

点击查看代码
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <string>
#include <stack>
#include <set>
#include <cmath>

using namespace std;

// 得分系统结构体
struct ScoreSystem {
    int totalProblems = 0;
    int correctAnswers = 0;
    int wrongAnswers = 0;
    double score = 0.0;
    
    void addCorrect() {
        correctAnswers++;
        totalProblems++;
        calculateScore();
    }
    
    void addWrong() {
        wrongAnswers++;
        totalProblems++;
        calculateScore();
    }
    
    void calculateScore() {
        if (totalProblems > 0) {
            score = round((double)correctAnswers / totalProblems * 100);
        }
    }
    
    void displayStats() {
        cout << "\n===== 答题统计 =====" << endl;
        cout << "总题数: " << totalProblems << endl;
        cout << "正确: " << correctAnswers << endl;
        cout << "错误: " << wrongAnswers << endl;
        cout << "得分: " << score << "%" << endl;
    }
};

// 生成随机整数
int randomInt(int min, int max) {
    return rand() % (max - min + 1) + min;
}

// 计算表达式结果
int calculateExpression(const string& expr) {
    stack<int> nums;
    stack<char> ops;
    int num = 0;

    for (size_t i = 0; i < expr.size(); ++i) {
        char c = expr[i];
        if (isdigit(c)) {
            num = num * 10 + (c - '0');
        }
        else if (c == '+' || c == '-' || c == '*' || c == '/') {
            nums.push(num);
            num = 0;
            // 处理高优先级运算符
            if (!ops.empty() && (ops.top() == '*' || ops.top() == '/')) {
                char op = ops.top(); ops.pop();
                int b = nums.top(); nums.pop();
                int a = nums.top(); nums.pop();
                if (op == '*') nums.push(a * b);
                else nums.push(a / b);
            }
            ops.push(c);
        }
    }
    nums.push(num);

    // 处理剩余运算
    while (!ops.empty()) {
        char op = ops.top(); ops.pop();
        int b = nums.top(); nums.pop();
        int a = nums.top(); nums.pop();
        if (op == '+') nums.push(a + b);
        else if (op == '-') nums.push(a - b);
        else if (op == '*') nums.push(a * b);
        else nums.push(a / b);
    }

    return nums.top();
}

// 检查表达式是否有效
bool isValidExpression(const string& expr) {
    try {
        int result = calculateExpression(expr);
        return result >= 0 && result <= 1000;
    } catch (...) {
        return false;
    }
}

// 生成一个有效的表达式
string generateUniqueExpression(set<string>& existingExpressions) {
    vector<char> operators = {'+', '-', '*', '/'};
    string expr;
    int attempts = 0;
    const int maxAttempts = 1000;

    while (attempts < maxAttempts) {
        char op1 = operators[randomInt(0, 3)];
        char op2 = operators[randomInt(0, 3)];

        int num1 = randomInt(1, 100);
        int num2 = randomInt(1, 100);
        int num3 = randomInt(1, 100);

        // 确保除法能整除
        if (op1 == '/') {
            vector<int> factors;
            for (int i = 1; i <= num1; ++i) {
                if (num1 % i == 0) factors.push_back(i);
            }
            if (!factors.empty()) {
                num2 = factors[randomInt(0, factors.size() - 1)];
            }
        }

        if (op2 == '/') {
            int temp;
            if (op1 == '+') temp = num1 + num2;
            else if (op1 == '-') temp = num1 - num2;
            else if (op1 == '*') temp = num1 * num2;
            else temp = num1 / num2;

            if (temp > 0) {
                vector<int> factors;
                for (int i = 1; i <= temp; ++i) {
                    if (temp % i == 0) factors.push_back(i);
                }
                if (!factors.empty()) {
                    num3 = factors[randomInt(0, factors.size() - 1)];
                }
            }
        }

        int bracketType = randomInt(0, 2);
        char buffer[100];

        switch (bracketType) {
        case 0:
            snprintf(buffer, sizeof(buffer), "%d %c %d %c %d", num1, op1, num2, op2, num3);
            break;
        case 1:
            snprintf(buffer, sizeof(buffer), "(%d %c %d) %c %d", num1, op1, num2, op2, num3);
            break;
        case 2:
            snprintf(buffer, sizeof(buffer), "%d %c (%d %c %d)", num1, op1, num2, op2, num3);
            break;
        }
        expr = buffer;

        if (isValidExpression(expr) && existingExpressions.find(expr) == existingExpressions.end()) {
            existingExpressions.insert(expr);
            return expr;
        }

        attempts++;
    }

    // 如果多次尝试失败,生成一个简单且唯一的表达式
    string uniqueExpr;
    do {
        int a = randomInt(1, 50);
        int b = randomInt(1, 50);
        while (a % b != 0) b = randomInt(1, a);
        char buffer[50];
        snprintf(buffer, sizeof(buffer), "%d / %d + %d", a, b, randomInt(0, 10));
        uniqueExpr = buffer;
    } while (existingExpressions.find(uniqueExpr) != existingExpressions.end());

    existingExpressions.insert(uniqueExpr);
    return uniqueExpr;
}

int main() {
    srand(time(0));
    const int totalProblems = 300;
    const int problemsPerLine = 5;
    set<string> existingExpressions;
    ScoreSystem scoreSystem;

    cout << "生成 " << totalProblems << " 道四则运算练习题:" << endl;
    cout << "----------------------------------------" << endl;
    cout << "要求:1. 100以内数字 2. 两个运算符 3. 除法结果必须为整数 4. 所有题目不同" << endl;
    cout << "----------------------------------------" << endl;

    // 生成题目
    vector<pair<string, int>> problems;
    for (int i = 0; i < totalProblems; ++i) {
        string problem = generateUniqueExpression(existingExpressions);
        int answer = calculateExpression(problem);
        problems.emplace_back(problem, answer);
    }

    // 显示题目并获取用户答案
    for (int i = 0; i < totalProblems; ++i) {
        cout << (i + 1) << ". " << problems[i].first << " = ";
        
        int userAnswer;
        cin >> userAnswer;
        
        if (userAnswer == problems[i].second) {
            cout << "正确!\n";
            scoreSystem.addCorrect();
        } else {
            cout << "错误!正确答案是: " << problems[i].second << "\n";
            scoreSystem.addWrong();
        }
        
        // 每5题显示一次当前统计
        if ((i + 1) % problemsPerLine == 0) {
            scoreSystem.displayStats();
            cout << "----------------------------------------" << endl;
        }
    }

    // 最终统计
    cout << "\n====== 最终成绩 ======" << endl;
    scoreSystem.displayStats();
    cout << "=====================" << endl;

    // 根据得分给出评价
    if (scoreSystem.score >= 90) {
        cout << "优秀!继续保持!" << endl;
    } else if (scoreSystem.score >= 70) {
        cout << "良好!还有提升空间!" << endl;
    } else if (scoreSystem.score >= 60) {
        cout << "及格!需要多加练习!" << endl;
    } else {
        cout << "不及格!建议重新学习基础知识!" << endl;
    }

    return 0;
}

设计思路:首先确定规则 1.100以内数字 2.两个运算符 3.除法结果必须为整数 4.所有题目不同 5.设计一个简单的得分系统
首先完成四则运算的基本规则的完成

点击查看代码
// 生成随机整数
int randomInt(int min, int max) {
    return rand() % (max - min + 1) + min;
}

// 检查表达式是否有效
bool isValidExpression(const string& expr) {
    stack<int> nums;
    stack<char> ops;
    int num = 0;

    for (size_t i = 0; i < expr.size(); ++i) {
        char c = expr[i];
        if (isdigit(c)) {
            num = num * 10 + (c - '0');
        }
        else if (c == '+' || c == '-' || c == '*' || c == '/') {
            nums.push(num);
            num = 0;
            // 处理高优先级运算符
            if (!ops.empty() && (ops.top() == '*' || ops.top() == '/')) {
                char op = ops.top(); ops.pop();
                int b = nums.top(); nums.pop();
                int a = nums.top(); nums.pop();
                if (op == '*') nums.push(a * b);
                else {
                    if (b == 0) return false;
                    if (a % b != 0) return false;
                    nums.push(a / b);
                }
            }
            ops.push(c);
        }
    }
    nums.push(num);

    // 处理剩余运算
    while (!ops.empty()) {
        char op = ops.top(); ops.pop();
        int b = nums.top(); nums.pop();
        int a = nums.top(); nums.pop();
        if (op == '+') nums.push(a + b);
        else if (op == '-') nums.push(a - b);
        else if (op == '*') nums.push(a * b);
        else {
            if (b == 0) return false;
            if (a % b != 0) return false;
            nums.push(a / b);
        }
    }

    int result = nums.top();
    return result >= 0 && result <= 1000;
}

然后生成表达式且增加尝试次数以确保唯一性
点击查看代码
// 生成一个有效的表达式
string generateUniqueExpression(set<string>& existingExpressions) {
    vector<char> operators;
    operators.push_back('+');
    operators.push_back('-');
    operators.push_back('*');
    operators.push_back('/');

    string expr;
    int attempts = 0;
    const int maxAttempts = 1000; // 增加尝试次数以确保唯一性

    while (attempts < maxAttempts) {
        char op1 = operators[randomInt(0, 3)];
        char op2 = operators[randomInt(0, 3)];

        int num1 = randomInt(1, 100);
        int num2 = randomInt(1, 100);
        int num3 = randomInt(1, 100);
因随机生成的算式除法可能出现余数 则会产生小数 接着我们保证除法能够整除
点击查看代码
 // 确保除法能整除
        if (op1 == '/') {
            vector<int> factors;
            for (int i = 1; i <= num1; ++i) {
                if (num1 % i == 0) factors.push_back(i);
            }
            if (!factors.empty()) {
                num2 = factors[randomInt(0, factors.size() - 1)];
            }
        }

        if (op2 == '/') {
            int temp;
            if (op1 == '+') temp = num1 + num2;
            else if (op1 == '-') temp = num1 - num2;
            else if (op1 == '*') temp = num1 * num2;
            else temp = num1 / num2;

            if (temp > 0) {
                vector<int> factors;
                for (int i = 1; i <= temp; ++i) {
                    if (temp % i == 0) factors.push_back(i);
                }
                if (!factors.empty()) {
                    num3 = factors[randomInt(0, factors.size() - 1)];
                }
            }
        }

        int bracketType = randomInt(0, 2);
        char buffer[100];

        switch (bracketType) {
        case 0:
            snprintf(buffer, sizeof(buffer), "%d %c %d %c %d", num1, op1, num2, op2, num3);
            break;
        case 1:
            snprintf(buffer, sizeof(buffer), "(%d %c %d) %c %d", num1, op1, num2, op2, num3);
            break;
        case 2:
            snprintf(buffer, sizeof(buffer), "%d %c (%d %c %d)", num1, op1, num2, op2, num3);
            break;
        }
        expr = buffer;

        if (isValidExpression(expr) && existingExpressions.find(expr) == existingExpressions.end()) {
            existingExpressions.insert(expr);
            return expr;
        }

        attempts++;
    }

    // 如果多次尝试失败,生成一个简单且唯一的表达式
    string uniqueExpr;
    do {
        int a = randomInt(1, 50);
        int b = randomInt(1, 50);
        while (a % b != 0) b = randomInt(1, a);
        char buffer[50];
        snprintf(buffer, sizeof(buffer), "%d / %d + %d", a, b, randomInt(0, 10));
        uniqueExpr = buffer;
    } while (existingExpressions.find(uniqueExpr) != existingExpressions.end());

    existingExpressions.insert(uniqueExpr);
    return uniqueExpr;
}

最后构建一个简单的得分系统(答题后出现“正确”或“错误”及正确答案 每五题结算一次正确率)
点击查看代码
// 得分系统结构体
struct ScoreSystem {
    int totalProblems = 0;
    int correctAnswers = 0;
    int wrongAnswers = 0;
    double score = 0.0;

    void addCorrect() {
        correctAnswers++;
        totalProblems++;
        calculateScore();
    }

    void addWrong() {
        wrongAnswers++;
        totalProblems++;
        calculateScore();
    }

    void calculateScore() {
        if (totalProblems > 0) {
            score = round((double)correctAnswers / totalProblems * 100);
        }
    }

    void displayStats() {
        cout << "\n===== 答题统计 =====" << endl;
        cout << "总题数: " << totalProblems << endl;
        cout << "正确: " << correctAnswers << endl;
        cout << "错误: " << wrongAnswers << endl;
        cout << "得分: " << score << "%" << endl;
    }
}
点击查看代码
 // 生成题目
    vector<pair<string, int>> problems;
    for (int i = 0; i < totalProblems; ++i) {
        string problem = generateUniqueExpression(existingExpressions);
        int answer = calculateExpression(problem);
        problems.emplace_back(problem, answer);
    }

    // 显示题目并获取用户答案
    for (int i = 0; i < totalProblems; ++i) {
        cout << (i + 1) << ". " << problems[i].first << " = ";

        int userAnswer;
        cin >> userAnswer;

        if (userAnswer == problems[i].second) {
            cout << "正确!\n";
            scoreSystem.addCorrect();
        } else {
            cout << "错误!正确答案是: " << problems[i].second << "\n";
            scoreSystem.addWrong();
        }

        // 每5题显示一次当前统计
        if ((i + 1) % problemsPerLine == 0) {
            scoreSystem.displayStats();
            cout << "----------------------------------------" << endl;
        }
    }

    // 最终统计
    cout << "\n====== 最终成绩 ======" << endl;
    scoreSystem.displayStats();
    cout << "=====================" << endl;

    // 根据得分给出评价
    if (scoreSystem.score >= 90) {
        cout << "优秀!继续保持!" << endl;
    } else if (scoreSystem.score >= 70) {
        cout << "良好!还有提升空间!" << endl;
    } else if (scoreSystem.score >= 60) {
        cout << "及格!需要多加练习!" << endl;
    } else {
        cout << "不及格!建议重新学习基础知识!" << endl;
    }

    return 0;
}

结对编程心得体会: 在这次与同学合作的结对编程项目中,我们共同完成了四则运算练习题生成器的开发,并加入了得分统计系统。通过这次合作,我深刻体会到了结对编程的优势与挑战。

分工协作,高效互补:我主要负责表达式生成算法和唯一性校验,而同学负责得分系统和用户交互。在编写代码时,我们一人编写代码,另一人实时审查,发现并修正了多个潜在错误,比如除零异常和括号匹配问题。

思维碰撞,优化设计:在讨论如何保证题目不重复时,我们尝试了多种方案,最终采用标准化表达式的方法,既保证了效率,又避免了重复。此外,同学提出的每5题反馈进度的设计,让体验大幅提升。

沟通与调试的挑战:由于编程风格不同,初期在代码合并时出现了冲突,但通过Git版本管理和详细注释,我们很快适应了彼此的节奏。

这次合作让我认识到,结对编程不仅能减少错误,还能激发更好的解决方案。未来我们会继续努力,进一步提升代码质量。

posted @ 2025-04-11 14:22  2352337王兵寒  阅读(25)  评论(0)    收藏  举报