当前位置:编程学习 > VB >>

请教一个算法

某公司有六个字公司,公司年会需要编写一个抽奖软件。因为每个子公司的人数不一样,故需要先用随机函数随机公司名,抽到了公司名再随机公司员工名。
用VB+Access编写
先使用MSHflexGrid控件读取Access里公司和员工名
然后在MSHflexGrid控件里读取员工名
每次随机到的员工名,将在MSHGrid控件里使用MSHFlexGrid1.TextMatrix(行,列)=“”清空,避免出现重复抽取
列代表公司名,行代表员工姓名
上面的步骤已经完成。
问题是:
      1、当随机到最后,如果随机数是已经抽过的行和列(即此时行和列)为空,将会自动在同一公司的情况下再随机员工名
      2、特别是如果人数少的公司已经抽取完毕,如何将那个公司清除,在余下的公司里再随机循环。
      3、依次类推
请教大家关于上面问题处理的算法,谢谢 --------------------编程问答-------------------- 已经抽取到的人员清空,没有人员的公司清空 --------------------编程问答--------------------
引用 1 楼 jhone99 的回复:
已经抽取到的人员清空,没有人员的公司清空


lz把问题搞复杂了 --------------------编程问答-------------------- 如下算法解决问题1

[0]剩余奖项数=总奖项数
[1]获取随机数
[2]先使用MSHflexGrid控件读取Access里公司和员工名 
[3]获取随机数
[4]然后在MSHflexGrid控件里读取员工名 
[5]若该员工名=“#”,转[1] '解决问题1
[6]每次随机到的员工名,将在MSHGrid控件里使用MSHFlexGrid1.TextMatrix(行,列)=“#”清空,避免出现重复抽取
[7]剩余奖项数=剩余奖项数-1
[8]若剩余奖项数>0 转[1]
[9]结束


对于问题2,我理解lz的意思是该公司的人都中奖了,那么在[5]时会转[1],不会有问题 --------------------编程问答-------------------- 假设20个人吧,举个简单的例子给楼主参考一下,把数组元素来当成员工,假设从这20个人中抽5次
Dim I(19) as long
Dim L as long
Dim Luck as long

...数组附值省略...

For L = 0 to 4                '5次循环,代表抽5次奖
   Luck = Int(Rnd * (19-L))    '产生一个小于20-L的随机自然数
   Debug.print "第" & L+1 & "个中奖者是:" & I(Luck)
   I(Luck)=I(19-L)       '把已经中奖的人排除
Next

5次循环从数组中随机挑出了5个不重复的数组元素, 楼主看明白之后再改成你要的程序吧
--------------------编程问答-------------------- lz的设计模式我不赞同.
我觉得应放若干文本框,动态的随机的取得数据,用sql语句+timer+Rnd
需要注意的是sql语句要加上 order by newid(),每次检索的记录顺序就不一样了
抽到一组人员,就更新记录标志,这样就不会再出现抽到已获奖的人员
这会csdn忙,不能帖图.... --------------------编程问答-------------------- 唉,老虎最爱回答这类问题

再次偷偷思念一哈俺家老大 --------------------编程问答--------------------
引用楼主 welldoneyc 的回复:
某公司有六个子公司,公司年会需要编写一个抽奖软件。
因为每个子公司的人数不一样,故需要先用随机函数随机公司名,抽到了公司名再随机公司员工名。


我觉得这样的话,其实不够随机,小子公司的人员被抽到的概率会更大,这对大子公司的人员不公平。

如果要真正公平,不应该区分公司。而应该把所有人员形成一个完整的列表(可以在数据库里生成一个临时表,加一个字段标记是否获奖),每次从未获奖的所有人员中随机抽取,抽取到的人员的获奖字段标记为已获奖,这样自动从下次随机摇码中排除。就不会出现你最后提到的问题。 --------------------编程问答-------------------- 具体到实现,你的显示部分仍然不动(抽到的人清空),只把摇奖的部分替换成7楼的算法就可以了。 --------------------编程问答--------------------
引用 7 楼 slowgrace 的回复:
我觉得这样的话,其实不够随机,小子公司的人员被抽到的概率会更大,这对大子公司的人员不公平。

如果要真正公平,不应该区分公司。而应该把所有人员形成一个完整的列表(可以在数据库里生成一个临时表,加一个字段标记是否获奖),每次从未获奖的所有人员中随机抽取,抽取到的人员的获奖字段标记为已获奖,这样自动从下次随机摇码中排除。就不会出现你最后提到的问题。


这样公平

这样也简化了

设一个集合,把所有人员加入集合,抽到奖的从集合清出,很简单就可以做出来 --------------------编程问答-------------------- 小娟娟,赞同我就比个大拇哥撒
--------------------编程问答--------------------
引用 10 楼 slowgrace 的回复:
小娟娟,赞同我就比个大拇哥撒


--------------------编程问答--------------------
引用 11 楼 jhone99 的回复:
惊见小娟的兰花小指 --------------------编程问答--------------------
引用 12 楼 slowgrace 的回复:
引用 11 楼 jhone99 的回复:

惊见小娟的兰花小指


--------------------编程问答-------------------- 给lz一个产生不重复随机数的算法

Private Sub Command1_Click()
    Dim cltTemp As New Collection
    Dim i As Integer
    Dim intOut As Integer
    
    For i = 1 To 30
        cltTemp.Add i      '所有人员加入集合
    Next i
    
    Randomize
    
    While cltTemp.Count > 0
        intOut = Int(Rnd * cltTemp.Count + 1)   '未中奖的随机
        Debug.Print cltTemp.Item(intOut)   '中奖的
        cltTemp.Remove (intOut)       '中奖的排出
    Wend
            
End Sub
--------------------编程问答-------------------- 友情Up ................
--------------------编程问答--------------------
既然是随机抽取,没有必要搞成两层。

实际上,把所有员工都放到一个 ListBox 中就可以了。List 文本可以包含子公司名称和员工姓名。

用 List1.ListCount * Rnd 取得一个表项,然后用 List1.RemoveItem 方法删除它。

--------------------编程问答--------------------
引用 16 楼 of123 的回复:
既然是随机抽取,没有必要搞成两层。

实际上,把所有员工都放到一个 ListBox 中就可以了。List 文本可以包含子公司名称和员工姓名。

用 List1.ListCount * Rnd 取得一个表项,然后用 List1.RemoveItem 方法删除它。


还是我的办法好。控件就是用来表现数据的,不要和数据本身鸟在一起。 --------------------编程问答-------------------- 1.将员工的信息按你的“列代表公司名,行代表员工姓名”的方式显示在MSHflexGrid控件中
2.用SQL语句一次性随机获取全部中奖人员记录集
3.循环记录集,在MSHflexGrid中查找对应的信息清除之...

实际上一次性用SQL语句随机获取全部中奖人员后,找个个性的显示方式是不是更好?

--------------------编程问答--------------------
补充:VB ,  基础类
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,