【项目实战】从抽奖算法感受算法奥妙

来源:互联网 发布:java表格代码怎么写 编辑:程序博客网 时间:2024/05/17 09:27

【前言】

           最近因为公司年会需要,组长让我们花几天时间开发了个抽奖系统。虽然就是cs的一个小例子,不过自己设计算法的过程还是蛮有意思的。下面先给大家看看,最后成品的样子。主要实现的就是excel表的导入导出和抽奖功能, 这篇就讲一下抽奖功能的实现。目前实现的效果是点击开始时,全屏隐去,只剩下名字在滚动显示,需要停止时在datagridview中显示出获奖人信息。

【设计思路



首先从excel导入名单到dataset,用timer 控制label(lblgetname)每毫秒显示

一个dataset中的名字,循环显示。 然后写一个getname方法, 让timer启动一下,

系统延迟10毫秒,然后停一下,得到一个名字。 再写一个getnewName(string[]

nameSet,string tmpName,int times)方法用来查重,将抽到的名字传进去和

抽到的名字集合nameset做比较,有重复的,重新抽取。 SelectPerson就是调用get

name和getNewName获得抽奖人,然后把已经抽到的人从dataSet中删除,防止多次抽

奖重复抽取一个人。 这是这一版的实现思路,最终成型的和这个又有差别。



