快乐模拟掘金抽奖项目

这是我参与8月更文挑战的第5天,活动详情查看: 8月更文挑战git

前言

平常看看掘金首页的热门文章,今日份文章不少,仍是被它吸引。 云的世界:# 掘金的抽奖github

在线抽奖预览地址算法

缘由很简单,自从掘金上线签到抽奖系统,天天不断的小乐趣,就是抽奖!抽奖!抽奖!,中没中是一回事,过程是开心的 。数组

image.png

看完文章后本着cv的借鉴精神,去仰慕了一下源码, 原文章源码地址 源码是纯js实现抽奖的,想了想本身很久没输出文章了,趁着午间休息,给本身增长几个合理需求,去实现它,大佬的文章也是很详细介绍抽奖的实现了,我就不抄袭文章内容了,我就从实现抽奖后改造开始说明,若是你对原来实现有想了解的 请看大佬的文章云的世界:# 掘金的抽奖浏览器

image.png

新需求

  • 需求1:每次都是随机抽取
  • 需求2:能够为每一个中奖选项设置权重
  • 需求3:增长一个查看中奖项

需求1:每次都是随机抽取

简单分析,中奖有八项,原文是固定设置中奖序号4,那咱们就改为随机的便可。 获取随机一个0-7的随机数(Math.floor(Math.random() * 8)),而后去设置终点,也就是中奖的内容markdown

const randomNum = Math.floor(Math.random() * 8)
lottery.setPrize([randomNum])

复制代码

可是这样提示内容仍是原来写死的,须要根据咱们中奖的内容去提示对应内容,全局增长一个gift变量,用来获取当前中奖内容,这样作就能够每次根据中的内容去显示对应中奖提示app

// 奖池
 const arr = ['66矿石', '随机限量徽章', '掘金新款T恤', '乐高海洋巨轮', 'Switch', 'Yoyo抱枕', '掘金鼠标垫', 'Bug']
  gift = arr[randomNum] //中奖内容
  
 //中奖提示
  dialogEl.querySelector('.desc-gift').textContent = gift + '一个,请联系管理员兑换!!'
 
复制代码

需求2:能够为每一个中奖选项设置权重

那抽奖不可能都是给你同样的几率,确定须要后台设置一个中奖几率或者中奖权重,我这里实现权重的方式。 设置一个权重数组,而后随机一个小于权重和的数,看看这个数是属于哪一段的,返回对应的中奖序号便可。 我这里实现思路是,遍历看看这个随机数是属于哪一档的,遍历对比这个随机数是否小于i和i以前的和,若是小于i,大于i-1(i为0的话,大于0),返回idom

function getGift() {
  const weightRatio = [1, 1, 1, 1, 1, 1, 1, 1]
  const total = weightRatio.reduce((prev, curr) => {
    return prev + curr
  })
  let randomNum = Math.random() * total
  for (let i = 0; i < weightRatio.length; i++) {
    if (randomNum < weightRatio[i]) {
      return i
    } else {
      randomNum -= weightRatio[i]
    }
  }
}
复制代码

实现的算法有待优化...oop

这样的话就能够本身设置中奖权重了。(weightRatio这个数组),你本身能够去改代码中的这个数组来实现中奖比例post

看了评论,修改了一版,修改前中奖率都同样,能够当作抽中什么都是随机的。最新版在线demo修改了权重:const weightRatio = [3000, 10, 10, 1, 1, 10, 10, 1000]

  • bug的几率是24.7402%
  • 矿石的几率是74.2207%
  • 徽章、鼠标垫、T恤、抱枕的几率都是0.2474%,
  • 乐高和switch的几率是0.02474%,

非bug和矿石的几率1.03909%,按理说抽一百次能够中一次奖。(这只是demo模拟几率,不表明其它,图个乐子,吐槽归吐槽,但能白拿的福利还那么多要求就是咱们的不是了)

image.png

需求3:增长一个查看中奖项

这个需求分为两点,

  • 1.一个增长查看的按钮和对应事件
  • 2.一个增长查看的按钮和对应事件

第一点就简单的在对应位置增长一个div(<div class='main-look'>点击查看个人收获</div>)和设置对应样式,这里增长一个独有的类名,能够用来设置样式和等等增长点击事件

image.png

这里也要说两种实现吧,最快的方法就是用浏览器自带的alert()去显示中奖内容,

初版 (粗糙版)

设置一个放中奖物品的数组giftArr,而后每次中奖都push进这个数组中,最后查看的时候去遍历数组,展现里面对应内容,缺点很明显,奖品多了,本身都不知道中了几个

var lookGift = document.querySelector(".main-look");
lookGift.addEventListener('click', function () {
  if (!giftArr || giftArr.length === 0) {
    alert('暂时没有收获,先去抽奖吧!')
  } else {
    let str = ''
    giftArr.forEach((item, index) => {
      str += (index ? ',' : '') + item + '\n'
    })
    alert(str)
  }
})

复制代码

效果:

image.png

第二版 (优化版)

初版只是玩玩,那第二版一样来个数组来收集中奖,不过这个数组初始化giftArr=[0,0,0,0,0,0,0,0],当抽奖后对应的数字+1,就能统计中奖次数了

// 保存中奖内容
giftArr.splice(randomNum, 1, giftArr[randomNum] + 1)
//展现
var lookGift = document.querySelector(".main-look");
lookGift.addEventListener('click', function () {
  const flag = giftArr.some(item => {
    return item !== 0
  })
  if (flag) {
    const arr = ['66矿石', '随机限量徽章', '掘金新款T恤', '乐高海洋巨轮', 'Switch', 'Yoyo抱枕', '掘金鼠标垫', 'Bug']
    const total = giftArr.reduce((prev, curr) => {
      return prev + curr
    })
    let str = '恭喜总计中奖' + total + '个,其中:' + '\n'
    giftArr.forEach((item, index) => {
      if (item != 0) {
        str += arr[index] + '*' + item + '\n'
      }
    })
    alert(str)
  } else {
    alert('暂时没有收获,先去抽奖吧!')
  }
})
复制代码

image.png

项目在线预览地址和代码地址

能够在线体验一下无限矿石抽奖的乐趣,可是别找我要实物,仅供娱乐,hhh

在线预览地址

代码地址

image.png

本文小结

本身给本身提需求,这样作起来就无f可说了吧,比较有动力。以上就是对抽奖需求的一些简单改造,若是你想要别的效果或者需求,能够留言,看见合理的需求那就是安排。再次感谢云大佬的原文分享。 熟能生巧(Practice make perfect!)。

567570eb04c107f0a5d6ccf93447999.png

相关文章
相关标签/搜索