【项目实战】从抽奖算法感受算法奥妙
来源:互联网 发布: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++; }
【总结】
其实最后成型的这个抽奖算法挺简单也用啥思想, 但是设计过程中思考的时候去重借鉴过选择排序,借鉴过散列表去重等等方法。第一次感觉算法这么有意思。 还是自己实际用到了才能感觉到好处。 感觉非常不错。
- 【项目实战】从抽奖算法感受算法奥妙
- 抽奖 算法
- 抽奖算法
- 抽奖算法
- 抽奖-算法
- 抽奖算法
- php 关于抽奖算法
- php 抽奖概率算法
- 抽奖简单算法
- 一个抽奖算法
- thinkphp 抽奖算法
- Java 抽奖算法
- 抽奖算法总结
- 大转盘抽奖算法
- 红包抽奖算法
- PHP抽奖算法
- Java 抽奖算法
- 抽奖算法分析
- RatingBar流泪、有脚、显示不全问题
- (C++基础)浅谈继承与派生
- MYSQL(5)触发器
- [IO系统]16 IO调度器-NOOP
- Java读取文件byte转化String问题
- 【项目实战】从抽奖算法感受算法奥妙
- codeforces contest 785 a题
- 指针极简教程
- OA的项目
- xpath提取网页内容
- 蓝桥杯 小朋友排队
- 登陆验证
- 数组中重复的数字
- 树的三种遍历算法