Last active
September 1, 2022 22:03
-
-
Save wilg/e310da134389d0e2cdcef3aafee6a338 to your computer and use it in GitHub Desktop.
Unity serializable list shuffling
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Linq; | |
using UnityEngine; | |
#nullable enable | |
public static class ShuffleExtensions { | |
// Returns a random element from the list. | |
public static T? RandomElement<T>(this IList<T> list) { | |
if (list.Count == 0) { | |
return default; | |
} | |
return list[Random.Range(0, list.Count)]; | |
} | |
// Returns a randomly-ordered version of the enumerable. Only iterates once. | |
// Use when you are going to immediately iterate over the result. | |
public static IEnumerable<T> Shuffled<T>(this IEnumerable<T> source) { | |
var list = source.ToArray(); | |
var n = list.Length; | |
for (int i = 0; i < (n - 1); i++) { | |
var r = i + Random.Range(0, n - i); | |
(list[i], list[r]) = (list[r], list[i]); | |
yield return list[i]; | |
} | |
} | |
// Returns a copy of the enumeration as an array, with a random order. | |
public static T[] ShuffledArray<T>(this IEnumerable<T> source) { | |
var list = source.ToArray(); | |
list.Shuffle(); | |
return list; | |
} | |
// Shuffles the list in-place. | |
public static void Shuffle<T>(this IList<T> list) { | |
var n = list.Count; | |
for (int i = 0; i < (n - 1); i++) { | |
var r = i + Random.Range(0, n - i); | |
(list[i], list[r]) = (list[r], list[i]); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
#nullable enable | |
// Like a queue, but it never runs out. It is always shuffled and will never dequeue the same item twice in a row. | |
// The order reshuffles every time the queue resets, so it will never repeat. | |
// There is a small amount of garbage generated on initialization and when the queue resets. | |
// Serialized, so you can use it in place of an array in the inspector. | |
[Serializable] | |
public class Shuffler<Item> { | |
public List<Item> items; | |
Item? lastDequeued; | |
Queue<Item>? queue; | |
public Shuffler(IEnumerable<Item> items) { | |
this.items = items.ToList(); | |
Shuffle(); | |
} | |
void Shuffle() { | |
queue = new Queue<Item>(items.Shuffled()); | |
} | |
public Item Dequeue() { | |
if (queue == null || queue.Count == 0) { | |
Shuffle(); | |
} | |
var item = queue!.Dequeue(); | |
if (lastDequeued != null && ReferenceEquals(item, lastDequeued)) { | |
return Dequeue(); | |
} | |
lastDequeued = item; | |
return lastDequeued; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment