I am working on a scrambling system where every time the player loads into the game certain variables would be completely random. What I need is a way to have values (for and example I will be using 1-9 as the values) so say we have 9 values and 9 variables. I want each of the 9 values to assign itself to one of the 9 variables but I don’t want multiple variables to have the same value. So one game it would be (for the variables I will use the letters a,b,c,d,e,f,g,h, and i) a1, b2, c3, d4, e5, f6, g7, h8, i9, and the next it could be a3, b2, c1, d9, e4, f8, g6, h7, i5. As each value is assigned to only one variable. I hope this makes sense, any help would be appreciated! Thank you!
This is problem that you can solve using a LINQ query. The code below does the following: a) Initialize a random generator using a seed; b) creates a string of letters from which to choose the random character value; and c) generates the list.
The list generator creates two enumerable lists in the range of 1 through 9 inclusive and orders them randomly, then uses the LINQ .Zip() method to combine the results of the two lists. The delegate that I pass to the Zip() method takes the value from each list, combining them into a string using the first number as an index into our string and the second number converted to a string.
The resulting list is a unique combination of the letter and number, without reusing either letter or number in each generated pair. I think this is what you are trying to accomplish given what you had described.
The code:
Random rand = new Random(Environment.TickCount);
string letters = "abcdefghi";
var randomList = Enumerable.Range(1, 9)
.OrderBy(x => rand.Next())
.Zip(Enumerable.Range(1, 9)
.OrderBy(x => rand.Next()),
(first, second) => string.Concat(letters[first - 1], second.ToString())).ToList();
Here is some code that will scramble a collection:
using UnityEngine;
using System.Collections.Generic;
public static class ObjectScrambler
{
public static T[] ScrambleCollection<T>(ICollection<T> input)
{
T[] output = new T[input.Count];
try
{
int outputPosition = 0;
List<T> inputCopy = new List<T>(input);
int index = 0;
int count = inputCopy.Count;
while (count > 0)
{
index = UnityEngine.Random.Range(0, count--);
output[outputPosition++] = inputCopy[index];
inputCopy.RemoveAt(index);
}
}
catch (System.Exception ex)
{
Debug.Log("Could not scramble input collection: " + ex.ToString());
}
return output;
}
}
How to use:
int[] inputCollection = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int[] scrambledCollection = ObjectScrambler.ScrambleCollection(inputCollection);
Example Result using integers:
Example with Colors:
public Color[] inputCollection;
public Color[] scrambledCollection;
private void Awake()
{
inputCollection = new Color[] {Color.red, Color.blue, Color.green, Color.black, Color.magenta, Color.white };
scrambledCollection = ObjectScrambler.ScrambleCollection(inputCollection);
}
Result with colors: