快樂模擬掘金抽獎項目

這是我參與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

相關文章
相關標籤/搜索