楼主: 北意大利

[有事请教] 如何实现随机抽到的数字不重复(7月31日追加问题)

[复制链接]
梦石
0
星屑
1343
在线时间
153 小时
注册时间
2020-4-26
回帖
146
发表于 2020-8-1 02:13:13 | 显示全部楼层
本帖最后由 moonyoulove 于 2020-8-1 02:38 编辑

先初始化签筒,把签筒保存全局变量或rm的变量里,
再来决定要抽取几道题目,最大值应为6*6*6(依照配置)
参数传入签筒(types),重复执行randomCode,每次都能得到随机不重复的题目编号了
[pre lang="javascript"]//初始化题库的签筒
      function initQuestion() {
        var typeNum = 6; //类型数量
        var hardNum = 6; //难度数量
        var questNum = 6; //序号数量
        // 建立一个多重嵌套的数组(多维阵列),如下
        //类型1─难度1─序号1
        //   │     └序号2
        //   │     └序号3
        //   └难度2─序号1
        //        └序号2
        var types = [];
        for (var i = 0; i < typeNum; i++) {
          var hards = [];
          for (var j = 0; j < hardNum; j++) {
            var quests = [];
            for (var k = 0; k < questNum; k++) {
              //存放一个对象,其里面的num代表实际序号
              quests.push({
                        num: k + 1
                      });
            }
            //除了num,还得存放该难度下的序号数组
            hards.push({
              num: j + 1,
              quests: quests,
            });
          }
          //同理,只是改放难度数组
          types.push({
            num: i + 1,
            hards: hards,
          });
        }
        //全部数组建好后,返回types
        return types;
      }
      
      //抽签,原理是对建立好的签筒进行抽完不放回的动作
      function randomCode(types) {
                //先抽类型,i、j、k会依序存放抽到的是第几支签
        var i = rand(types.length); //表示随机types数组的到第一位到最后一位
        var type = types; // type实际长这样{num:第几个类型, hards:类型里的难度数组}
        var hards = type.hards; //取得难度数组
        var j = rand(hards.length);//第二阶段,抽难度
        var hard = hards[j];
        var quests = hard.quests;
        var k = rand(quests.length);//第三阶段,抽题目序号
        var quest = quests[k];
        //已经得到一组类型、难度和序号
        //实际数值是放在num里
        //code可以依照需求改写,下面是用「-」连成字符串
        var code = type.num + "-" + hard.num + "-" + quest.num;
        //等三支签(类型、难度、序号)抽完,再进行丢掉的动作
        quests[k] = quests[quests.length - 1]; //把最后一个元素覆盖到抽到的元素的位置
        quests.pop();//舍弃掉最后的元素
        //抽出来的序号签已经丢掉了,接下来换难度的签
        //于是这里检查这个难度底下是不是还有题目,没有的话把这个难度从数组删掉
        if (quests.length == 0) {
                  //跟上面同样原理
          hards[j] = hards[hards.length - 1];
          hards.pop();
        }
        //再来换检查是否要从整个数组删除已经不需要的种类
        if (hards.length == 0) {
          types = types[types.length - 1];
          types.pop();
        }
        //最后返回处理好的编码,此处能做变通,比如返回数组,或不返回,直接赋值给rm的变量
        return code;
        
        //内部的函数,用来方便地得到一个从0到i,但不包括i的随机整数
        function rand(i) {
          return Math.floor(Math.random() * i);
        }
      }[/pre]

点评

注解好详细!!辛苦了!!这里学到了很多、问题也解决了><实在是非常感谢!!  发表于 2020-8-1 14:59
我发现这种方法适合在题目少,或者抽取的数目接近总数的时候,如果是100万道题抽10题,那签可以抽完后放回,因为再抽到的机率低,再次重抽即可  发表于 2020-8-1 02:49

评分

参与人数 1赞 +1 收起 理由
北意大利 + 1 精品文章

查看全部评分

回复 2 0

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部