软件开发结对编程

结对编程同伴:2352509
采用C++语言编程

一、算法设计思路

  1. 基础版本设计
    核心算法:
    随机数生成:使用rand() % 100 + 1生成1-100的随机数
    运算符随机选择:通过rand() % 4随机选择加减乘除
    运算优先级处理:通过条件判断(op1 >= 2 && op2 < 2)识别需要优先计算的运算符组合
    结果验证:确保运算结果在0-1000范围内,否则重新生成

数据结构:
使用Question结构体存储题目表达式、正确答案、用户答案和判断结果
使用vector容器管理所有题目

关键函数:
generateTwoOperatorExpression:生成双运算符题目
showResults:显示练习结果
intToString:替代不兼容的to_string函数

  1. 难度扩展版本设计
    难度分级机制:
    enum Difficulty {
    EASY, // 简单:单运算符,小数字(1-20)
    MEDIUM, // 中等:双运算符,中等数字(10-50)
    HARD, // 较难:双运算符,大数字(30-100)
    EXTREME // 困难:双运算符,更多除法(50-100)
    };

难度控制实现:

  1. 数字范围控制:
    void getNumberRange(Difficulty diff, int& minNum, int& maxNum) {
    switch(diff) {
    case EASY: minNum=1; maxNum=20; break;
    case MEDIUM: minNum=10; maxNum=50; break;
    // ...
    }
    }

  2. 运算符控制:
    void getOperators(Difficulty diff, int& op1, int& op2) {
    switch(diff) {
    case EASY: op1=rand()%2; op2=-1; break; // 只有加减
    case EXTREME: // 增加除法概率
    if(rand()%2) op1=3;
    if(rand()%2) op2=3;
    break;
    }
    }

  3. 智能重试机制:
    if(finalResult<0 || finalResult>1000 || isnan(finalResult)) {
    generateExpression(questionNum, diff); // 重新生成
    return;
    }

结果统计增强:
按难度级别分别统计正确率
总正确率计算
详细的题目回顾功能

二、程序代码
第一版(没有难易程度):

点击查看代码
include <iostream>
include <cstdlib>
include <ctime>
include <string>
include <vector>
include <cmath>
include <sstream> // 用于替代to_string

using namespace std;

// 存储题目和答案的结构体
struct Question {
    string expression;
    double correctAnswer;
    double userAnswer;
    bool isCorrect;
};

vector<Question> questions; // 存储所有问题

// 整数转字符串函数(替代to_string)
string intToString(int num) {
    stringstream ss;
    ss << num;
    return ss.str();
}

// 生成包含两个运算符的算术表达式
void generateTwoOperatorExpression(int questionNum) {
    // 生成三个100以内的随机数
    int num1 = rand() % 100 + 1; // 1-100
    int num2 = rand() % 100 + 1;
    int num3 = rand() % 100 + 1;
    
    // 随机选择两个运算符 (0:+, 1:-, 2:, 3:/)
    int op1 = rand() % 4;
    int op2 = rand() % 4;
    
    char operations[2];
    double intermediateResult, finalResult;
    string expression;
    
    // 第一个运算符
    operations[0] = (op1 == 0) ? '+' : 
                   (op1 == 1) ? '-' : 
                   (op1 == 2) ? '' : '/';
    
    // 第二个运算符
    operations[1] = (op2 == 0) ? '+' : 
                   (op2 == 1) ? '-' : 
                   (op2 == 2) ? '' : '/';
    
    // 计算表达式结果(考虑运算优先级)
    if ((op1 >= 2 && op2 < 2) || (op1 < 2 && op2 < 2)) {
        // 先计算第一个运算
        switch(op1) {
            case 0: intermediateResult = num1 + num2; break;
            case 1: intermediateResult = num1 - num2; break;
            case 2: intermediateResult = num1  num2; break;
            case 3: intermediateResult = static_cast<double>(num1) / num2; break;
        }
        
        // 然后计算第二个运算
        switch(op2) {
            case 0: finalResult = intermediateResult + num3; break;
            case 1: finalResult = intermediateResult - num3; break;
            case 2: finalResult = intermediateResult  num3; break;
            case 3: finalResult = intermediateResult / num3; break;
        }
        
        expression = intToString(num1) + " " + operations[0] + " " + 
                    intToString(num2) + " " + operations[1] + " " + 
                    intToString(num3) + " = ";
    } else {
        // 先计算第二个运算
        switch(op2) {
            case 0: intermediateResult = num2 + num3; break;
            case 1: intermediateResult = num2 - num3; break;
            case 2: intermediateResult = num2  num3; break;
            case 3: intermediateResult = static_cast<double>(num2) / num3; break;
        }
        
        // 然后计算第一个运算
        switch(op1) {
            case 0: finalResult = num1 + intermediateResult; break;
            case 1: finalResult = num1 - intermediateResult; break;
            case 2: finalResult = num1  intermediateResult; break;
            case 3: finalResult = num1 / intermediateResult; break;
        }
        
        expression = intToString(num1) + " " + operations[0] + " (" + 
                    intToString(num2) + " " + operations[1] + " " + 
                    intToString(num3) + ") = ";
    }
    
    // 确保结果在0-1000之间
    if (finalResult < 0 || finalResult > 1000 || isnan(finalResult)) {
        generateTwoOperatorExpression(questionNum); // 重新生成
        return;
    }
    
    // 显示题目
    cout << "问题 " << questionNum << ": " << expression;
    
    // 获取用户答案
    double userAnswer;
    cin >> userAnswer;
    
    // 存储问题信息
    Question q;
    q.expression = expression;
    q.correctAnswer = finalResult;
    q.userAnswer = userAnswer;
    q.isCorrect = fabs(userAnswer - finalResult) < 0.001;
    questions.push_back(q);
}

