Predictable Javascript array shuffle

后端 未结 3 1292
后悔当初
后悔当初 2021-01-19 02:27

I\'m trying to predictably shuffle javascript arrays the same way each time the webpage is loaded.

I can shuffle the arrays randomly, but every time i reload the pag

3条回答
  •  旧时难觅i
    2021-01-19 02:53

    In order to shuffle an array in a seemingly random and predetermined way, you can break the problem into two parts.

    1. Generate pseudo random numbers

    You could use a different PRNG, but the Xorshift is very simple, fast to both initialise and step through, and evenly distributed.

    This function takes an integer as a seed value, and returns a random function that always returns the same floating point values in the range 0 to 1.

    const xor = seed => {
      const baseSeeds = [123456789, 362436069, 521288629, 88675123]
    
      let [x, y, z, w] = baseSeeds
    
      const random = () => {
        const t = x ^ (x << 11)
        ;[x, y, z] = [y, z, w]
        w = w ^ (w >> 19) ^ (t ^ (t >> 8))
        return w / 0x7fffffff
      }
    
      ;[x, y, z, w] = baseSeeds.map(i => i + seed)
      ;[x, y, z, w] = [0, 0, 0, 0].map(() => Math.round(random() * 1e16))
    
      return random
    }
    

    2. Shuffle using configurable random function

    The Fisher Yates shuffle is an efficient shuffle algorithm with even distribution.

    const shuffle = (array, random = Math.random) => {
      let m = array.length
      let t
      let i
    
      while (m) {
        i = Math.floor(random() * m--)
        t = array[m]
        array[m] = array[i]
        array[i] = t
      }
    
      return array
    }
    

    Putting it together

    // passing an xor with the same seed produces same order of output array
    console.log(shuffle([1, 2, 3, 4, 5, 6, 7, 8, 9], xor(1))) // [ 3, 4, 2, 6, 7, 1, 8, 9, 5 ]
    console.log(shuffle([1, 2, 3, 4, 5, 6, 7, 8, 9], xor(1))) // [ 3, 4, 2, 6, 7, 1, 8, 9, 5 ]
    
    // changing the seed passed to the xor function changes the output
    console.log(shuffle([1, 2, 3, 4, 5, 6, 7, 8, 9], xor(2))) // [ 4, 2, 6, 9, 7, 3, 8, 1, 5 ]
    

提交回复
热议问题