黄金点游戏
项目要求:
黄金点游戏是一个数字小游戏,其游戏规则是:
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/dujuan105
赵伟莨的coding地址:https://coding.net/u/zhaoweiliang
赵伟莨的博客地址为:http://www.cnblogs.com/zhaoweiliang/
功能实现:
用结构体保存玩家信息,包括编号,得分,玩家输入的数字,输赢次数,number和黄金点差值的绝对值。主函数绘制菜单界面。具体代码如下:
#include "stdio.h" #include "stdlib.h" #include "windows.h" #include "math.h" #include "string.h" typedef struct player { int name; int score; float number; float b; int win; int fail; }PLAYER; //保存玩家信息 void setup_game(FILE *fp); //保存玩家的初始化函数 void print_rule(); //打印游戏规则函数 void set_score(PLAYER *p,float ave,int num,FILE *fp);//计算得分函数 void save_file(FILE *fp,PLAYER *p,int n,int num);//将成绩保存到文件中 void lookup(FILE *fp,int num2,int a);//从文件中读取玩家信息 int main() { int select; FILE *fp; system("color 9E"); while(1) { if((fp=fopen("a.txt","w+"))==NULL) { printf("无法创建文件保存记录!\n"); exit(0); } printf("\t\t\t ********黄金点游戏********\n\n"); printf("\t\t\t\t1. 开始游戏PK\n"); printf("\t\t\t\t2. 游戏规则^_^\n"); printf("\t\t\t\t3. 退出游戏\n"); scanf("%d",&select); switch(select) { case 1: setup_game(fp); break; case 2: print_rule(); break; case 3: exit(0); break; default: { printf("\t\t\t 您的输入有误,请重新输入\n"); Sleep(1000); system("cls"); break; } } } return 0; }
void setup_game(FILE *fp)用于初始化数据。在for循环中首先对数据初始化,计算出黄金点的值,将参数传入子函数可计算玩家得分,获取玩家信息等功能。
void setup_game(FILE *fp) { PLAYER *p; int i,num1,num2,j; int flag=1; float sum,ave; char select; p=(PLAYER *)malloc(10*sizeof(PLAYER)); printf("请输入玩家人数:"); scanf("%d",&num1); if(num1>10) { p=(PLAYER *)realloc(p,num1*sizeof(PLAYER));//若空间不足,则增加空间 } printf("请输入比赛轮次:"); scanf("%d",&num2); printf("\n"); for(j=0;j<num2;j++) { printf("第%d轮比赛:\n",j+1); for(i=0,sum=0 ;i<num1;i++) { if(flag==1) { p[i].name=i+1; p[i].score=0;//初始化操作 p[i].win=0; p[i].fail=0; } printf("\t\t\t\t玩家%d: ",p[i].name); scanf("%f",&p[i].number); sum+=p[i].number; } ave=sum/num1; ave=(float)(ave*0.618);//计算黄金点 printf("\n\t\t\t黄金点G的值为:%f\n",ave); set_score(p,ave,num1,fp); save_file(fp,p,j,num1); flag=0; } rewind(fp); printf("比赛已完成,是否查看各轮成绩:Y or N:"); while(1) { flushall(); scanf("%c",&select); if(select=='y'||select=='Y') { int a; printf("请输入想要查询的轮次:"); scanf("%d",&a); system("cls"); lookup(fp,num2,a); Sleep(2000); system("cls"); break; } else if(select=='n'||select=='N') { break; } else { printf("您的输入有误!\n"); } } system("cls"); printf("最终战绩如下:\n"); for(i=0;i<num1;i++) { printf("\t\t\t玩家%d: ",p[i].name); printf("赢局次数:%d 败局次数:%d\n",p[i].win,p[i].fail); } Sleep(5000); system("cls"); }
void set_score(PLAYER *p,float ave,int num,FILE *fp)计算本轮各玩家得分,判断玩家输赢。
void set_score(PLAYER *p,float ave,int num,FILE *fp) { int i,win,fail; float max=(float)fabs(p[0].number-ave); float min=max; char ch; 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;//保留与黄金点最小的差值 } printf("本轮比赛的得分:\n"); for(i=0;i<num;i++) { if(p[i].b==max) { p[i].score-=2; fail=i; } if(p[i].b==min) { p[i].score+=num; win=i; } } p[win].win+=1; p[fail].fail+=1; int max_score=p[0].score; int min_score=max_score; for(i=0;i<num;i++)//得出目前为止的最高分与最低分 { if(p[i].score>max_score) max_score=p[i].score; if(p[i].score<min_score) min_score=p[i].score; } for(i=0;i<num;i++) { printf("\t\t\t\t玩家%d: %d",p[i].name,p[i].score); if(max_score==min_score) printf(" 平手\n"); else if(p[i].score==max_score) printf(" 赢家^_^\n"); else if(p[i].score==min_score) printf(" 输家\n"); else printf(" 继续加油\n"); } while(1) { printf("是否继续Y or N : "); flushall(); scanf("%c",&ch); if(ch=='y'||ch=='Y') { system("cls"); break; } else if(ch=='n'||ch=='N') { exit(0); } else { printf("您的输入有误!\n"); } } }
void print_rule()用于显示游戏规则,可实现5秒后自动清屏的功能。
void print_rule() { printf(" a. N个同学(N通常大于10),每人写一个0~100之间的有理数(不包括0或100)。\n"); printf(" b. 裁判算出所有数字的平均值,然后乘以0.618(所谓黄金分割常数),得到G值。\n"); printf(" c. 提交的数字最靠近G(取绝对值)的同学得到N分,离G最远的同学得到-2分,\n 其他同学得0分。\n\n"); Sleep(5000); system("cls"); }
void save_file(FILE *fp,PLAYER *p,int n,int num)将各轮次比赛成绩存入文件。
void save_file(FILE *fp,PLAYER *p,int n,int num) { int i; fprintf(fp,"N%d",n+1); for(i=0;i<num;i++) { fprintf(fp," %d",p[i].score); } fprintf(fp,"\n"); } void lookup(FILE *fp,int num2,int a) { char ch; int num,i,n=1,flag=0; while(1) { ch=fgetc(fp); if(ch=='N') fscanf(fp,"%d",&num); if(num==a) { char c[10]={"\0"}; ch=fgetc(fp); while(ch!='\n') { ch=fgetc(fp); for(i=0;ch!=' ';i++) { c[i]=ch; ch=fgetc(fp); if(ch=='\n') break; } printf("\t\t\t\t玩家%d:",n); printf("%s分\n",c); n++; for(i=0;isdigit(c[i])||c[i]=='-';i++) c[i]='\0'; } flag=1; } if(num!=a) continue; if(flag==1) break; } }
编程收获:
这次结对编程跟我的队友学到了很多东西,也知道了结对编程的重要性,但人的思想不同,编程习惯也不同,如不重视代码规范的话,就会给队友带来很多苦恼,所以一定要和队友多沟通,做出你们都满意的程序!