// 显示练习结果
void showResults() {
    cout << "\n======== 练习结果 ========\n";
    int correctCount = 0;
    
    for (size_t i = 0; i < questions.size(); ++i) {
        cout << "问题 " << i+1 << ": " << questions[i].expression << endl;
        cout << "你的答案: " << questions[i].userAnswer << endl;
        cout << "正确答案: " << questions[i].correctAnswer << endl;
        
        if (questions[i].isCorrect) {
            cout << "结果: 正确!\n";
            correctCount++;
        } else {
            cout << "结果: 错误!\n";
        }
        cout << "------------------------\n";
    }
    
    cout << "总结: 你答对了 " << correctCount << " 题,共 " << questions.size() << " 题\n";
    cout << "正确率: " << (correctCount  100 / questions.size()) << "%\n";
}

int main() {
    srand(time(0)); // 初始化随机数种子
    
    cout << "双运算符四则运算练习 (数字范围1-100)\n";
    cout << "输入你的答案后按回车\n";
    cout << "所有题目完成后会显示结果\n";
    cout << "==============================\n";
    
    int questionCount = 10; // 设置题目数量
    
    // 生成题目
    for (int i = 0; i < questionCount; ++i) {
        generateTwoOperatorExpression(i+1);
    }
    
    // 显示结果
    showResults();
    
    system("pause"); // Dev-C++专用,防止窗口一闪而过
    return 0;
}
 

第二版(加入难易程度):

点击查看代码
include <iostream>
include <cstdlib>
include <ctime>
include <string>
include <vector>
include <cmath>
include <sstream>

using namespace std;

// 难度级别枚举
enum Difficulty {
    EASY,       // 简单:最多一个运算符,数字小
    MEDIUM,      // 中等:两个运算符,数字中等
    HARD,        // 较难:两个运算符,数字较大
    EXTREME      // 困难:两个运算符,包含更多除法
};

// 前向声明函数
string getDifficultyName(Difficulty diff);

// 存储题目和答案的结构体
struct Question {
    string expression;
    double correctAnswer;
    double userAnswer;
    bool isCorrect;
    Difficulty difficulty;
};

vector<Question> questions;

// 整数转字符串函数
string intToString(int num) {
    stringstream ss;
    ss << num;
    return ss.str();
}

// 获取难度名称
string getDifficultyName(Difficulty diff) {
    switch(diff) {
        case EASY: return "简单";
        case MEDIUM: return "中等";
        case HARD: return "较难";
        case EXTREME: return "困难";
        default: return "未知";
    }
}

