日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

JavaScript洗牌算法之重复抽奖

發布時間:2023/12/25 综合教程 33 生活家
生活随笔 收集整理的這篇文章主要介紹了 JavaScript洗牌算法之重复抽奖 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

十年蹤跡的最新博客:5分鐘現場擼代碼——談總結會抽獎程序,實際上就是一個洗牌算法,描述為從一個數組中隨機抽取幾個數出來,我之前寫過的一個文章:js隨機從數組中取出幾個元素?正好符合上面的要求,看了他的代碼,延伸出來的另外一種就是可以重復抽獎。學習一下,順便復習一下以前寫過的東西。

我原來簡單的代碼是這樣子:

function getRandomArrayElements(arr, count) {
    var shuffled = arr.slice(0), i = arr.length, min = i - count, temp, index;
    while (i-- > min) {
        index = Math.floor((i + 1) * Math.random());
        temp = shuffled[index];
        shuffled[index] = shuffled[i];
        shuffled[i] = temp;
    }
    return shuffled.slice(min);
}


var items = ['1','2','4','5','6','7','8','9','10'];
console.log( getRandomArrayElements(items, 4) );

邏輯:

1.首先從整個數組中抽取一個隨機值,然后把這個值和最后面一個沒有查過的項交換位置

2.循環遍歷的結果就是所有隨機值都放到最后面,循環次數為要取的隨機數組長度。

3.最后把最后面的數組取出來就得到我們的隨機數組了。

十年蹤跡的代碼使用到了ES6。

代碼一:

const cards = Array(62).fill().map((_,i)=>i+1); //初始化一個 1~62 的數組

function draw(n = 1){ // 一次抽取 n 個,默認一次 1 個
    var ret = [];
    for(var i = 0; i < n; i++){
        let idx = Math.floor(cards.length * Math.random());
        ret.push(...cards.splice(idx, 1));
    }
    return ret;
}
console.log(draw(10)); //抽取一次,10個中獎者

1.其中ret.push(...cards.splice(idx,1));使用到了上一節講到的ES6擴展符,這個會組合兩個數組的值,

2.cards.splice(idx,1)返回的是刪除的元素的數組,使用數組splice()方法,原數組cards也會發生變化,即原數組已經去掉了idx這個項。

3.接著循環的時候,cards.length縮小,idx,也會從剩下的項中取。

代碼二:

代碼二和代碼三跟我最上面的做法差不多,通過洗牌算法

function draw(amount, n = 1){
    const cards = Array(amount).fill().map((_,i)=>i+1); 

    for(let i = amount - 1, stop = amount - n - 1; i > stop; i--){
        let rand = Math.floor((i + 1) * Math.random());
        [cards[rand], cards[i]] =  [cards[i], cards[rand]];
    }
    return cards.slice(-n);
}
console.log(draw(62, 10));

其中使用到了ES6的解構,解構提供了一個方便地從對象或數組中提取數據的方法。

let [x, y] = [1, 2]; // x = 1, y = 2
 
// ES5 equivalent:
var arr = [1, 2];
var x = arr[0];
var y = arr[1];

使用這個語法,可以一次性給多個變量賦值。一個很好的附加用處是可以很簡單地交換變量值:

let x = 1,
   y = 2;

[x, y] = [y, x]; // x = 2, y = 1

代碼四:

需求是可以分開多次來取值,則需要用到了構造函數來初始化,通過方法來獲取值。

function Box(amount){
    this.cards = Array(amount).fill().map((_,i)=>i+1); 
}
Box.prototype.draw = function(n = 1){
    let amount = this.cards.length, cards = this.cards;

    for(let i = amount - 1, stop = amount - n - 1; i > stop; i--){
        let rand = Math.floor((i + 1) * Math.random());
        [cards[rand], cards[i]] =  [cards[i], cards[rand]];
    }

    let ret = cards.slice(-n);    
    cards.length = amount - n;

    return ret;
}

var box = new Box(62);
console.log(box.draw(5), box.draw(5)); //一次取 5 個,取 2 次

這個沒什么好說的,下面我附上一個我寫的代碼:

function RandomArr(amount) {
    this.arr = Array(amount).fill().map((_, i) = >i + 1);
}
RandomArr.prototype.getCount = function(count) {
    var arr = this.arr,
    len = arr.length,
    min = len - count,
    index;
    while (len-->min) {
        index = Math.floor((len + 1) * Math.random()); 
        [arr[index], arr[len]] = [arr[len], arr[index]];
    }
    var ret = arr.slice(min);
    arr.length = min;
    return ret
}

var rand = new RandomArr(62);
console.log(rand.getCount(4), rand.getCount(6));

有一些東西,叫我十分鐘現場寫出來,可能寫不出來吧。看來還是要多掌握基礎的東西。比如這個洗牌算法:

function shuffle(array) {
    var currentIndex = array.length
      , temporaryValue
      , randomIndex
      ;

    // While there remain elements to shuffle...
    while (0 !== currentIndex) {

      // Pick a remaining element...
      randomIndex = Math.floor(Math.random() * currentIndex);
      currentIndex -= 1;

      // And swap it with the current element.
      temporaryValue = array[currentIndex];
      array[currentIndex] = array[randomIndex];
      array[randomIndex] = temporaryValue;
    }

    return array;
  }

本文純粹水文一篇,歡迎到十年蹤跡的原文看他的思路:https://www.h5jun.com/post/luckey-draw-in-5-minutes.html

總結

以上是生活随笔為你收集整理的JavaScript洗牌算法之重复抽奖的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。