zoukankan      html  css  js  c++  java
  • 实验二 结对编程之第二阶段

    一、实验目标
      1)体验敏捷开发中的两人合作。

      2)进一步提高个人编程技巧与实践。

    二 、实验内容
      1)根据以下问题描述,练习结对编程(pair programming)实践;

      2)要求学生两人一组,自由组合。每组使用一台计算机,二人共同编码,完成实验要求。

      3)要求在结对编程工作期间,两人的角色至少切换 4 次;

      4)编程语言不限,版本不限。建议使用 Python 或 JAVA 进行编程。

    三、队员信息

    队员

    博客地址

    GitHub仓库地址

    选择课题

    XYZ

    王慧

    https://www.cnblogs.com/1234wh/

    https://github.com/yqw0710/wyzproject

    生命游戏

    叶啟文

    https://www.cnblogs.com/yqw0710/

    四、代码规范

    参考:https://www.cnblogs.com/niansi/p/7751374.html 

     1.代码编排
        a.缩进。4个空格的缩进(编辑器都可以完成此功能),不使用Tap,更不能混合使用Tap和空格。
        b.每行最大长度79,换行可以使用反斜杠,最好使用圆括号。换行点要在操作符的后边敲回车。   
        c.如无特殊情况,文件一律使用UTF-8编码。

      2.文档编排
        a.模块内容的顺序:模块说明和docstring—import—globals&constants—其他定义。其中import部分,又按标准、三方和自己编写顺序依次排放,每组之间空一行。
        b.不要在一句import中多个库

      3.空格的使用(总体原则,避免不必要的空格。)
        a.逗号、冒号、分号前不要加空格。  
        b.操作符左右各加一个空格,不要为了对齐增加空格。
        c.不要将多句语句写在同一行,尽管使用‘;’也不允许。

      4.注释(总体原则,错误的注释不如没有注释。)
        a.块注释,在一段代码前增加的注释。在‘#’后加一空格。段落之间以只有‘#’的行间隔。
        b .行注释,在一句代码后加注释。 
        c. 至少使用两个空格和语句分开,避免无谓的注释。

       5.命名规范
        a. 尽量单独使用小写字母‘l’,大写字母‘O’等容易混淆的字母。
        b.函数命名使用全部小写的方式,可以使用下划线; 常量命名使用全部大写的方式,可以使用下划线。
        c.类名使用驼峰命名风格,首字母大写,私有类可用一个下划线开头。

    五、程序的总体设计

                 

      六、结对编程过程

        我们小组通过QQ屏幕分享来通过实现代码编程,通过在GitHub上托管代码来实现代码保存与更新。

        1.针对python代码讨论代码规范

              

         2.针对代码不同模块进行结对编程

    交互

    驾驶员

    观察员

    编程内容

    第1次

    王慧

    叶啟文

    细胞生命初始化模块

    第2次

    叶啟文

    王慧

    游戏规则设置模块

    第3次

    王慧

    叶啟文

    接收动图长度值

    第4次

    叶啟文

    王慧

    绘制动图模块

    第5次

    王慧

    叶啟文

    代码升级,实现地图从N* N到N* M

    第6次

    叶啟文

    王慧

    代码优化,删除冗余代码、简化注释等

       

      部分过程记录:

                           

           

    七、功能模块

       1.细胞生命初始化模块

    # 初始化细胞生命状态
    def randomGrid(N):# returns a grid of NxN random values
        return np.random.choice(vals, N * N, p=[0.2, 0.8]).reshape(N, N)
    

     2.游戏规则设置模块

    #更新细胞生命状态
    def update(frameNum, img, grid, N):
        newGrid = grid.copy()
        for i in range(N):
            for j in range(N):# 检测网格的8个边缘。用取模运算符让值在边缘折返
                total = int((grid[i, (j - 1) % N] + grid[i, (j + 1) % N] +
                             grid[(i - 1) % N, j] + grid[(i + 1) % N, j] +
                             grid[(i - 1) % N, (j - 1) % N] + grid[(i - 1) % N, (j + 1) % N] +
                             grid[(i + 1) % N, (j - 1) % N] + grid[(i + 1) % N, (j + 1) % N]))
                if grid[i, j] == ON:
                    if (total < 2) or (total > 3):
                        newGrid[i, j] = OFF
                else:
                    if total == 3:
                        newGrid[i, j] = ON
        # update data
        img.set_data(newGrid)
        grid[:] = newGrid[:]
        return img
    

     3.绘制动图模块

        # declare grid
        grid = randomGrid(N)
        
        parser = argparse.ArgumentParser()
        parser.add_argument('--interval', dest='interval', required=False) # 设置动画更新间隔的毫秒数
        args = parser.parse_args()
        # 设置动画
        fig, ax = plt.subplots(facecolor='Lavender')  # 配置 matplotlib 的绘图和动画参数
        img = ax.imshow(grid, cmap=cmap,interpolation='nearest')  # 用plt.show()方法将这个矩阵的值显示为图像,并给 interpolation 选项传入'nearest'值,以得到尖锐的边缘(否则是模糊的)
        ani =animation.FuncAnimation(fig, update, fargs=(img, grid, N,),frames=10,interval=50,save_count=50)
                 # animation.FuncAnimation()调用函数 update(),该函数在前面的程序中定义,根据命游戏的规则更新网格。
        plt.show()
    

       4.接收动图长度值

    print("请输入一个地图的大小值:")
        N = input()
        try:
            if N and int(N) > 8:
                N = int(N)
        except ValueError:
            print('The input is not a number!')
            sys.exit(0)
    

      5.代码升级,实现地图从N* N到N* M

     # set grid size
        print("请输入一个地图的长与宽:")
        M = input()
        N = input()
        try:
            if M and int(M) > 8:
                M = int(M)
            if N and int(N) > 8:
                N = int(N)
        except ValueError:
            print('The input is not a number!')
            sys.exit(0)
    

      

    # 实现环形边界条件
    def update(frameNum, img, grid, N ,M):
        newGrid = grid.copy()
        for i in range(N):
            for j in range(M):  # 检测网格的8个边缘。用取模运算符让值在边缘折返
                total = int((grid[i, (j - 1) % M] + grid[i, (j + 1) % M] +
                             grid[(i - 1) % N, j] + grid[(i + 1) % N, j] +
                             grid[(i - 1) % N, (j - 1) % M] + grid[(i - 1) % N, (j + 1) % M] +
                             grid[(i + 1) % N, (j - 1) % M] + grid[(i + 1) % N, (j + 1) % M]))
                if grid[i, j] == ON:
                    if (total < 2) or (total > 3):
                        newGrid[i, j] = OFF
                else:
                    if total == 3:
                        newGrid[i, j] = ON
        # update data
        img.set_data(newGrid)
        grid[:] = newGrid[:]
        return img
    

      结果显示:

        1.输入参数有误时:

          

         2.N*N的动图                                                                                                                                                           

                                    

        3.N*M的动图

           

        4.动图显示为:

                             

                

    八、项目github地址

           

     commit记录:

            

    九、问题解决

     1.python模块下载慢

        此次实验中我们用到了numpy和matplotlib两个模块,但是在python的官方网站下载模块不仅速度特别慢,中途还会无缘无故发生无法下载的情况。为了下载这两个模块我们花了比较长的时间,也尝试过在CSDN中下载,最后终于下载过来。

     2.python安装模块pip需升级

        参考教程我先在python中安装模块(在cmd中进入python安装的文件位置,输入命令:python -m pip install numpy),结果报错提示:pip需要先升级。

       

        根据提示我输入命令:python -m pip install --upgrade pip,但是更新到一半又报错了。后查找资料,有博主给出新的命令:python -m pip install -U pip,但是执行还是在中途中断。

        最后看见别人说命令需要多尝试几次,我用系统提示的命令运行了3、4次后,最终pip升级成功。

         

        接下来进入python的scripts中安装两个模块都成功了。

        

      3.pycharm安装模块报错

       参考在pycharm中导入模块的教程,我在本次实验的项目中安装两个模块,但是一直不成功。参考很多教程后,找到了问题所在:由于python与pycharm安装路径不同,导致pycharm的sys.path中少了三个重要的路径。

       解决方法为:file->setting->project->Project Interpreter-> 小齿轮 ->Show All-> 加号->System Interpreter->找到python安装文件中的python.exe->点击确定。然后再导入两个模块即可。

           

       4.无法生成动态地图

         每次执行代码,结果都只显示一张静态图,我们一直以为是代码有问题。针对绘制动图的animation模块的函数,我们在详细学习后还是找不到问题出现的原因。最后查找资料发现pycharm只显示一帧的解决方案,通过设置后成功显示动图。

            

        5.设置地图长宽颠倒

          在升级代码从N*N的地图到N* M的地图时,我们以N为长(横轴),M为宽(纵轴)来执行时,在游戏规则模块发现有数组下标越界的情况,且结果显示的一张静态图的长与宽与我们设想的不一致,所以我们发现长与宽颠倒了。我们将NM交换后,运行成功。

         例:我们输入长N为20,宽M为30,结果报错下标越界,长宽颠倒了。 

             

     十、实验总结

        1.在进行代码编辑之前的准备工作,我们就面临了很多问题,比如模块下载不成功、模块导入不成功等。寻找能正真解决问题的方法也比较漫长,不是方法不适用就是方法不正确,我们参考多个平台(百度、CSDN、博客园等)最终找到解决问题的方法。在成功导入模块之后,我们感觉之前所遇到的问题都不算什么,遇到错误不要怕也不要烦躁,主动去了解都能解决,不要把问题看得过于困难,正是因为我们不懂才会觉得难。解决问题的过程中,我们学习到很多,不仅仅是理论知识,更多的是解决问题的方法与面对错误时的态度。

        2.由于之前学习python只是比较浅显的知识,对于实验中导入的numpy和matplotlib模块了解甚少,所以即使是在参考别人的代码时理解起来还是比较吃力。遇到不会的函数通过查资料,理解其中每个参数的作用,由来及去向,疏通了整个代码的实现流程。在理解得基础上,我们通过调试代码,删除冗余的数据,简化复杂的代码,增加注释最后使代码实现更高效。我们还成功将地图从固定的大小升级为自定义的地图大小。

        3.最终我们的代码实现只有仅仅六十几行,相对比其他代码而言是非常简洁的,可以发现python在可视化方面有着很大的功能与作用。

    结对编程第一阶段:https://www.cnblogs.com/yqw0710/p/12542668.html

    参考文献:

    1、python模块下载地址:https://pypi.org/project        https://www.lfd.uci.edu/~gohlke/pythonlibs

    2、pip升级解决:https://blog.csdn.net/lanluyug/article/details/82878152

    3、python numpy安装方法:https://blog.csdn.net/swjian1997/article/details/82027013?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

    4、pycharm中导入模块报错解决:https://www.cnblogs.com/zhiyuanxiong/p/8948500.html

    5、python设置执行参数argparse介绍:https://blog.csdn.net/Samaritan_x/article/details/84146029

    6、python绘制动图animation模块的使用:https://blog.csdn.net/u013180339/article/details/77002254

    7、pycharm 无法显示动态图片解决:https://www.jianshu.com/p/c6b362fde21c

  • 相关阅读:
    [Swift]LeetCode239. 滑动窗口最大值 | Sliding Window Maximum
    [Swift]LeetCode238. 除自身以外数组的乘积 | Product of Array Except Self
    [Java]LeetCode237. 删除链表中的节点 | Delete Node in a Linked List
    [Swift]LeetCode236. 二叉树的最近公共祖先 | Lowest Common Ancestor of a Binary Tree
    [Swift]LeetCode235. 二叉搜索树的最近公共祖先 | Lowest Common Ancestor of a Binary Search Tree
    [Swift]LeetCode233. 数字1的个数 | Number of Digit One
    [Swift]LeetCode232. 用栈实现队列 | Implement Queue using Stacks
    [Swift]LeetCode230. 二叉搜索树中第K小的元素 | Kth Smallest Element in a BST
    [Swift]LeetCode229. 求众数 II | Majority Element II
    [Swift]LeetCode228. 汇总区间 | Summary Ranges
  • 原文地址:https://www.cnblogs.com/yqw0710/p/12596581.html
Copyright © 2011-2022 走看看