一、结对编程题目及其要求
黄金点游戏是一个数字小游戏,其游戏规则是:
N个同学(N通常大于10),每人写一个0~100之间的有理数 (不包括0或100),交给裁判,裁判算出所有数字的平均值,然后乘以0.618(所谓黄金分割常数),得到G值。提交的数字最靠近G(取绝对值)的同学得到N分,离G最远的同学得到-2分,其他同学得0分。玩了几天以后,大家发现了一些很有意思的现象,比如黄金点在逐渐地往下移动。
现在请大家根据这个游戏规则,编一个可以多人一起玩的小游戏程序,要求如下:
1、本作业属于结对编程项目,必须由二人共同完成,并分别将本次作业过程发到博客,同时将本次作业源代码提交到codeing系统;
2、如果可能的话尽量以C/S或B/S方式实现,即利用服务器接收和处理所有玩家提交的数字,并将结果反馈给各玩家,玩家可以通过客户端提交的数字;
3、如果采用单机方式实现的话,需要为用户提供便利的输入界面;
4、该游戏每次至少可以运行10轮以上,并能够保留各轮比赛结果。
二、需求分析
从题目的要求上来看,这次的结对编程主要是要实现黄金点游戏的编程。而具体的黄金点游戏在上面的题目以及要求里面已经说的很清楚:可以实现N个同学进行黄金点游戏,每个同学随机给1-99之间的任意有理数,通过计算机计算实现求出平均值以后乘以0.618得到G值,即所谓的黄金分割常数。
各位同学的分数也很有意思,距离G点最近的数字的同学得分最高为N分,最远的同学为最低分-1分,其他中间的同学为0分。
三、功能分析
由上面的要求以及需求分析来看,我们的编程要实现的功能是很清晰的。首先要实现能够输入N个同学的数字并进行存储,待输入结束后,可以进行黄金点值的计算,之后将每一位玩家的分数与得到的黄金点值进行比较,即相减之后的绝对值最小的得到的分数最多,为参加游戏的人数;绝对值最大的分数最低,为-2分;其他的分数为0分。分别将各位同学的分数进行统计,并可以在每轮游戏结束后看到该玩家总共得到了多少分以及每轮分数。
四、具体实现
鉴于上面的需求分析以及功能分析,我和我的队友张威同学进行了讨论,基本的小功能我们都能通过已经学过的知识来实现。基于以上的功能板块的分析,我们决定用C++来实现这个小游戏。看了别的结对编程的小伙伴们的博客,相比较之下就感觉我们的小游戏真的是一个“小”游戏,还是有很多的大神用了很多的高大上的“武器”。羡慕之余想到的是每一个小组都有自己的风格,我们的小程序随感看起来简单很“小”,可我们贵在简炼、精巧。
首先是我们用到的变量:我们用N和M来实现分别控制游戏的轮数和参加游戏的人数,用数组S[100]来存储我们的玩家输入的数字num,i,j为循环控制变量,S2和S3数组是后面用来实现对每轮的游戏分数进行统计的。下面的双精度变量ave、sum、G分别为平均值、玩家数字之和以及判断点G,max、min为下面为了给出分数而设置的最大值和最小值。
int i, j, num, N, M, S[100], S2[100], S3[100] = { 0};
double S1[100], ave,sum,G;
double max, min;
下面就是一个对于初玩者基本的介绍,这里就不再一一赘述。如图所示为我们的进入画面:
整体最主要的部分也就是实现玩家输入数字计算G值的部分我们是通过两个嵌套的for循环实现的,实现每一轮的玩家输入数字并进行计算数字之和sum,平均值ave,然后算出这一轮的G值。到下一轮游戏就重复以上过程。
for (i = 1; i <= N; i++)
{
sum = 0;
G = 0;
cout << "Input the number between 1 to 100." << endl;
for (j = 1; j <= M; j++)
{
cout <<" Player " << j << " input your choose!" << endl;
cin >> num;
S[j] = num;
sum = sum + S[j];
}
ave = sum / num;
G = ave*0.618;
cout << "黄金点是G=" << G << endl;
下图为输入的图片:
下一步就是要实现给出每个玩家评判的分数,我们通过构造了数组S2和S3来分别存储。利用库函数math.h函数中的abs()函数实现计算每一位玩家的数字与G值得绝对值大小,从而实现绝对值最小的给N分,最大的给-2分,其他取得都是0分。并且予以显示。
for (j = 1; j <= M; j++)
{
S1[j] = abs(S[j] - G);
}
max = min = S1[1];
for (j = 1; j <= M; j++)
{
if (S1[j] >= max)
max = S1[j];
else if (S1[j] < min)
min = S1[j];
}
for (j = 1; j <= M; j++)
{
if (S1[j] == max)
S2[j] = -2;
else if (S1[j] == min)
S2[j] = M;
else S2[j] = 0;
}
上面为计算分数的程序。
for (j = 1; j <= M; j++)
{
cout << "本轮分数" << "S2[" << j << "]=" << S2[j] << endl;
S3[j] = S3[j] + S2[j];
cout << "总分数 " << "S3[" << j << "]=" << S3[j] << endl;
}
上面为显示分数的程序。
以上为运行的图片显示。
下面位运行的第二轮游戏:
通过对S3数组的如下操作实现对两轮分数的求和,并且显示:
...........
直到轮数运行完毕:
五、结对编程的感悟以及对队友的评价
以前的时候,当有一个写程序的任务来了的时候总是会犯“拖延症”,不到最后一天都不怎么操心去想或者开始着手去准备。进行了结对编程之后,我才发现了这种编程模式的好处,在这种模式下,我和我的小伙伴肩并肩地、平等地、互补地进行编程。看了书上的说法,我们用一台电脑,面对同一个显示器,使用同一个键盘、同一个鼠标一起工作;一起分析,一起设计,一起改进,一起进步。这样的结果就是我们都提高了自己的综合水平。
由于我今年要考研,所以老师提出的要求并没有做到尽善尽美,像老师说的C/S或B/S即即利用服务器接收和处理所有玩家提交的数字,并将结果反馈给各玩家,玩家可以通过客户端提交的数字的功能并没有实现。但是体验了一把结对编程的乐趣也未尝不是一种很好的收获。
我的结对编程队友是我们班的张威同学,对他在一开始的时候并不是很了解。只是觉得应该是一个很聪明的同学,在一起编程之后才发现原来不仅如此。我在这次结对编程的任务中主要负责的是前期的需求分析和程序整体的设计,以及后期的代码复审以及功能的补充。张威同学负责完成初次的代码设计,之后我们在复审以及补充功能上面进行了多次探讨以及互换身份的复审,小伙伴是一个虽然看起来不太努力,但是真正努力起来非常认真刻苦,能够坚持自己的看法,并且也有督促我好好学习的方面。
总之,这是一次虽然中间有许多困难,最终也都被我们一一拿下的经历,相信会在以后的发展中给与我们很多的帮助。非常感谢老师给我们这样一次在大学里就体验了一次结对编程的机会,我们定当努力,不负老师所望。
附图:
- 结对伙伴博客地址:http://www.cnblogs.com/zw2013040101034/
- 我的coding主页地址:https://coding.net/u/wanjhon
- 小伙伴coding地址:https://coding.net/u/2013040101034