在结队编程过程中,我收获了这些 【Tutorials】

发布时间 2023-04-08 21:52:09作者: Noctis_Stardust

在结队编程过程中,我收获了这些


受到了编程开发领域文档设计的启发’What nobody tells you about documentation’,本文结构为四种基本博客文档结构中的Tutorials类型,旨在记录与总结,并以清晰的行文展示出来。

image
? 如果一篇文档不好理解,很可能是它将多种文档塞经一篇文中导致的。

结队编程的核心,在于和队友的合作编程的同时不降低编程效率,同时实现1+1>2的效果,而不是拖慢彼此进度。

在这次结队编程,我2152316和我的同伴 2152312 完成了一个扩充功能的四则运算程序,基于c++语言。

程序具体实现了如下功能:

  1. 随机生成加减乘除四则运算题目。
  2. 支持自定义题目数量和数值范围。
  3. 支持选择是否包含负数。
  4. 对于每道题目,程序可以自动计算出正确答案,并与用户输入的答案进行比对,给出是否正确的反馈。
  5. 加入了答题计时功能,用户可在完成答题后知道答题的用时,进一步提高运算效率。

结队编程的概念和意义

结队编程是一种编程模式,指的是两名或多名开发人员共同编写代码的过程。在结队编程中,每个人员都有自己的角色和任务分工,他们通过协作来完成项目的开发。结队编程的目的是通过协作来提高编程效率、质量和可维护性,同时也可以促进团队合作和沟通。

结队编程的意义在于:

  • 提高编程效率:结队编程可以让多名开发人员在同一时间内共同工作,通过协作来增加开发速度。
  • 提高代码质量:结队编程可以让多名开发人员对代码进行共同的评审和修改,从而提高代码的质量。
  • 促进团队合作和沟通:结队编程可以让多名开发人员在同一项目上共同工作,从而促进团队合作和沟通,提高团队的凝聚力。

如何在结队编程中提高编程效率

在结队编程中,要想提高编程效率,需要注意以下几点:

  • 选择合适的队友:选择具有不同技能和经验的队友,以便在不同的领域进行协作。
  • 分工合作:将任务分配给不同的队友,以便在同一时间内完成多个任务。
  • 协调沟通:通过有效的沟通和协调,确保每个人员都了解自己的任务和进度。
  • 维护代码一致性:通过使用版本控制和代码评审等工具,确保代码的一致性和可维护性。
  • 避免冲突:通过定义清晰的代码规范和工作流程,以避免不必要的冲突。

程序简析与编程过程

由于此次是结队编程,代码的写作形式与以往独自开发并不相同。在开始之前,我们首先讨论了程序的整体框架,然后确定了想要实现的功能,提出各自对于具体实现的想法。

进入编写代码部分后,我们首先完成了主函数的开头,确定了程序输入输出部分的大体结构。在一位同学编写时,另一位细化了特定功能的实现(这里我们加入了程序计时模块)。

在这里,我们编写了获取用户输入的题目数量,和选择是否包含负数的功能。接着设定计时起始点,以便在程序结束时计算答题用时。

