标签:
一、背景
黄金点游戏是一个数字小游戏,其游戏规则是:
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轮以上,并能够保留各轮比赛结果。
二、分析
这个小游戏,你肯定会想, 如果大家随机报数的话,
第一轮开始:可能是真正的随机,0-100 的平均数是50, 50 * 0.618 = 31. 那我就来个 31。
第二轮开始:当大家渐渐明白了游戏的BUG时候,但 他们肯定也想到选31附近,如果大家大家都选 31 附近的数, 那我得选 31*0.618 = 19;
第三轮以及之后的。。。。。。
但是这些人肯定也想到了这一点, 那我要选 19 * 0.618 = 12… 然后 12 * 0.618 = 8
。。。。。。。。
最后干脆选越小的数,例如0.00000000001,这是个有理数。
0.00000000001是正确答案么? 这取决于参与游戏的所有成员。
当这个游戏的人员都是程序员或者都是智商比较高的人员,游戏的确会出现我们之前预测的一样,G点的值在不断的下降。
但是如果是一群知识为了开心的玩耍的小伙伴呢,那么这个结果就会出现各种情况,结果不具有预见性,但是你仔细观察会发现,G值的大小不是由少数人决定的,而是由大多数人决定的。最恐怖是反向逆行的游戏者最后都“守约” 提交了大数,最终你的分数是负数,再来一轮,你也不是傻瓜,你也会使自己的数足够的小,走出自己是-2分的局面。
黄金比例0.618,在生活中,学习都可以经常见到,黄金比例分割是指把一条线段分割为两部分,使其中一部分与全长之比等于另一部分与这部分之比。其比值是一个无理数,取其前三位数字的近似值是0.618。所谓黄金分割,指的是把长为L的线段分为两部分,使其中一部分对于全部之比,等于另一部分对于该部分之比。而计算黄金分割最简单的方法,是计算斐波那契数列1,1,2,3,5,8,13,21,...后二数之比2/3,3/5,4/8,8/13,13/21,...近似值的。
三、易错点
之前自己认为是整数,当自己输入时有理数时候程序自动停止。当程序中出现中国人的名字的时候时候可以存储,当map中没有清空。。。。。。。。。
易出现的错误(1):是有理数,不是整数
原因及解决办法:改变map<string,int>mp;--->map<string,double>mp;这个就是map非常灵活的地方,自己可以自己定义数据类型。
易出现的错误(2):当游戏人数不变时,人员发生改变时,大家还是可以继续玩
原因及解决办法:每一次的求和,平均值,G值清空。
易出现的错误(3):当人员名字改变时,每一轮的游戏开始都是新的开始
解决原因及办法:自己的map每一次都没有清空,使用的map中的函数clear(),语句是使用mp.clear()清空。
当第一轮中的人员和第二轮中的人员不一样时,map中存了所欲哦
易错点(4):每一轮的输入可不可以不按照一定顺序的输入,但是map最终是以map字典序的输出,
原因及解决办法:map还有一个优点是自动对第一个字段进行排序。所以在游戏中可以可以当有的人还没有想好交上什么数据,可以跳过,不会影响到结果的。
大家选取的数据越来越小的时候,会出现G值的确会逐渐减小。
四、结对编程的照片(Ps:认真帅气漂亮)
五、总结和评价
这一次结对编程,可以说不是自己的第一次结对编程,在ACM中经常就是一个编程,一个人复审,另外一个人提供思路,然后交叉轮流编程,轮流代码审核,这样编程效率高,还不容易出错,而且可以通过结对编程,熟悉了解搭档的编程风格和思路模式,也是对自己的不足的地方一种提高。是一种相互学习的方式,只会让结对编程的两人的编程水平共同提高,但是存在这样的情况,你压根不想和他一起编程,只会让彼此相互埋汰,然后工作效率低。
对队友的评价:在明白题意后,自己的思路是使用STL中的Map,时间复杂度logn,我先把map建立与数据的输入进行简单的测试,然后再把写到多轮游戏的开始完成。但是她给我提出一个如果要显示多轮之后的成绩怎么显示,她说,他可以定义另外一个map的变量,用来存每一次的分数,在累加,就可以实现。
六、源代码(使用的软件Code Block,在GCC编译器编译通过)
#include <iostream> #include<cstdio> #include<cstdlib> #include<map> using namespace std; int main() { int game_num; map<string,double>mp; int i,n; double num,sum,ave; int G,temp=0; string name; printf("请输入游戏的人数:"); scanf("%d",&n); printf("\n"); printf("请输入此次游戏进行的轮数:"); scanf("%d",&game_num); printf("\n"); while(game_num--) { ++temp; mp.clear(); //清空map中的数据 sum=0;ave=0;G=0; printf("第%d轮开始:\n",temp); printf("请输入每人的姓名和有理数(空格隔开):\n"); for(i=0;i<n;i++) { cin>>name>>num; if(num>0.0&&num<100.0) { mp[name]=num; //建立map的关系 sum=sum+num; } else { printf("请输入(0-100)的有理数\n"); i--; } } map<string,double>::iterator iter,result_high,result_low; printf("总和为:%.4lf\n",sum); ave=sum/n; printf("平均值:%.4lf\n",ave); G=ave*0.618; printf("G点值:%.4lf\n",G); for(iter=mp.begin();iter!=mp.end();iter++) { iter->second =(int)abs(G-(int)iter->second); //iter存的是差值 } for(iter=mp.begin(),result_high=mp.begin(),result_low=mp.begin();iter!=mp.end();iter++) { if(iter->second<result_high->second) result_high=iter; if(iter->second>result_low->second) result_low=iter; } cout<<endl; cout<<"姓名"<<"\t"<<"差值"<<endl; cout<<result_high->first<<"\t"<<result_high->second<<"\t"<<"得到"<<n<<"分"<<endl; cout<<result_low->first<<"\t"<<result_low->second<<"\t"<<"得到-2分"<<endl; cout<<endl; for(iter=mp.begin();iter!=mp.end();iter++) { iter->second =0; } for(iter=mp.begin();iter!=mp.end();iter++) { if(iter==result_high) iter->second+=n; if(iter==result_low) iter->second+=-2; } cout<<"第"<<temp<<"轮结果:"<<endl; cout<<"姓名"<<"\t"<<"分数"<<endl; for(iter=mp.begin();iter!=mp.end();iter++) cout<<iter->first<<"\t"<<iter->second<<endl; cout<<endl; } return 0; }
如果文中存在错误,请帮忙指出,大家可以一起讨论,共同提高。
数据
标签:
原文地址:http://www.cnblogs.com/chengxs/p/5361170.html