Shuffler.ts 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. /**
  2. * Warning: Shufflers will alter the given array
  3. */
  4. class Shuffler<T> {
  5. private array : Array<T>;
  6. private position = 0;
  7. /**
  8. * Maybe use seeded random some day
  9. */
  10. private rng : () => number;
  11. public constructor (array : Array<T>, rng? : () => number) {
  12. this.rng = rng == undefined ? Math.random : rng;
  13. this.array = array;
  14. }
  15. public restart () {
  16. this.position = 0;
  17. }
  18. /**
  19. * Gets a random element from the Shuffler Array
  20. * Can be called repeatedly
  21. * When there are no more elements left, returns undefined
  22. * @returns {T}
  23. */
  24. public getOne () : T {
  25. // get a random element from this.position to (array.length - 1)
  26. // store it locally
  27. // switch it with array[this.position]
  28. // return it
  29. if (this.position >= this.array.length) {
  30. return undefined;
  31. }
  32. let randomIndex = Math.floor(this.rng() * (this.array.length - this.position)) + this.position;
  33. let localCopy = this.array[this.position];
  34. this.array[this.position] = this.array[randomIndex];
  35. this.array[randomIndex] = localCopy;
  36. return this.array[this.position++];
  37. }
  38. /**
  39. * There should be no reason to use this with the "getOne" code above.
  40. * @returns {T[]}
  41. */
  42. public getShuffled () : Array<T> {
  43. let array = this.array.slice(0);
  44. var m = array.length, t, i;
  45. while (m) {
  46. i = Math.floor(this.rng() * m--);
  47. t = array[m];
  48. array[m] = array[i];
  49. array[i] = t;
  50. }
  51. return array;
  52. }
  53. }