问题描述
我有这个代码,但看起来随机正在激活同一个游戏对象。我怎么能确定不一样的会被激活?例如,此代码激活 2 个游戏对象,但有时只激活一个,因为随机选择了相同的游戏对象两次。
for (int i = 0; i < 2; i++)
{
int index = Random.Range(0,EyeButtonArray.Length);
EyeButtonArray[index].SetActive(true);
}
解决方法
你可以随机打乱你的容器并选择前两个元素。
int wanted = 2;
int[] nums = System.Linq.Enumerable.Range(0,EyeButtonArray.Length).ToArray();
System.Random rnd = new System.Random();
nums = nums.OrderBy(x => rnd.Next()).ToArray();
for(int x = 0; x < 2; ++x)
EyeButtonArray[nums[x]].SetActive(true);
另一种使用 HashSet
的解决方案是跟踪您选择的元素并不断生成,直到您选择唯一的元素。
HashSet<int> RandomElementIdx = new HashSet<int>();
int picked = 0;
int wanted = 2;
while(picked < wanted)
{
int index = Random.Range(0,EyeButtonArray.Length);
if(RandomElementIdx.Contains(index))
continue;
RandomElementIdx.Add(index);
EyeButtonArray[index].SetActive(true);
++picked;
}
以上代码段假设您的列表大于或等于 wanted
。如果小于,则会导致无限循环。它也不完全有效,因为它会不断尝试生成新数字,直到随机命中一个未使用的数字为止。
听起来你想要的是
- 您有一个对象列表/数组
- 您想启用接下来的两个随机的
- (可选 - 不确定)您想禁用两个当前的
您可以简单地“洗牌”您的数组,然后启用现在洗牌的两个项目,例如
using System.Linq;
...
// OPTIONAL (but I thought makes sense)
// store the currently enabled objects to also be able to disable them later
// when you enable the next pair
private GameObject[] _currentEnabled;
public void EnableTwoRandom()
{
// OPTIONAL (but I thought makes sense)
// if exists first disable the last selected two buttons
if(_currentEnabled!=null)
{
foreach(var item in _currentEnabled)
{
item.SetActive(false);
}
}
// Pick two random buttons
// This first "shuffles" the buttons and then simply takes the
// first two random elements
_currentEnabled = EyeButtonArray.OrderBy(i => Random.value).Take(2).ToArray();
// enable the new two random buttons
foreach(var item in toEnable)
{
item.SetActive(true);
}
}
见
如果另外你想确保新选择的按钮也不等于你可以添加的以前的按钮
// Pick two random buttons
if(_currentEnabled != null)
{
// if there already exists a previous selection
// then exclude this selection from the available options first
_currentEnabled = EyeButtonArray.Except(_currentEnabled).OrderBy(i => Random.value).Take(2).ToArray();
}
else
{
_currentEnabled = EyeButtonArray.OrderBy(i => Random.value).Take(2).ToArray();
}
见