结对编程——黄金点游戏
前言:经过一个多月的软件工程这门课的学习,总的来说受益良多。了解到如何才是一个合格的程序,合格的程序员。并不是说一个程序能运行才是程序,而是各方面,诸如界面,简洁,效率,完善都要做到完美。一个好的程序员不仅要满足客户的需求,还要自己寻找以后可能出现的问题,并保证程序可扩充性。本学期我们会有个人项目,结对项目,团队项目的一步一步深入地学习,那么这次我们接到了组队编程的任务。
任务:本次结对编程的题目如下:黄金点游戏是一个数字小游戏,其游戏规则是:
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轮以上,并能够保留各轮比赛结果。
人员:本次结对编程,我的队友是胡林状,他是我的班上唯一的安徽老乡。他做事比较低调,默默勤劳工作。我们这次编程遇到的诸多问题,我们都有积极探讨并交换了意见。
我的coding地址:https://coding.net/u/lvjianxiong
胡林状的coding地址:https://coding.net/u/hulinzhuang
胡林状的博客地址:http://www.cnblogs.com/hulinzhuang/
编程过程:我们积极地首先对题目开始分析,理解题目究竟是什么意思,玩的是个什么游戏,我们在编程之前自己用笔代替电脑,走了一遍游戏的流程。我觉得这是很有必要的。然后进入编程环节,本次选择的编程语言是C语言(C++没有C语言通俗易懂;JAVA还处于自学阶段,还不足以编程)。N个同学每人输入一个有理数,用scanf函数很容易实现;求和然后取平均值,再算G点值,这是最简单的计算;然后比较每个值与G点的接近程度,但是考虑到不是简单的减法,因为你不知道哪个值大,如果存在绝对值的符号就好了。百度知道,fabs就是求浮点数的绝对值。这也算是一个小小的收获吧,之前还不知道呢;至于给分的模块,我们可以设定一个max和min值,初值均赋为第一个数值,后面的数值挨个和初值比较,最终得到这组数据的最大值和最小值。最大值赋予N分,最小值-2分,其他的值不做任何变动即可。
程序源代码
#include "stdafx.h"
#include "stdlib.h"
#include "windows.h"
#include "math.h"
typedef struct gameplayer //定义玩家结构体
{
int name;
int score;
float number;
}PLAYER; //含有玩家的姓名,分数,编号,分数信息
每个玩家涉及信息量较多,我们很自然选用了结构体。
void startgame(FILE *fp); //游戏的初始化
void gamerule(); //游戏规则
void suan_score(PLAYER *p,float ave,int num,FILE *fp);//计算比赛得分的函数
这里我们主要用到这几个函数。
int main()
{
system("color 3B");
int choice;
FILE *fp;
while(1)
{
fp=fopen("goldgame.txt","w+");
printf("\n 黄金点游戏 \n\n");
printf(" 1. 游戏规则\n");
printf(" 2. 开始游戏\n");
printf(" 3. 退出游戏\n");
scanf("%d",&choice);
switch(choice)
{
case 1: gamerule(); break;
case 2: startgame(fp); break;
case 3: exit(0); break;
default:
{
printf(" 您的输入有误,请重新输入\n");
break;
}
}
}
return 0;
}
主函数,我们设计了初始界面:包括开始游戏,游戏规则,退出游戏简单的功能。用SWITCH函数读取玩家的操作。
void startgame(FILE *fp)
{
PLAYER *p;
int i,playernum,gamenum,j;
int flag=1;
float sum,ave;
char choice;
p=(PLAYER *)malloc(10*sizeof(PLAYER)); //动态分配结构体数组
printf("请输入参与的玩家数:");
scanf("%d",&playernum);
if(playernum>10)
{
p=(PLAYER *)realloc(p,playernum*sizeof(PLAYER));//空间不足而需要增加空间
}
printf("请输入比赛轮次:");
scanf("%d",&gamenum);
printf("\n");
for(j=0;j<gamenum;j++)
{
printf("第%d轮比赛:\n",j+1);
for(i=0,sum=0 ;i<playernum;i++)//sum设为总数和
{
if(flag==1)
{
p[i].name=i+1;
p[i].score=0;
p[i].win=0;
p[i].fail=0;
} //初始化初值为0
printf(" 玩家%d: ",p[i].name);
scanf("%f",&p[i].number);
sum+=p[i].number;
}
ave=sum/playernum; //计算平均值
ave=(float)(ave*0.618); //计算黄金点的值
printf(" 黄金点G的值为:%f\n",ave);
suan_score(p,ave,playernum,fp);
flag=0;
}
}
这是开始化游戏函数,动态分配内存空间,如果不够,需要补充空间。主要进行玩家人数和游戏轮次的设定,然后读取玩家各个数值,计算G点值,进入suan_score函数。
void suan_score(PLAYER *p,float ave,int num,FILE *fp)
{
int i;
char ch;
float max=(float)fabs(p[0].number-ave);
float min=(float)fabs(p[0].number-ave);
for(i=0;i<num;i++) //统计出本轮最大值,最小值
{
p[i].b=(float)fabs(p[i].number-ave);
if(max<p[i].b)
max=p[i].b;
if(min>p[i].b)
min=p[i].b;
}
for(i=0;i<num;i++) //挨个玩家赋予成绩
{
if(p[i].b==max)
{
p[i].score-=2;
}
if(p[i].b==min)
{
p[i].score+=num;
}
}
printf("累计比赛的得分:\n");
for(i=0;i<num;i++) //挨个玩家输出成绩
printf(" 玩家%d: %d\n",p[i].name,p[i].score);
while(1)
{
printf("是否继续 Y or N : ");
scanf("%c",&ch);
if(ch=='y'||ch=='Y')
{
break;
}
else if(ch=='n'||ch=='N')
{
exit(0);
}
}
}
这是给各玩家赋予成绩的函数,首先max和min均设为第一个玩家的数值,然后后继的数值挨个比较,选出本组数值最大值和最小值。最后比较得到最大值的玩家+N,得到最小值玩家—2,其他玩家我们不进行任何操作。输出每个玩家的成绩并进行下一轮的游戏。
void gamerule()
{
printf(" N个同学(N通常大于10),每人写一个0~100之间的有理数(不包括0或100),裁判算出所有数字的平均值,然后乘以0.618(所谓黄金分割常数),得到G值。提交的数字最靠近G(取绝对值)的同学得到N分,离G最远的同学得到-2分,其他同学得0分。\n\n");
}
这个就是读取游戏规则函数,就是简单的printf就可以完成。
总结:由于我们小队两个人都是考研的,就连周六周日都有课程,时间相对比较匆忙,本次编程也算抽时间完成了。虽然不够完美,我们也曾想做到完美,但是还是限于自己的能力以及时间的紧张,没有做到心中的完美。但是还是很有收获的,集思广益,团队的力量可以使问题变得简单一些,虽然仅仅是两个人。希望后续的作业,我们都能尽自己最大的努力去完成,一定会有回报的吧。