软件工程-构建之法 黄金点小游戏

一、背景

黄金点游戏是一个数字小游戏,其游戏规则是:

Coding.net地址:https://coding.net/u/2011040802012/p/soft_structure/git

      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>
#include<math.h>
using namespace std;

int main()
{
    int game_num;
    map<string,double>mp;
    int i,n;
    double num,sum,ave,G;
    int 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 =(double)fabs(G-(double)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;
}

如果文中存在错误,请帮忙指出,大家可以一起讨论,共同提高。

 

posted @ 2016-04-06 21:17  saucxs  阅读(483)  评论(3编辑  收藏  举报