int main() {
    srand(time(NULL)); // 设置随机种子

    // 输入题目数量
    int num = 10;
    //是否包含负数
    bool includeNegative = false;
    //答对的题目数量
    int correctnum = 0;
    std::cout << "请输入题目数量:";
    cin >> num;
    /*可选:输入数值范围
    std::cout << "请输入数值范围(最小值和最大值,用空格隔开):";
    cin >> minValue >> maxValue;
    */
    std::cout << "是否包含负数(1表示是,0表示否):";
    cin >> includeNegative;
    // 开始计时
    auto start = chrono::steady_clock::now();

这一段代码是程序的起始部分。在这里,我们首先完成了程序的基础运算与计数功能,同时就随机数的实现进行了讨论思考。(见引用)

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <chrono>

using namespace std;

//数值范围
int minValue = 1, maxValue = 100;

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

// 生成随机运算符
char getRandomOperator() {
    const char operators[] = "+-*/";
    return operators[rand() % 4];
}

// 计算结果
int calculate(int left, char op, int right) {
    switch (op) {
    case '+':
        return left + right;
    case '-':
        return left - right;
    case '*':
        return left * right;
    case '/':
        return left / right;
    }
    return 0;
}

在C++中,要生成随机数需要利用rand()函数。但是rand()函数的计算结果是由一个叫做“随机数种子”的数决定的。如果不设置随机数种子,每次生成的随机数都是相同的,这显然不是我们所希望的。因此,在C++中生成随机数时,我们需要先设置随机数种子,一般使用srand()函数设置。srand()函数需要传入一个参数,这个参数就是随机数种子。通常我们使用time()函数获取当前时间来作为随机数种子,这样每次运行程序时,随机数种子都不同,可以得到不同的随机数序列。

下方代码则是程序的核心部分,也是结队编程中二人多次修改完善的部分。其中循环生成题目、获取用户输入的答案,并比对答案的正确性。

此外,由于要求的是100以内的四则运算,我们引入了检测机制来保证各种运算的结果符合生成题目的限定要求,且结果小于100。对于减法,因为此前已经限制数值范围为[0,100],因此只需添加对于结果是否为负数的检查。对于加法和乘法,我们的解决方案为若结果大于100,则直接重新生成一对运算数,通过循环来使得最终题目中出现的运算结果不大于100。对于除法,除了避免除零以外,还需要限定运算是整除。不过,若直接沿用上述方法,经常会出现除数为1或除数和被除数相同的情况。为排除这类过于简单的题目,我们修改了判断条件。

    // 生成并输出题目
    for (int i = 0; i < num; i++) {
        int left = getRandom(minValue, maxValue);
        int right = getRandom(minValue, maxValue);
        char op = getRandomOperator();
        //进行题目数值处理
        switch (op)
        {
        case '+':
            while (left + right > 100)//保证相加结果小于100
            {
                left = getRandom(minValue, maxValue);
                right = getRandom(minValue, maxValue);
            }
            break;
        case '-':
            if (!includeNegative)// 如果不包含负数,则保证左右运算数都是正数
            {
                left = max(left, right);
                right = getRandom(minValue, left);
            }
            break;
        case '*':
            while (left * right > 100)//保证相乘结果小于100
            {
                left = getRandom(minValue, maxValue);
                right = getRandom(minValue, maxValue);
            }
            break;
        case '/':
            if (right == 0)//避免除零
            {
                right = 1;
            }
            while (right == 1 || left == right || left % right != 0)
            {
                left = getRandom(minValue, maxValue);
                right = getRandom(minValue, maxValue);
                if (right == 0)//避免除零
                {
                    right = 1;
                }
            }
            break;
        }
        std::cout << left << " " << op << " " << right << " = ";
        // 用户输入答案
        int answer;
        cin >> answer;
        // 计算正确答案并比对
        int correctAnswer = calculate(left, op, right);
        if (answer == correctAnswer) {
            std::cout << "恭喜你,答对了!" << endl;
            //答对的题目数量
            correctnum++;
        }
        else {
            std::cout << "很遗憾,正确答案是 " << correctAnswer << "。" << endl;
        }
    }

在程序的末尾,这段代码用于计算答题用时和正确率,并输出结果。

    //停止计时,并计算答题用时
    auto end = chrono::steady_clock::now();
    auto diff = end - start;
    //计算正确率
    double percentage = (double)correctnum / (double)num;
    std::cout << "答题结束。在" << num << "题中,你答对了" << correctnum << "题。\\n你的正确率为 " << percentage * 100 << " % " << endl;
    std::cout << "答题共用时:" << chrono::duration<double, milli>(diff).count() / 1000 << "秒" << endl;
    return 0;
}

代码功能演示

image

结队编程技巧与工作流的实践

在结队编程中,代码一致性是一个非常重要的问题。在开发过程中,如果两位开发人员不协调,很容易导致代码冲突,影响双方的的工作效率和代码质量。因此,为了保证代码一致性,我们最终在这次编程中实际采取了以下措施:

  • 使用版本控制工具。版本控制工具可以让多个开发人员协同工作,同时也可以帮助我们管理代码的版本,保证代码的一致性。我们使用了常用的版本控制工具包括Subversion。使用版本控制工具,可以让我们方便地查看代码的历史版本、回滚代码等。
  • 定义清晰的代码规范。在项目开发之前,我们需要定义并共享代码规范。这些规范包括代码格式、命名规则、注释规则等。定义清晰的代码规范可以帮助我们避免不必要的冲突,同时也可以提高代码的可读性和可维护性。

image

留下注释与待完善功能,增加可读性与可扩展性

  • 使用代码评审工具。代码评审是一种有效的代码加工方法,可以帮助我么们发现潜在的错误和问题。可以使用一些开源的代码评审工具,如Review Board。在代码评审过程中,我们对代码进行详细的审查,包括代码格式、代码逻辑、注释等,从而提高代码质量和可读性。

image

文档协同编辑

  • 避免同时修改同一文件。为了避免冲突,在结队编程中要避免同时修改同一文件。对此,我们在开发过程中使用vscode的服务器同步插件;在合并代码时,我们需要注意解决冲突的方式,避免影响代码的正确性和质量;而在维护与编写文档时,使用了Notion工作区让我与同伴能同时编辑markdown文档,并通过comment留下修改记录,方便版本回溯、异步交流。这些实时工作流让我们尝试了现今远程协作项目的合作方法,同时也体会到结队编程的核心,很好地提升了效率。

