整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          JavaScript4種數組隨機選取實戰源碼

          JavaScript4種數組隨機選取實戰源碼

          我們的實際開發工作中,經常都會使用到數組隨機選取的功能需求,比如彩票隨機一注,隨機五注,機動車號牌隨機選一個等等。

          接下來的內容,來給大家分享一下,我們在開發過程中,常用到的4種數組隨機選取實現方案,這些實現方案都是在實戰中應用的,非常值得大家學習和收藏,我們一起來看看都有哪些方法吧!

          1 使用Math.random()

          這種方式是使用Array.sort()和Math.random()結合的方法,Math.random()返回的是一個0-1之間(不包括1)的偽隨機數,注意這不是真正的隨機數。

          var letter=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
          function shuffle1(arr) {
              return arr.sort(()=> 0.5 - Math.random())
          }
          console.time("shuffle1");
          letter=shuffle1(letter);
          console.timeEnd("shuffle1");
          console.log(letter);

          這種方式并不是真正的隨機,來看下面的例子。對這個10個字母數組排序1000次,假設這個排序是隨機的話,字母a在排序后的數組中每個位置出現的位置應該是1000/10=100,或者說接近100次??聪旅娴臏y試代碼:

          let n=1000;
          let count=(new Array(10)).fill(0);
          for (let i=0; i < n; i++) {
              let letter=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
              letter.sort(()=> Math.random() - 0.5);
              count[letter.indexOf('a')]++
          }
          console.log(count); 

          結果如下:

          可以看出元素a的位置在0到9出現的次數并不是接近100的。

          原因有兩點:

          1. Math.random()方法產生的偽隨機數并不是在0到1之間均勻分布,不能提供像密碼一樣安全的隨機數字。
          2. Array.prototype.sort(compareFunction)方法中的compareFunction(a, b)回調必須總是對相同的輸入返回相同的比較結果,否則排序的結果將是不確定的。

          這里sort(()=> 0.5 - Math.random())沒有輸入,跟談不上返回相同的結果,所以這個方法返回的結果不是真正的數組中的隨機元素。

          2 隨機值排序

          既然(a, b)=> Math.random() - 0.5 的問題是不能保證針對同一組 a、b 每次返回的值相同,那么我們不妨將數組元素改造一下,比如將元素'a'改造為{ value: 'a', range: Math.random() },數組變成[{ value: 'a', range: 0.10497314648454847 }, { value: 'b', range: 0.6497386423992171 }, ...],比較的時候用這個range值進行比較,這樣就滿足了Array.sort()的比較條件。

          代碼如下:

          let letter=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
          function shuffle2(arr) {
              let new_arr=arr.map(i=> ({value: i, range: Math.random()}));
              new_arr.sort((a, b)=> a.r - b.r);
              arr.splice(0, arr.length, ...new_arr.map(i=> i.value));
          }
          console.time("shuffle2");
          letter=shuffle2(letter);
          console.timeEnd("shuffle2");
          console.log(shuffle2); 

          輸出結果如下:

          我們再使用上面的方式測試一下,看看元素a元素是不是隨機分布的。

          let n=1000, count=(new Array(10)).fill(0);
          for (let i=0; i < n; i++) {
              let letter=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
              letter=shuffle2(letter)
              count[letter.indexOf('a')]++
          }
          console.log(count); 

          結果如下:

          從這里可以看出,元素a在位置0到9出現的次數是接近100的,也就是說元素a是隨機分布的,其他的元素也是,這時再從這個新數組中截取前幾個元素就是想要的數組了。

          3 洗牌算法

          上面的sort算法,雖然滿足了隨機性的需求,但是性能上并不是很好,很明顯為了達到隨機目的把簡單數組變成了對象數組,最后又從排序后的數組中獲取這個隨機數組,明顯走了一些彎路。

          洗牌算法可以解決隨機性問題,洗牌算法的步驟如下:

          1. 數組arr,有n個元素,存放從1到n的數值;
          2. 生成一個從0到n-1的隨機數x;
          3. 輸出arr下標為x的元素,即第一個隨機數;
          4. 將arr的尾元素和下標為x的元素值互換;
          5. 同步驟2,生成一個從0到n-2的隨機數x;
          6. 輸出arr下標為x的數組,第二個隨機數;
          7. 將arr倒數第二個元素和下標為x的元素互換;
          8. 重復執行直至輸出m個數為止;

          洗牌算法是真的隨機的嗎,換言之洗牌算法真的可以隨機得到n個元素中m個嗎?下面拿一個只有5個元素的數組來說明。

          數組有5個元素,如下圖。

          從5個元素隨機抽出一個元素和最后一個換位,假設抽到3,概率是1/5,如下圖。注意其他任意4個元素未被抽到的概率是4/5。最終3出現在最后一位的概率是1/5。

          將抽到的3和最后一位的5互換位置,最后一位3就確定了,如下圖:

          再從前面不確定的4個元素隨機抽一個,這里注意要先考慮這4個元素在第一次未被抽到的概率是4/5,再考慮本次抽到的概率是1/4,然后乘一下得到1/5。注意其他任意3個未被抽到的概率是3/4。5出現在倒數第二位的概率是4/5*1/4=1/5如下圖:

          現在最后2個元素確定了,從剩下的3個元素中任意抽取一個,概率是1/3,身下任意2個未被抽到的概率是2/3,但是要考慮上一次未被抽到的概率是3/4,以及上上一次未被抽到的概率是4/5,于是最終1出現在倒數第三位的概率是1/3*3/4*4/5=1/5。

          現在倒數3個元素已經確定,剩下的2個元素中任意取一個,概率是1/2,但是要考慮上一次未被抽到的概率是2/3,上上一次未被抽到的概率是3/4,上上上一次未被抽到的概率是4/5,最終4出現在倒數第4位的概率是1/2*2/3*3/4*4/5=1/5。

          最后還剩下一個2,它出現在倒數第5位的概率肯定也是1/5。不嫌啰嗦的話可以繼續看下去。

          現在倒數4個元素已經確定,剩下1個元素中任意取一個,概率是1,但要考慮上一次未被抽中的概率是1/2,上上一次未被抽中的概率是2/3,上上上一次未被抽中的概率是3/4,上上上上一次未被抽中的概率是4/5,于是2出現在倒數5位置的概率是1*1/2*2/3*3/4*4/5=1/5。

          有了算法,下面給出洗牌算法的代碼:

          let letter=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
          function shuffle3(arr) {
              let i=arr.length, t, j;
              while (i) {
                  j=Math.floor(Math.random() * (i--)); //
                  t=arr[i];
                  arr[i]=arr[j];
                  arr[j]=t;
              }
          }
          console.time("shuffle3");
          shuffle3(letter);
          console.timeEnd("shuffle3");
          console.log(letter) 

          運行結果如下:

          還有最后一個問題,我們來驗證一下,還是和上面的方法一樣,隨機排序1000次,看看字母a出現在0-9個位置的概率是多少,理論上應該是1000/10=100。

          來看下面的代碼:

          let n=1000;
          let count=(new Array(10)).fill(0);
          function shuffle3(arr) {
              let i=arr.length, t, j;
              while (i) {
                  j=Math.floor(Math.random() * (i--)); //
                  t=arr[i];
                  arr[i]=arr[j];
                  arr[j]=t;
              }
          }
          for (let i=0; i < n; i++) {
              let letter=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
              shuffle3(letter);
              count[letter.indexOf('a')]++
          }
          console.log(count); 

          結果如下:

          可以看到基本上都是接近100的,可以說明洗牌算法是隨機的。

          4 機選彩票

          最近開發做了一個模擬彩票游戲的功能,彩票有機選,其實就是隨機選取,下面以雙色球為例來看看實現的效果是什么樣的。

          雙色球前區從1到33個小球,后區從1到16個小球,一注彩票中前區至少選6個,后區至少選1個。

          這里使用洗牌算法實現,如下圖:

          天在小破站看到一個前端生成隨機驗證碼的視頻,感覺很有意思,就跟著操作了一下,成功了。

          后來自己又想給它加一個提交按鈕,輸入并判斷驗證碼的正確性,也可以正常運行,但是我的代碼好像還是存在一些bug:

          1.canvas標簽是繪圖容器,自帶屬性使它是一個默認300*150的容器,縮小canvs容器時,里面的繪圖也會變小,我沒有找到合適的方法去調整它的大小。

          2.對于輸入框input,我使用了float浮動,為了使input輸入框和canvas里面的驗證碼并排,但是被vscode警告了。

          這次的實戰練習也經歷了很多坎坷,但是也收獲很大。學習到了canvas標簽的用法、JS全局變量和局部變量、以及有關context的一些屬性和方法。

          最后,希望路過的大佬,幫我看看bug,幫幫菜鳥。

          附上源碼

          家好,今天給大家介紹一款,js+css實現的按鈕懸停動畫特效html頁面前端源碼,隨機元素彈出(圖1)。送給大家哦,獲取方式在本文末尾。

          圖1

          鼠標經過按鈕區域的時候,會隨機從不同位置上彈出很多小元素,效果很不錯(圖2)

          圖2

          源碼完整,需要的朋友可以下載學習(圖3)

          圖3

          本源碼編碼:20238,需要的朋友,訪問下面鏈接后,搜索20238,即可獲取。

          「鏈接」


          主站蜘蛛池模板: 免费一区二区三区在线视频| 美女免费视频一区二区三区| 日本高清天码一区在线播放| 亚洲制服丝袜一区二区三区 | 国产品无码一区二区三区在线蜜桃 | 午夜福利一区二区三区高清视频| 一区二区在线播放视频| 一区二区精品在线观看| 中文字幕日韩一区二区三区不 | 国产婷婷色一区二区三区| 国产亚洲福利精品一区| 亚洲国产一区二区三区在线观看| 亚洲AV无码一区二区三区牛牛| 好吊妞视频一区二区| 亚洲国产综合精品一区在线播放| 亚洲午夜一区二区电影院| 国产SUV精品一区二区88L| 亚洲av无码一区二区三区不卡 | 亚洲AV无码一区二区乱孑伦AS| 无码一区18禁3D| 国产一区在线视频| 麻豆精品人妻一区二区三区蜜桃| 一区二区免费电影| 色偷偷av一区二区三区| 国产av一区二区精品久久凹凸| 美女一区二区三区| 中文字幕日韩一区二区三区不| 亚洲一区二区三区在线| 国产色综合一区二区三区| 国产精品小黄鸭一区二区三区| 在线观看中文字幕一区| 少妇一夜三次一区二区| 日韩高清国产一区在线| 99精品国产高清一区二区三区 | 亚洲一区精品无码| 中文字幕一区二区人妻性色| 亚洲AV日韩精品一区二区三区| 无码人妻一区二区三区一| 中文字幕一区视频| 亚洲Av永久无码精品一区二区| 亚洲色欲一区二区三区在线观看|