实验二-结对编程第二阶段
一、实验目标:
1)体验敏捷开发中的两人合作。
2)进一步提高个人编程技巧与实践。
二 、实验内容:
1)根据以下问题描述,练习结对编程(pair programming)实践;
2)要求学生两人一组,自由组合。每组使用一台计算机,二人共同编码,完成实验要求。
3)要求在结对编程工作期间,两人的角色至少切换 4 次;
4)编程语言不限,版本不限。建议使用 Python 或 JAVA 进行编程。
三、实验记录:
1.关于结对编程和敏捷开发
通过百度百科查阅资料等获知敏捷开发是以用户的需求进化为核心,采用迭代、循序渐进的方法进行软件开发。在敏捷开发中,软件项目在构建初期被切分成多个子项目,各个子项目的成果都经过测试,具备可视、可集成和可运行使用的特征。换言之,就是把一个大项目分为多个相互联系,但也可独立运行的小项目,并分别完成,在此过程中软件一直处于可使用状态。敏捷建模主张简单,拥抱变化,第二个目标可持续性等核心原则。
结对编程(英语:Pair programming)是一种敏捷软件开发的方法,两个程序员在一个计算机上共同工作。一个人输入代码,而另一个人审查他输入的每一行代码。输入代码的人称作驾驶员,审查代码的人称作观察员(或导航员)。两个程序员经常互换角色。在结对编程中,观察员同时考虑工作的战略性方向,提出改进的意见,或将来可能出现的问题以便处理。这样使得驾驶者可以集中全部注意力在完成当前任务的“战术”方面。观察员当作安全网和指南。结对编程对开发程序有很多好处。比如增加纪律性,写出更好的代码等。结对编程是极端编程的组成部分。
2.组队情况
纪超超:博客地址(https://www.cnblgs.com/aspic/)
刘莹:博客地址(https://www.cnblogs.com/lldkla/)
选择课题:生命游戏
github仓库地址:https://github.com/DKLA5/software-test.git
3.课题理解
生命游戏是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机,它包括一个二维矩形世界,这个世界中的每个方格居住着一个活着的或死亡的细胞。一个细胞在下一个时刻生死取决于相邻八个方格中活着的或死了的细胞的数量。如果相邻方格活着的细胞数量过多,这个细胞会因为资源匮乏而在下一个时刻死去;相反,如果周围活细胞过少,这个细胞会因太孤单而死去。游戏在一个类似于围棋棋盘一样的,可以无限延伸的二维方格网中进行。例如,设想每个方格中都可放置一个生命细胞,生命细胞只有两种状态:“生”或“死”。 游戏开始时, 每个细胞可以随机地(或给定地)被设定为“生”或“死”之一的某个状态, 然后,再根据如下生存定律计算下一代每个细胞的状态:每个细胞的状态由该细胞及周围 8 个细胞上一次的状态所决定;如果一个细胞周围有 3 个细胞为生,则该细胞为生,即该细胞若原先为死则转为生,若原先为生则保持不变;如果一个细胞周围有 2 个细胞为生,则该细胞的生死状态保持不变;在其它情况下,该细胞为死,即该细胞若原先为生则转为死,若原先为死则保持不变。
根据查阅的资料,生命游戏与局部多数模型的关键区别在于,在这里,元胞的更新规则有两个阈值,并且所有的元胞都同步更新自己的状态。因此,在生命游戏中,我们可以说初始配置如何如何,时间的配置如何如何等等。还可以把同步更新视为一个“进行曲”动态机制。编写生命游戏,通过以上规则进行迭代变化,使细胞生生死死,得到不一样的结果。初始设置每个细胞,依据上述的游戏规则演绎生命的变化,而初始状态和迭代次数的不同,可以获得精彩纷呈的图案。
4.开发工具
经过简单讨论我们决定使用vc++来编写该程序,VC++的界面简洁,操作方便,占用资源少,比较适合我们初次结对编程的菜鸟。用github作为远程仓库,进行观察和修改。
5.关于实验的思考
一个人编程作业量大,而且容错率较低, 结对编程技术可以达到事半功倍的效果,在遇到问题的时候,可以快速的找到解决的方案,两个程序员共同的错误和盲点可能性很小。互换身份有利于自身的提高,方便我们思考。
四、实验过程:
1、代码规范
代码规范化的第一个好处就是看着很整齐、很舒服。假如用不规范的方式写了若干行代码,即便自己对代码很熟悉,过了一天可能看起来就很吃力了,更不要说给别人看了。而且代码不规范在出现错误的时候,找错也是一件很麻烦的事情,大大增加了自己的工作量,所以代码要写规范。
代码的规范可以注意以下几点:
(1)空行
空行起着分隔程序段落的作用。空行得体将使程序的布局更加清晰。空行不会浪费内存,虽然打印含有空行的程序会多消耗一些纸张,但是值得。定义变量后要空行。尽可能在定义变量的同时初始化该变量,即遵循就近原则。如果变量的引用和定义相隔比较远,那么变量的初始化就很容易被忘记。若引用了未被初始化的变量,就会导致程序出错。每个函数定义结束之后都要加空行。
两个相对独立的程序块、变量说明之后必须要加空行。比如上面几行代码完成的是一个功能,下面几行代码完成的是另一个功能,那么它们中间就要加空行。这样看起来更清晰。
(2)缩进与对齐
缩进是通过键盘上的 Tab 键实现的,缩进可以使程序更有层次感。原则是:如果地位相等,则不需要缩进;如果属于某一个代码的内部代码就需要缩进。
此外编程软件还有“对齐、缩进修正”功能。就是按 Ctrl+A 全选,然后按 Alt+F8,这时程序中所有成对的大括号都会自动对齐,未缩进的也会自动缩进。不管是在编程过程中,还是在编写结束完之后,都可以使用这个技巧。但如果完全按照规范写,那根本就不需要这个技巧,所以,这只是一个辅助功能。
(3)注释
C语言中一行注释一般采用//…,多行注释必须采用/*…*/。注释通常用于重要的代码行或段落提示。在一般情况下,源程序有效注释量必须在 20% 以上。虽然注释有助于理解代码,但注意不可过多地使用注释。注释是对代码的“提示”,而不是文档。程序中的注释不可喧宾夺主,注释太多会让人眼花缭乱。如果代码本来就是清楚的,则不必加注释。边写代码边注释,修改代码的同时要修改相应的注释,以保证注释与代码的一致性,不再有用的注释要删除。当代码比较长,特别是有多重嵌套的时候,应当在段落的结束处加注释,这样便于阅读。每一条宏定义的右边必须要有注释,说明其作用。
(4)命名
只要提到代码规范,就不得不说的一个问题。在一些小的演示程序中,也许费尽心思去构思一个 命名 是一件十分傻的行为,但是只要程序上升到你需要严正设计,思考,复查的层次,就需要好好考虑 命名 这个问题。
C语言中,我们可以让下划线或者词汇帮助我们表达函数功能。例如define函数的命名,define,无参宏定义的一般形式为:#define 标识符 字符串,define 函数定义一个常量。常量类似变量,不同之处在于:在设定以后,常量的值无法更改。常量名不需要开头的美元符号 ($)。作用域不影响对常量的访问 。常量值只能是字符串或数字。
参考网址:http://c.biancheng.net/view/158.html
2、程序的总体设计(附图说明模块之间的关系)
(1)算法思想
假设有int Cells[30][30],也即有30×30个小格子,每个小格子里面可以有细胞生命,或者细胞死亡。通过把这些状态输出出来,就可以显示出相应的图案。通过对生命游戏的理解,可以体会二维数组在游戏开发中的应用,可以记录画布中的所有数据,并把画面显示、数据更新两块隔离开,便于程序的维护和更新。
(2)流程图

3、程序结对编程过程(附图)及功能实现情况(附代码和图)
(1)结对编程过程
我们采用QQ屏幕分享功能,做到一个人编写代码,一个监督和纠错。由我负责变量名、数据初始化以及主函数的编写,其他部分由我的队友负责。
我们通过github托管,队友已经在github上建好仓库,fork她的仓库地址,在git bash上提交修改,可以实现两人共同编写一个代码。

下面是我提交的第一次补充和修改

队友在merge我的修改申请后,git pull将github上的文件拉下来,并继续补充修改。下面是我的第二次提交


至此,本次生命游戏代码的编写就告一段落了。
(2)功能实现情况
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#include <time.h>
#define L 30 // 游戏画面尺寸
#define W 60
// 全局变量
int cells[L][W]; // 所有位置细胞生1或死0
void gotoxy(int x,int y)//类似于清屏函数
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(handle,pos);
}
void startup() // 数据初始化
{
int i,j;
for (i=0;i<L;i++) // 初始化
for (j=0;j<W;j++)
{
cells[i][j] = 1;
}
}
void show() // 显示画面
{
gotoxy(0,0); // 清屏
int i,j;
for (i=1;i<=L-1;i++)
{
for (j=1;j<=W-1;j++)
{
if (cells[i][j]==1)
printf("●"); // 输出活的细胞
else
printf("○"); // 输出空格
}
printf("\n");
}
Sleep(500);
}
void updateWithoutInput() // 与用户输入无关的更新
{
int NewCells[L][W]; // 下一帧的细胞情况
int NeibourNumber; //统计邻居的个数
int i,j;
for (i=1;i<=L-1;i++)
{
for (j=1;j<=W-1;j++)
{
NeibourNumber = cells[i-1][j-1] + cells[i-1][j] + cells[i-1][j+1]
+ cells[i][j-1] + cells[i][j+1] + cells[i+1][j-1] + cells[i+1][j] + cells[i+1][j+1];
if (NeibourNumber==3)
NewCells[i][j] = 1;
else if (NeibourNumber==2)
NewCells[i][j] = cells[i][j];
else
NewCells[i][j] = 0;
}
}
for (i=1;i<=L-1;i++)
for (j=1;j<=W-1;j++)
cells[i][j] = NewCells[i][j];
}
void updateWithInput() // 与用户输入有关的更新
{
}
void main()
{
startup(); // 数据初始化
while (1) // 游戏循环执行
{
show(); // 显示画面
updateWithoutInput(); // 与用户输入无关的更新
updateWithInput(); // 与用户输入有关的更新
}
}
运行结果如下

参考代码:https://zhuanlan.zhihu.com/p/24768071
4、项目github地址(附图)
地址:https://github.com/DKLA5/software-test

5、实验总结
这次的结对实验花费了我们不少时间,通过生命游戏这种相对不是很复杂的程序的编写,让我初步体验并且熟悉了结对实验的操作过程。或许远程仓库的修改和提交不熟悉的情况下会比较麻烦,但是其中也有和同伴合作才有的快乐。而且两人合作确实在代码的出错率上有很大的改善,编写的过程也出现了很多奇思妙想,即使是对我这样的菜鸟也受益颇深。在不断地克服困难中获得了无与伦比的成就感,这种成就感不亚于在高考时解决了最后一道数学大题。感谢编程让我找回了青春的感觉。


浙公网安备 33010602011771号