实验二 结对编程之第二阶段

一、实验目标
  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

原文地址:https://www.cnblogs.com/yqw0710/p/12596581.html