一、实验目标:
1)体验敏捷开发中的两人合作。
2)进一步提高个人编程技巧与实践。
二 、实验内容:
1)根据以下问题描述,练习结对编程(pair programming)实践;
2)要求学生两人一组,自由组合。每组使用一台计算机,二人共同编码,完成实验要求。
3)要求在结对编程工作期间,两人的角色至少切换 4 次;
4)编程语言不限,版本不限。建议使用 Python 或 JAVA 进行编程。
三、问题描述
1)生命游戏
生命游戏是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机,它包括一个二维矩形世界,这个世界中的每个方格居住着一个活着的或死亡的细胞。一个细胞在下一个时刻生死取决于相邻八个方格中活着的或死了的细胞的数量。如果相邻方格活着的细胞数量过多,这个细胞会因为资源匮乏而在下一个时刻死去;相反,如果周围活细胞过少,这个细胞会因太孤单而死去。
游戏在一个类似于围棋棋盘一样的,可以无限延伸的二维方格网中进行。例如,设想每个方格中都可放置一个生命细胞,生命细胞只有两种状态:“生”或“死”。图中,用黑色的方格表示该细胞为“死”, 其它颜色表示该细胞为“生” 。
游戏开始时, 每个细胞可以随机地(或给定地)被设定为“生”或“死”之一的某个状态, 然后,再根据如下生存定律计算下一代每个细胞的状态:
每个细胞的状态由该细胞及周围 8 个细胞上一次的状态所决定;
如果一个细胞周围有 3 个细胞为生,则该细胞为生,即该细胞若原先为死则转为生,若原先为生则保持不变;
如果一个细胞周围有 2 个细胞为生,则该细胞的生死状态保持不变;
在其它情况下,该细胞为死,即该细胞若原先为生则转为死,若原先为死则保持不变。
结对编程 第一周记录
选题 | 生命游戏 |
开发工具 | Eclipse |
组员学号 | 3170701128、31707011 |
Github地址 | https://github.com/wbr1224/LifeGame |
博客园地址 |
一、代码规范准备
此次结对编程我们选用的语言是Java,相应的代代码规可参考这一篇博文https://www.cnblogs.com/xiaocai0923/p/10698824.html。
首先我们讨论了一下
二、敏捷开发、结对编程理解与准备
1、敏捷开发理解
所谓结对编程,也就是两个人写一个程序,一个人负责写代码,另一个人负责审阅检查,两个人的角色时常互换,这样思考和计划才能更加缜密,错误会少一点,同时也能提升双方编程能力
关于对结对编程的理解,可以参考这一篇博文https://www.cnblogs.com/lcw/p/3601257.html。
2、结对编程准备
我们使用GitHub托管我们的源代码。首先我在GitHub上把项目的创建好,再在本地创建好项目、仓库,然后使用git 上传到我的GitHub上
然后在GitHub仓库的setting里设置contributor,搜索用户名就能添加协作者,这样就能能很方便的一起协作项目,不用fork我的主仓库了
我们使用QQ远程演示来完成结对编程,这样交流比较方便,
一遍讨论一边写,但是家里人太多有些吵,就用文字交流了,有时候我觉得文字表述比对话好一点,尤其是解释一些关系的时候。上图是我的partner写的cell类,以下是我的写的Map类
在整个项目我们进行了四次交换
编辑人 | 交换目的 | |
第一次交换 | partner | 编写Cell类 |
第二次交换 | 我 | 编写Map类 |
第三次交换 | partner | 测试Map类中规则逻辑 |
第四次交换 | 我 | 编写总调用GUI |
总的来说配合的还不错,写代码时互相提醒,写出的代码基本不会出太大的错误
三、对于生命游戏的分析
生命游戏的规则不在赘述了,这篇博客里介绍了很多种玩法https://www.cnblogs.com/lfri/p/9733883.html,还有一个模拟软件Golly(https://pan.baidu.com/s/1dUrbioy7Ai9Q2_4Tb5vWwQ 提取码:bl5n )可以随意设定初始条件,蛮有趣的。
(1)数据结构
我们采用二维数组来构建游戏,即Cell二维矩阵,Cell是一个类,将会在下面介绍。
(2)类方法描述
经过讨论后,我们决定写三个类,分别是Cell、Map、showGame。
Cell:
作用:Cell类包含了当前细胞的状态,周围活细胞数
主要方法:含参数status的构造方法public Cell(int stau) ,设定下一轮状态的方法public void setNextStatus();
Map:
作用:Map类用于构造地图,继承了Jpanel,使用drawrect()、fillrect()方法画矩形
主要方法:更新地图上所有细胞的下一轮状态(death or live)public void updateStatus(),一个重写方法用于绘制矩形public void paintComponent(Graphics g)
showGame:
作用:这是一个总调用的类,基础了JFrame
主要方法:含有一个构造方法public showGame()
类名 | 包含字段 | 包含方法 |
Cell | int Status
int LivingNum |
public Cell(int stau) ; public void setNextStatus(); |
Map |
int Height |
public void updateStatus(); public void paintComponent; |
showGame | final Map m; | public showGame() |
(3)基本流程
初步设计的基本流程如下:
(4)模块功能关系
各个模块如下
各个模块之间调用关系:
(6)主要函数代码
1、Cell中的设定下一轮状态方法
public void setNextStatus() { //TODO judge the next round status of cells if(this.getLivingNum() == 3) { this.setCellStatus(1); } else if(this.getLivingNum()<2 || this.getLivingNum()>3){ //other numbers will lead to death this.setCellStatus(0); } else { //remain the status this.setCellStatus(this.Status); } }
2、初始化Cell矩阵,使用代码块
public Cell [][]cell = new Cell[Height][Width]; { //TODO start the map with a random situation for(int i = 0;i<Height;i++) { for(int j = 0;j<Width;j++) { Random r = new Random(); this.cell[i][j] = new Cell(r.nextInt(2)); } } }
3、更新状态模块
这里我和partner有两种方案,一种就是在最外层再加一层,就相当于墙壁,这样cell矩阵计算就方便了,还有一种就是用if来判断,我们讨论了使用第二种,因为这样节省了资源
public void updateStatus() { //TODO count the number of living cell in matrix each round int sourroundingAliveNum = 0; for(int x=0;x<Height;x++) { for(int y=0;y<Width;y++) { if(isvalideCell(x-1, y-1) && (cell[x-1][y-1].getCellStatus() == 1)) sourroundingAliveNum++; if(isvalideCell(x-1, y) && (cell[x-1][y].getCellStatus() == 1)) sourroundingAliveNum++; if(isvalideCell(x-1, y+1) && (cell[x-1][y+1].getCellStatus() == 1)) sourroundingAliveNum++; if(isvalideCell(x, y-1) && (cell[x][y-1].getCellStatus() == 1)) sourroundingAliveNum++; if(isvalideCell(x, y+1) && (cell[x][y+1].getCellStatus() == 1)) sourroundingAliveNum++; if(isvalideCell(x+1, y-1) && (cell[x+1][y-1].getCellStatus() == 1)) sourroundingAliveNum++; if(isvalideCell(x+1, y) && (cell[x+1][y].getCellStatus() == 1)) sourroundingAliveNum++; if(isvalideCell(x+1, y+1) && (cell[x+1][y+1].getCellStatus() == 1)) sourroundingAliveNum++; cell[x][y].setLivingNum(sourroundingAliveNum); sourroundingAliveNum = 0; } } for(int x=0;x<Height;x++) { for(int y=0;y<Width;y++) { cell[x][y].setNextStatus(); } } }
4、GUL显示模块
public void paintComponent(Graphics g) { super.paintComponent(g); for(int i=0;i<Height;i++) { for(int j=0;j<Width;j++) { if(cell[i][j].getCellStatus() == 1) { g.fillRect(j*20, i*20, 20, 20); //fill rectangles with black } else { g.drawRect(j*20, i*20, 20, 20); //draw rectangles } } } }
四、总结
这一次结对编程,让我体会很深刻,以前都是一个人写代码,导致我的代码风格和partner的差好多;在命名的时候,我有时候不太喜欢partner的命名,为此我们之间要讨论好久,最后用谷歌翻译;我们对编程语言熟练程度不同,有时候要去解释代码。协助是一个大问题,这也是我日后需要去锻炼的,一个大的项目不是一个人就能完成的,往往要和很多人协作,所以要培养沟通能力,加强编程,才能提升自己。
附gif:
多试几次会有比较有趣的图案