// 根据难度获取数字范围
void getNumberRange(Difficulty diff, int& minNum, int& maxNum) {
    switch(diff) {
        case EASY:    minNum = 1; maxNum = 20; break;
        case MEDIUM:  minNum = 10; maxNum = 50; break;
        case HARD:    minNum = 30; maxNum = 100; break;
        case EXTREME: minNum = 50; maxNum = 100; break;
    }
}

// 根据难度生成运算符
void getOperators(Difficulty diff, int& op1, int& op2) {
    switch(diff) {
        case EASY:    // 简单:只用一个运算符
            op1 = rand() % 2; // 只有加减
            op2 = -1; // 表示没有第二个运算符
            break;
        case MEDIUM:  // 中等:两个运算符,主要是加减
            op1 = rand() % 2;
            op2 = rand() % 3; // 加减乘
            break;
        case HARD:    // 较难:两个运算符,包含乘除
            op1 = rand() % 3;
            op2 = rand() % 4;
            break;
        case EXTREME: // 困难:两个运算符,更多除法
            op1 = rand() % 4;
            op2 = rand() % 4;
            if (rand() % 2) op1 = 3; // 增加除法概率
            if (rand() % 2) op2 = 3;
            break;
    }
}

// 生成算术表达式
void generateExpression(int questionNum, Difficulty diff) {
    int minNum, maxNum;
    getNumberRange(diff, minNum, maxNum);
    
    int num1 = rand() % (maxNum - minNum + 1) + minNum;
    int num2 = rand() % (maxNum - minNum + 1) + minNum;
    int num3 = (diff == EASY) ? 0 : rand() % (maxNum - minNum + 1) + minNum;
    
    int op1, op2;
    getOperators(diff, op1, op2);
    
    char operations[2];
    double intermediateResult, finalResult;
    string expression;
    
    operations[0] = (op1 == 0) ? '+' : 
                   (op1 == 1) ? '-' : 
                   (op1 == 2) ? '' : '/';
    
    // 简单难度只有一个运算符
    if (diff == EASY) {
        switch(op1) {
            case 0: finalResult = num1 + num2; break;
            case 1: finalResult = num1 - num2; break;
        }
        expression = intToString(num1) + " " + operations[0] + " " + 
                    intToString(num2) + " = ";
    } 
    else { // 其他难度有两个运算符
        operations[1] = (op2 == 0) ? '+' : 
                       (op2 == 1) ? '-' : 
                       (op2 == 2) ? '' : '/';
        
        // 考虑运算优先级
        if ((op1 >= 2 && op2 < 2) || (op1 < 2 && op2 < 2)) {
            // 先算第一个运算
            switch(op1) {
                case 0: intermediateResult = num1 + num2; break;
                case 1: intermediateResult = num1 - num2; break;
                case 2: intermediateResult = num1  num2; break;
                case 3: intermediateResult = static_cast<double>(num1) / num2; break;
            }
            
            // 再算第二个运算
            switch(op2) {
                case 0: finalResult = intermediateResult + num3; break;
                case 1: finalResult = intermediateResult - num3; break;
                case 2: finalResult = intermediateResult  num3; break;
                case 3: finalResult = intermediateResult / num3; break;
            }
            
            expression = intToString(num1) + " " + operations[0] + " " + 
                        intToString(num2) + " " + operations[1] + " " + 
                        intToString(num3) + " = ";
        } else {
            // 先算第二个运算
            switch(op2) {
                case 0: intermediateResult = num2 + num3; break;
                case 1: intermediateResult = num2 - num3; break;
                case 2: intermediateResult = num2  num3; break;
                case 3: intermediateResult = static_cast<double>(num2) / num3; break;
            }
            
            // 再算第一个运算
            switch(op1) {
                case 0: finalResult = num1 + intermediateResult; break;
                case 1: finalResult = num1 - intermediateResult; break;
                case 2: finalResult = num1  intermediateResult; break;
                case 3: finalResult = num1 / intermediateResult; break;
            }
            
            expression = intToString(num1) + " " + operations[0] + " (" + 
                        intToString(num2) + " " + operations[1] + " " + 
                        intToString(num3) + ") = ";
        }
    }
    
    // 确保结果在0-1000之间
    if (finalResult < 0 || finalResult > 1000 || isnan(finalResult)) {
        generateExpression(questionNum, diff); // 重新生成
        return;
    }
    
    // 显示题目
    cout << "问题 " << questionNum << " (" << getDifficultyName(diff) << "): " << expression;
    
    // 获取用户答案
    double userAnswer;
    cin >> userAnswer;
    
    // 存储问题信息
    Question q;
    q.expression = expression;
    q.correctAnswer = finalResult;
    q.userAnswer = userAnswer;
    q.isCorrect = fabs(userAnswer - finalResult) < 0.001;
    q.difficulty = diff;
    questions.push_back(q);
}

