一、实验目标
1)体验敏捷开发中的两人合作。
2)进一步提高个人编程技巧与实践。
二 、实验内容
1)根据以下问题描述,练习结对编程(pair programming)实践;
2)要求学生两人一组,自由组合。每组使用一台计算机,二人共同编码,完成实验要求。
3)要求在结对编程工作期间,两人的角色至少切换 4 次;
4)编程语言不限,版本不限。建议使用 Python 或 JAVA 进行编程。
三、问题描述(生命游戏)
生命游戏是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机,它包括一个二维矩形世界,这个世界中的每个方格居住着一个活着的或死亡的细胞。一个细胞在下一个时刻生死取决于相邻八个方格中活着的或死了的细胞的数量。如果相邻方格活着的细胞数量过多,这个细胞会因为资源匮乏而在下一个时刻死去;相反,如果周围活细胞过少,这个细胞会因太孤单而死去。游戏在一个类似于棋盘一样的,可以无限延伸的二维方格网中进行。例如,设想每个方格中都可放置一个生命细胞,生命细胞只有两种状态:“生”或“死”。图中,用黑色的方格表示该细胞为“死”, 其它颜色表示该细胞为“生” 。游戏开始时, 每个细胞可以随机地(或给定地)被设定为“生”或“死”之一的某个状态, 然后,再根据如下生存定律计算下一代每个细胞的状态:
- 每个细胞的状态由该细胞及周围 8 个细胞上一次的状态所决定;
- 如果一个细胞周围有 3 个细胞为生,则该细胞为生,即该细胞若原先为死则转为生,若原先为生则保持不变;
- 如果一个细胞周围有 2 个细胞为生,则该细胞的生死状态保持不变;
- 在其它情况下,该细胞为死,即该细胞若原先为生则转为死,若原先为死则保持不变。
四、实验内容
1、代码规范:
(1)两个相对独立的程序块、变量说明之后必须要加空行。比如上面几行代码完成的是一个功能,下面几行代码完成的是另一个功能,那么它们中间就要加空行。这样看起来更清晰。
(2)关键字之后要留空格;函数名之后不要留空格,应紧跟左括号(
,以与关键字区别;(
向后紧跟;)
、,
、;
这三个向前紧跟;紧跟处不留空格;,
之后要留空格;赋值运算符、关系运算符、算术运算符、逻辑运算符、位运算符等双目运算符的前后应当加空格;单目运算符等前后不加空格;数组符号[]
、结构体成员运算符.
、指向结构体成员运算符->
,这类操作符前后不加空格;对于表达式比较长的 for 语句和 if 语句,为了紧凑起见,可以适当地去掉一些空格。
(3)成对的符号一定要成对书写,如 ()、{}。不要写完左括号然后写内容最后再补右括号,这样很容易漏掉右括号,尤其是写嵌套程序的时候。
(4)缩进是通过键盘上的 Tab 键实现的,缩进可以使程序更有层次感。原则是:如果地位相等,则不需要缩进;如果属于某一个代码的内部代码就需要缩进。
(5){
和}
分别都要独占一行。互为一对的{
和}
要位于同一列,并且与引用它们的语句左对齐;{}
之内的代码要向内缩进一个 Tab,且同一地位的要左对齐,地位不同的继续缩进。
(6)一行代码只做一件事情,如只定义一个变量,或只写一条语句。这样的代码容易阅读,并且便于写注释;if、else、for、while、do 等语句自占一行,执行语句不得紧跟其后。此外,非常重要的一点是,不论执行语句有多少行,就算只有一行也要加{}
,并且遵循对齐的原则,这样可以防止书写失误。
(7)注释是对代码的“提示”,而不是文档。程序中的注释不可喧宾夺主,注释太多会让人眼花缭乱。如果代码本来就是清楚的,则不必加注释。边写代码边注释,修改代码的同时要修改相应的注释,以保证注释与代码的一致性,不再有用的注释要删除。当代码比较长,特别是有多重嵌套的时候,应当在段落的结束处加注释,这样便于阅读。每一条宏定义的右边必须要有注释,说明其作用。
2、程序的总体设计:
按照游戏规则,首先初始化一个对局函数,然后再调用已存的游戏数据对棋盘进行更新,用到Initialize()初始化函数,RunGame()进行游戏函数,count_cellsNumber()计算生命数量函数,Data()调用游戏数据函数:
3、程序的结对编程过程及功能实现:
首先我们先讨论了如何实现结对编程,决定使用小伙伴的仓库进行实验,小伙伴拟定了初方案,后续我也补了自己的代码,最终完善筛选出最后的代码,虽然小伙伴的代码没有完全采纳,但在实验过程中起到了很重要的铺垫作用。下面是我对小伙伴远程仓库pull request的部分:
多次交换身份提交, 最终仓库整体的构架:
功能的实现包括矩阵的初始化:
void Data()//调用已存的游戏数据 { int i,j; srand((unsigned)time(NULL)); for(i=0;i<N;i++){ for(j=0;j<N;j++) chess[i][j]=rand()%2; }
制定游戏规则:
void cells_state(int i,int j) { int living_cellsnumber=0; living_cellsnumber=count_cellsNumber(i,j); if(chess[i][j]==1){ if(living_cellsnumber<2) chess0[i][j]=0;//如果一个生命周围的生命少于2个,它在回合结束后死亡。 else if(living_cellsnumber>3) chess0[i][j]=0;//如果一个生命周围的生命超过3个,它在回合结束后死亡。 else if(living_cellsnumber==2||living_cellsnumber==3) chess0[i][j]=1;//如果一个生命周围有2或3个生命,它在回合结束时保持原样。 } else if(chess[i][j]==0){ if(living_cellsnumber==3) chess0[i][j]=1;//如果一个死格周围有3个生命,它在回合结束时获得生命。 } }
计算生命周围数量:
int count_cellsNumber(int xline,int yline)//计算生命周围的生命数量 { int living_cellsnumber=0,i,j; for(i=-1;i<=1;i++){ for(j=-1;j<=1;j++){ if(!(i==0&&j==0)&&chess[xline+i][yline+j]==1) living_cellsnumber++; } }return living_cellsnumber; }
进行游戏:
void RunGame()//进行游戏 { int i,j,s=0; int flag=0; while(1) { system("cls");//清理屏幕,准备写入 for(i=1;i<N+1;i++) { for(j=1;j<N+1;j++) if(chess[i][j]==1) printf("█");//printf("■"); else if(chess[i][j]==0) printf(" "); printf("\n"); } for(i=1;i<N+1;i++) for(j=1;j<N+1;j++) { cells_state(i,j); } for(i=1;i<N+1;i++) for(j=1;j<N+1;j++) chess[i][j]=chess0[i][j]; Sleep(10); if(flag==0) { getchar(); flag=1; } } }
运行如何所示:
4、项目的github地址:
https://github.com/dss-nnh/my-travel-plans
五、实验总结
本次实验为结对编程的第二阶段,旨在增强小组内两人之间的协作与交流,实验过程中遇到了一些问题,比如运行界面不够美观,代码不够完善,使用仓库不够灵活等问题,也出现过很多次“懒政”的行为,多亏了小伙伴的鼓励,让我感受到了完成一件事的快乐,下次还需要继续努力,认真加强自己编程上的不足。
原文地址:https://www.cnblogs.com/xy1229/p/12590742.html