/** * Warning: Shufflers will alter the given array */ class Shuffler { private array : Array; private position = 0; /** * Maybe use seeded random some day */ private rng : () => number; public constructor (array : Array, rng? : () => number) { this.rng = rng == undefined ? Math.random : rng; this.array = array; } public restart () { this.position = 0; } /** * Gets a random element from the Shuffler Array * Can be called repeatedly * When there are no more elements left, returns undefined * @returns {T} */ public getOne () : T { // get a random element from this.position to (array.length - 1) // store it locally // switch it with array[this.position] // return it if (this.position >= this.array.length) { return undefined; } let randomIndex = Math.floor(this.rng() * (this.array.length - this.position)) + this.position; let localCopy = this.array[this.position]; this.array[this.position] = this.array[randomIndex]; this.array[randomIndex] = localCopy; return this.array[this.position++]; } /** * There should be no reason to use this with the "getOne" code above. * @returns {T[]} */ public getShuffled () : Array { let array = this.array.slice(0); var m = array.length, t, i; while (m) { i = Math.floor(this.rng() * m--); t = array[m]; array[m] = array[i]; array[i] = t; } return array; } }