zoukankan      html  css  js  c++  java
  • 黄金点游戏

    ·题目介绍

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

          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个用户处获取数据,经过G点运算获取其差值,找出差值最大者和差值最小者对其进行分数赋予,在预设轮数后结束游戏并输出结果。思路清晰明了,大致分为以下几个步骤:

      1.从N个用户处获取数据

        鉴于这个程序实现的是单机形式,所以,除了真实玩家之外其他所有值都是由系统随机生成,运用到的方法是java类库里的Math.random(),这个方法可以随机生成一个双精度且介于0.0和1.0之间的小数,代码如下:

    /**
     * 生成0-100随机数
     * @author Eric
     */
    protected double[] rand() {
        double[] number = new double[11];
        for(int i=0;i<10;i++)
        {
            number[i]=Math.random()*100;
        }
        number[10] = 0;
        return number;
    }
          

      

      2.获取G值

        G值是此程序用于运算的关键数据,算法为所有用户提供数字的平均值与0.618的乘机,代码如下:

    /**
     * 获取G值
     * @author Eric
     */
        protected double  get_average(double[] number)
        {
            double sum = 0;
            double average;
            for(int i=0;i<11;i++)
            {
                sum+= number[i];
            }
            average = sum/11;
            average = average * 0.618;
            return average;
        }
    
    

      3.获取用户数据中距离G点最近的值和最远的值

        即获取赢家数据保存下标和输家数据保存下标,先调用之前的获取G点方法得到G的值,再把所有数据分别与之相减取绝对值得到差值数组,最后把差值数组内的每一个值分别与G值比较,保存下差距最大和差距最小者的下标,代码如下:

    /**
     * 判断并返回两个极端
     * @return
     */
        private int[] judge(double[] num) {
            double ave = get_average(num);
            int[] end = new int[2];
            double max;
            double min;
            double[] ju = new double[11]; 
            for(int i = 0;i<11;i++)
            {
                ju[i] = Math.abs(num[i] - ave);
            }
            max=ju[0];
            min=ju[0];
            end[0]=0;                     //保存距离近
            end[1]=0;               //保存距离远                    
                    for(int i=1;i<11;i++)
            {
                if(max<ju[i])
                {
                    end[1]=i;
                }
                if(min>ju[i])
                {
                    end[0] = i;
                }
            }
            return end;
        }    

      4.数据重复处理

        获取赢家成绩和输家成绩后,我们发现如果赢家不止一位,输家也不止一位,两个位置都有多个人占据,那么上面的代码就不能满足需求,所以要进行数据重复处理,获取完最大值和最小之后,反回去对原始距离数据进行对比,得出最大值和最小值的数据下标,代码如下:

    /**
     * 数字重复处理,获取离得近的且距离相同的人的下标
     * @author Eric
     */
        protected int[] getHighScore(double[] number)
        {
            int[] end;
            int[] highScore = new int[10];
            end = judge(number);
            int j =0;
            for(int i=0;i<number.length;i++)
            {
                if(number[i] == number[end[0]] )
                {
                    highScore[++j] = i;
                }
            }
            highScore[0] = j;                    //有效数量保存在数组首位
            return highScore;
            
        }
    /**
     * 数字重复处理,获取离得远的且距离相同的人的下标
     * @author Eric
     */
        protected int[] getLowScore(double[] number)
        {
            int[] end;
            int[] lowScore = new int[10];
            end = judge(number);
            int j =0;
            for(int i=0;i<number.length;i++)
            {
                if(number[i] == number[end[1]] )
                {
                    lowScore[++j] = i;
                }
            }
            lowScore[0] = j;                    //有效数量保存在数组首位
            return lowScore;
        }

     5.排序算法

        游戏运行完毕,用户的成绩各不相同,所以需要将其排序输出来使结果更加鲜明,由于这个程序全程使用数组作为存储结构存储数据,不像C中的结构体可以存储多种数据,所以一些经典的排序法,例如冒泡排序、快速排序、选择排序都不能适用,于是只好自己想算法。

        我们设定了一个与成绩数组相同长度的数组来保存下标,每轮筛选出数组中的最大值,保存其下标及其数值,下一轮在保证数字小于上一轮最大值的条件下继续筛选。但是,程序一出来马上出了BUG,就是相同的成绩只记录了一次,其他直接跳过,于是马上意识到没写相同分数处理,经过思考,添加相关代码,算法成功。代码如下

    /**
     * @author LZL
     * 排序算法,对最终分数进行排序,并决出最终的冠军
     * 设置一个分数数组长度的数组来保存下标,利用循环每次筛选出分数里最大的值,保存其相应下标,
     * 从小到大顺序
     */
        protected int[] sort(int[] goal)
        {
            int l = goal.length;
            int[] end= new int[l];
            int max;                //保存每次筛选的分数最大值
            int j;                    //保存下标的数组部分的对应下标
            int maxx;            //暂时保存上一轮筛选的最大值,方便下次剔除已筛选值
            
            for(int i=0;i<l;i++)           //初始化下标数组
            {
                end[i] = -1;
            }
            j = 0;
            max = goal[0];
            end[j] = 0; 
            
            for(int i = 1 ; i < l ; i ++)             //第一轮筛选最大值
            {
                if(max < goal[i])
                {
                    max = goal[i];
                    end[j] = i;
                }
            }
            maxx = max;                            //保存最大值
            j ++;  
            
            for(; j < l ;j ++)                           //循环筛选最大值
            {
                max = -100;
                for(int  i =0 ; i< l ; i++)
                {
                    if(goal[i] == maxx && !IsExist(i,end))                            //相同分数处理
                    {
                        max = goal[i];
                        end[j] = i;
                        break;
                    }
                    else if(goal[i<maxx)                                 //正常排序
                    {
                        if(max < goal[i])
                        {
                            max = goal[i];
                            end[j] = i;
                        }
                    }
                    
                }
                maxx = max;
            }
            return end;
        }
    
        
        /**
         * 判断一个数字是否存在于一个数组中
         * @author LZL
         */
        private boolean IsExist(int a,int[] b)                      {
            for(int i = 0;i<b.length;i++)
            {
                if(a == b[i])
                    return true;
            }
            return false;
        }

      6.界面设计

        这个项目使用的界面编辑器是SWT,拖控件什么的就不一一赘述,不过一些控件的属性实在有趣,如下:

        SWT.CENTER                                                     多用于文本设置,文本居中,可见于Text、label、clabel

        SWT.WRAP                                                        文本框属性,可换行

        SWT.BORDER                                                    令控件显示边框

        SWT.READ_ONLY                                               文本只读

    FILLLAYOUT:                                                                 布局类型,占满空间

        SWT.HORIZONTAL                                              横向布局

        SWT.VERTICAL                                                   纵向布局

    窗口实现如下:

      7.Java弹窗

      (1)JOptionPane.showMessageDialog(null,"message")                           //提示信息框

      (2)JOptionPane.showInputDialog("message");                                   //输入框

      (3)输入框的报错处理

        事实证明,如果输入弹窗获取到的数据为空,系统会报错,为保证系统流畅运行,报错处理十分重要。这里采用循环的方式利用两个提示信息不同的输入框进行数据采集,直到获取到合格的信息才会循环结束,代码如下

    maxxx = JOptionPane.showInputDialog("请输入您想进行的局数"); 
            while(maxxx.equals(""))
            {
                maxxx = JOptionPane.showInputDialog("您还没有输入您想进行的轮数,请重新输入"); 
            }
            maxx = Integer.parseInt(maxxx);

    ·运行展示

      1.游戏规则提示

      2.用户操作指南提示

      3.输入预设游戏进行轮数

      4.游戏初始界面

      5.运行游戏界面

      

      6.输入报错

      7.游戏结束成绩展示

     ·结队编程  

        刚看到这个要求时,我是拒绝的,因为这个东西我完全可以独立完成,何必再找个人去浪费大家时间呢,但老师排好了我就按着做了,结果收到了意想不到的结果。

        跟我结对的同学叫刘泽良,是个活泼开朗的男孩子,一手LOL6的不行,编程方面也就比我弱了那么一丝丝,我刚看到的时候心说,呀,大腿,后来大腿哥也给我承诺说能者多劳,看来这次能躺了。终于,我们要开工了,大腿哥坐在我旁边,开始很不适应,因为我习惯自己独立编程,但大腿哥的确给我指出了不少问题,纠正了不少错误,时常还会讲个笑话,大家笑得不亦乐乎,于是,编程氛围活跃了起来。再后来,我们完成了这个东西,由于是第一次做界面,所以真是被自己丑哭了,但是,这不是问题,我们初步完成了任务,后期还会有更新。

        总之,结对编程很happy,一改往日枯燥乏味的编程体验。下面上图

  • 相关阅读:
    Django(一)
    web 框架
    图片
    day16
    day 15
    day14 HTML CSS
    day12
    day11
    python IO多路复用,初识多线程
    python socket
  • 原文地址:https://www.cnblogs.com/weit/p/5347924.html
Copyright © 2011-2022 走看看