you could do
// Creates an enumeration from 1 to 10
// orders it randomly
// then picks 4 items
var enemyLanes = Enumerable.Range(1, 10).OrderBy(c => rnd.Next()).Take(4).ToArray();
which will return an int[]
with 4
elements which are unique random values between 1
and 10
.
But further it sounds like you also additionally want that in the next iteration it doesn't pick the same lanes again as it had before so you could remember which lanes you used before and also filter out these and do e.g.
private int[] currentEnemyLanes;
...
// Except additionally removes all the elects of currentEnemyLanes from the options
// and keeps only these that are not currently occupied
var nextEnemyLanes = var enemyLanes = Enumerable.Range(1, 10).Except(currentEnemyLanes).OrderBy(c => rnd.Next()).Take(4).ToArray();
currentEnemyLanes = nextEnemyLanes;
In general though it would even be more optimized in my eyes if the enemies store their current lane and give it free again when picking the next one like e.g.
private int currentLane;
private static HashSet<int> availableLanes = new HashSet<int>() { 1,2,3,4,5,6,7,8,9,10 };
void PickNextLane()
{
// pick a random entry from all available lanes
var newLane = availableLanes.OrderBy(l => rnd.Next()).First();
// remove this from the options so another instance won't pick the same one
availableLanes.Remove(newLane);
// if you had a valid lane already
if(currentLane > 0)
{
// Now give it free so another one can pick it again
availableLanes.Add(currentLane);
}
// finally store the new value
currentLane = newLane;
}