image

文档维护历史回溯与同步

  • 开展代码审查、以及在编写代码时注重可读性等方式,保证代码的一致性和可维护性。

通过这些措施,我们得以在结队编程中保证代码质量,提高项目的开发效率。

总结

以上,就是我们二人通过结队编程完成的程序与全部过程,在此实践中,我们熟悉了团队编程的工作流,同时探索出了可行有效的推进项目进度的方案。我们总共完成了这些:

  1. 在开发过程中,我们探索并使用了vscode的服务器同步插件和Notion工作区等实时工作流,提高了团队协作效率。
  2. 完成初步开发后,我们使用了版本控制、定义代码规范、使用代码评审工具、避免同时修改同一文件等措施,保证了代码一致性和可维护性。
  3. 项目完成后,我们共同审查了代码,并共同完成记录文档。

二人合作的程序项目经过完善与审查后,具有以下实用且有效的扩展功能:

  1. 随机生成加减乘除四则运算题目。
  2. 支持自定义题目数量和数值范围。
  3. 支持选择是否包含负数。
  4. 对于每道题目,程序可以自动计算出正确答案,并与用户输入的答案进行比对,给出是否正确的反馈。
  5. 加入了答题计时功能,用户可在完成答题后知道答题的用时,进一步提高运算效率。

完整源代码文件

地址:https://wwqu.lanzoum.com/i09yB0sd7duh

MathExercise程序代码

点击查看代码
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <chrono>

using namespace std;

//数值范围
int minValue = 1, maxValue = 100;

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

// 生成随机运算符
char getRandomOperator() {
    const char operators[] = "+-*/";
    return operators[rand() % 4];
}

// 计算结果
int calculate(int left, char op, int right) {
    switch (op) {
    case '+':
        return left + right;
    case '-':
        return left - right;
    case '*':
        return left * right;
    case '/':
        return left / right;
    }
    return 0;
}

int main() {
    srand(time(NULL)); // 设置随机种子

    // 输入题目数量
    int num = 10;
    //是否包含负数
    bool includeNegative = false;
    //答对的题目数量
    int correctnum = 0;
    std::cout << "请输入题目数量:";
    cin >> num;
    /*可选:输入数值范围
    std::cout << "请输入数值范围(最小值和最大值,用空格隔开):";
    cin >> minValue >> maxValue;
    */
    std::cout << "是否包含负数(1表示是,0表示否):";
    cin >> includeNegative;
    // 开始计时
    auto start = chrono::steady_clock::now();

    // 生成并输出题目
    for (int i = 0; i < num; i++) {
        int left = getRandom(minValue, maxValue);
        int right = getRandom(minValue, maxValue);
        char op = getRandomOperator();
        //进行题目数值处理
        switch (op)
        {
        case '+':
            while (left + right > 100)//保证相加结果小于100
            {
                left = getRandom(minValue, maxValue);
                right = getRandom(minValue, maxValue);
            }
            break;
        case '-':
            if (!includeNegative)// 如果不包含负数,则保证左右运算数都是正数
            {
                left = max(left, right);
                right = getRandom(minValue, left);
            }
            break;
        case '*':
            while (left * right > 100)//保证相乘结果小于100
            {
                left = getRandom(minValue, maxValue);
                right = getRandom(minValue, maxValue);
            }
            break;
        case '/':
            if (right == 0)//避免除零
            {
                right = 1;
            }
            while (right == 1 || left == right || left % right != 0)
            {
                left = getRandom(minValue, maxValue);
                right = getRandom(minValue, maxValue);
                if (right == 0)//避免除零
                {
                    right = 1;
                }
            }
            break;
        }
        std::cout << left << " " << op << " " << right << " = ";
        // 用户输入答案
        int answer;
        cin >> answer;
        // 计算正确答案并比对
        int correctAnswer = calculate(left, op, right);
        if (answer == correctAnswer) {
            std::cout << "恭喜你,答对了!" << endl;
            //答对的题目数量
            correctnum++;
        }
        else {
            std::cout << "很遗憾,正确答案是 " << correctAnswer << "。" << endl;
        }
    }
    //停止计时,并计算答题用时
    auto end = chrono::steady_clock::now();
    auto diff = end - start;
    //计算正确率
    double percentage = (double)correctnum / (double)num;
    std::cout << "答题结束。在" << num << "题中,你答对了" << correctnum << "题。\n你的正确率为 " << percentage * 100 << " % " << endl;
    std::cout << "答题共用时:" << chrono::duration<double, milli>(diff).count() / 1000 << "秒" << endl;
    return 0;
}