正文

       

      最初的想法是通过随机数来实现抽奖, 但是到多次抽奖间不重复的时候卡住了, 不知道怎么让随机数产生时刨除确定的几个数。

        最后是通过label和timer实现的选人,每选一次就从dataSet中删除一部分人。代码如下:

       

  private void btnBegin_Click(object sender, EventArgs e)        {            label1.Visible = false;             label2.Visible = false;            label3.Visible = false;            txtNumber.Visible = false;            btnLook.Visible = false;            btnBegin.Visible = false;            btnPreserve.Visible = false;            btnResetting.Visible = false;            dgv.Visible = false;            lblgetName.Visible = true;            dgv.Rows.Clear();            if (user != "")            {                if (txtNumber.Text.Trim() != "")                {                    lblgetName.Text = "吴迪";                    if (ds.Tables[0].Rows.Count > int.Parse(txtNumber.Text) * 1.3)                    {                        timer1.Start();                                              btnBegin.Enabled = false;                    }                    else                    {                        MessageBox.Show("剩余人数已不足");                        lblgetName.Visible = false;                        label1.Visible = true;                        label2.Visible = true;                        label3.Visible = true;                        txtNumber.Visible = true;                        btnLook.Visible = true;                        btnBegin.Visible = true;                        btnPreserve.Visible = true;                        btnResetting.Visible = true;                        dgv.Visible = true;                        return;                    }                }                else                {                    MessageBox.Show("请输入要选出的人数");                }            }            else            {                MessageBox.Show("请导入人员信息!");            }        }        private void lblgetName_Click(object sender, EventArgs e)        {            int number = int.Parse(txtNumber.Text.Trim());            string[] nameSet = selectPerson(number);            try            {                for (int rows = 0; rows <= ds.Tables[0].Rows.Count - 1; rows++)                {                    for (int times = 0; times < number; times++)                    {                        if (ds.Tables[0].Rows[rows][1].ToString().Trim() == nameSet[times].ToString().Trim())                        {                            ds.Tables[0].Rows[rows][2] = "是";                            ds.AcceptChanges();                        }                    }                }            }            catch (Exception)            {                MessageBox.Show("剩余人数不足", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);            }            List<LuckyPerson> luckyPeople = new List<LuckyPerson>();            int reCount = ds.Tables[0].Rows.Count - 1;            for (int rows = 0; rows <= reCount; rows++)            {                if (ds.Tables[0].Rows[rows][2].ToString().Trim() == "是")                {                    LuckyPerson lucky = new LuckyPerson();                    lucky.Name = ds.Tables[0].Rows[rows][1].ToString().Trim();                    //2表示电话所在列                    lucky.Tel = ds.Tables[0].Rows[rows][2].ToString().Trim();                    luckyPeople.Add(lucky);                }            }            dgv.Rows.Add(luckyPeople.Count);            for (int i = 0; i < luckyPeople.Count; i++)            {                dgv.Rows[i].Cells[0].Value = luckyPeople[i].Name;                dgv.Rows[i].Cells[1].Value = luckyPeople[i].Tel;            }            deletLuky(reCount);            btnBegin.Enabled = true;                        label1.Visible = true;            label2.Visible = true;            label3.Visible = true;            txtNumber.Visible = true;            btnLook.Visible = true;            btnBegin.Visible = true;            btnPreserve.Visible = true;            btnResetting.Visible = true;            dgv.Visible = true;            lblgetName.Visible = false;        }

  #region 抽奖功能-宋荣凯-2017年3月14日        /// <summary>        ///         //抽出幸运观众selectPerson-宋荣凯-2017年3月14日        /// </summary>        /// <param name="times">抽取数量</param>        /// <returns>获奖人的集合</returns>        public String[] selectPerson(int times)        {            String[] nameSet = new String[times];            string nameTmp;            //循环将抽中人员放入集合中            for (int i = 0; i < times; i++)            {                nameTmp = getName();                if (i == 0)                {                    nameSet[i] = nameTmp;                }                else                {                    //检查是否本次内是否有重复人员                    nameSet[i] = getNewName(nameSet, nameTmp, i);                }            }            return nameSet;        }        /// <summary>        /// 若重复重新抽取--getNewName--宋荣凯-2017年3月14日        /// </summary>        /// <param name="nameSet">本次已抽中人</param>        /// <param name="nameTmp">当前抽中人</param>        /// <param name="times">已抽中人数</param>        /// 通过循环递归,将        ///         /// <returns>不重复的获奖人</returns>        public String getNewName(String[] nameSet, String nameTmp, int times)        {            int n = 0;            string finalName = "";            while (n < times)            {                if (nameSet[n].ToString().Trim() == nameTmp.ToString().Trim())                {                    nameTmp = getName();                    finalName = getNewName(nameSet, nameTmp, times);                }                else                {                    finalName = nameTmp;                }                n++;            }            return finalName;        }        /// <summary>        /// 抽取获奖人-getName-宋荣凯-2017年3月14日        /// </summary>        /// 通过timer的开关,获取label中的名字        /// <returns>获奖人姓名</returns>        public String getName()        {            string name;            timer1.Start();            Thread.Sleep(100);            System.Windows.Forms.Application.DoEvents();            timer1.Stop();            name = this.lblgetName.Text;            return name;        }        #endregion
       //从dataSet中删去已抽中的人        public void deletLuky(int reCount)        {            for (int rows = 0; rows <= reCount; rows++)            {                if (ds.Tables[0].Rows[rows][2].ToString().Trim() == "是")                {                    ds.Tables[0].Rows[rows].Delete();                    ds.AcceptChanges();                    reCount--;                    rows--;                }            }        }

 private void timer1_Tick(object sender, EventArgs e)        {            if (i > ds.Tables[0].Rows.Count - 1)            {                i = 0;            }            if (ds.Tables[0].Rows[i][1].ToString() != null)            {                this.lblgetName.Text = ds.Tables[0].Rows[i][1].ToString();            }            else            {                i = i + 1;                this.lblgetName.Text = ds.Tables[0].Rows[i][1].ToString();            }            i++;                  }

【总结】

      其实最后成型的这个抽奖算法挺简单也用啥思想, 但是设计过程中思考的时候去重借鉴过选择排序,借鉴过散列表去重等等方法。第一次感觉算法这么有意思。 还是自己实际用到了才能感觉到好处。 感觉非常不错。

1 0
原创粉丝点击