// 显示练习结果
void showResults() {
    cout << "\n======== 练习结果 ========\n";
    int correctCount = 0;
    int diffCorrect[4] = {0}; // 各难度正确计数
    int diffTotal[4] = {0};    // 各难度总题数
    
    for (size_t i = 0; i < questions.size(); ++i) {
        Difficulty diff = questions[i].difficulty;
        diffTotal[diff]++;
        
        cout << "问题 " << i+1 << " (" << getDifficultyName(diff) << "): " 
             << questions[i].expression << endl;
        cout << "你的答案: " << questions[i].userAnswer << endl;
        cout << "正确答案: " << questions[i].correctAnswer << endl;
        
        if (questions[i].isCorrect) {
            cout << "结果: 正确!\n";
            correctCount++;
            diffCorrect[diff]++;
        } else {
            cout << "结果: 错误!\n";
        }
        cout << "------------------------\n";
    }
    
    cout << "\n======= 总结 =======\n";
    cout << "总正确率: " << correctCount << "/" << questions.size() << " (" 
         << (questions.size() ? (correctCount  100 / questions.size()) : 0) << "%)\n";
    
    // 各难度正确率
    for (int i = 0; i < 4; i++) {
        if (diffTotal[i] > 0) {
            cout << getDifficultyName(static_cast<Difficulty>(i)) << "难度: " 
                 << diffCorrect[i] << "/" << diffTotal[i] << " (" 
                 << (diffCorrect[i]  100 / diffTotal[i]) << "%)\n";
        }
    }
}

// 选择难度
Difficulty selectDifficulty() {
    cout << "请选择难度级别:\n";
    cout << "1. 简单\n";
    cout << "2. 中等\n";
    cout << "3. 较难\n";
    cout << "4. 困难\n";
    cout << "输入选项(1-4): ";
    
    int choice;
    cin >> choice;
    
    while (choice < 1 || choice > 4) {
        cout << "无效输入,请重新选择(1-4): ";
        cin >> choice;
    }
    
    return static_cast<Difficulty>(choice - 1);
}

int main() {
    srand(time(0));
    
    cout << "四则运算练习 (结果范围0-1000)\n";
    cout << "==============================\n";
    
    Difficulty diff = selectDifficulty();
    int questionCount = 10;// 设置题目数量
    
    // 生成题目
    for (int i = 0; i < questionCount; ++i) {
        generateExpression(i+1, diff);
    }
    
    // 显示结果
    showResults();
    
    system("pause");
    return 0;
}

三、运算结果
第一版(没有难易程度):

第二版(加入难易程度):





四、结对编程作业体会
2329311:
此次合作让我深刻体会到结对编程的优势:一是效率提升,双人审核显著减少代码错误;二是知识互补,搭档对随机数生成的建议简化了校验流程;三是强化沟通能力,尤其在需求细节对齐时需清晰表达。改进方向包括扩展题目难度或增加图形界面。最终,我们成功完成了四则运算练习程序。这次实践不仅巩固了编程技能,更让我认识到协作开发的价值。
2352509:
通过这次结对编程实践,我们不仅完成了一个功能完善的四则运算练习程序,还深刻体会到了协作开发的价值。从最初的基础版本到支持多难度级别的最终版本,整个过程充满了技术挑战和学习机会。我们学会了如何更好地分工合作、解决兼容性问题、设计友好的用户界面,这些经验将对未来的编程项目产生持久影响。

posted @ 2025-04-15 19:31  一点前睡觉  阅读(63)  评论(0)    收藏  举报