【问题标题】:Generate random number each time and don't include last number每次生成随机数,不包括最后一个数字
【发布时间】:2018-06-06 16:45:08
【问题描述】:

我有 4 种颜色。我想让它让玩家不能连续两次出现相同的颜色。当玩家与物体发生碰撞时,会调用RandomColor()。所以这个函数在游戏过程中被调用了很多次,有时玩家并没有改变他的颜色。

 using UnityEngine;

 public class ColorManager : MonoBehaviour {

     public SpriteRenderer player;
     public string playerColor;

     public Color[] colors = new Color[4];


     private void Awake()
     {
         RandomColor();        
     }

     public void RandomColor()
     {
         int index = Random.Range(0, 4);

         switch (index)
         {
             case 0:
                 player.color = colors[0]; //colors[0] is orange
                 playerColor = "orange";
                 break;

             case 1:
                 player.color = colors[1]; //colors[1] is pink
                 playerColor = "pink";
                 break;

             case 2:
                 player.color = colors[2]; //colors[2] is blue
                 playerColor = "blue";
                 break;

             case 3:
                 player.color = colors[3]; //colors[3] is purple
                 playerColor = "purple";
                 break;
             }    
     }    
 }

尝试使用 while 循环,执行 while 循环,但显然我做错了,因为有时我会连续两次收到相同的颜色。如果有人能弄清楚它并解释它是如何/为什么起作用的,那就太好了,因为我在这个问题上花了很多时间而且我很好奇。

【问题讨论】:

  • youz有4种颜色,在选择新颜色时重新reroll,直到播放器颜色与他目前拥有的那个不同.... span>
  • 一种更好的技术:创建一个仅包含当前合法颜色的集合,然后从该集合中选择一个随机元素。使用不可变集合会有所帮助。

标签: c# unity3d random repeat


【解决方案1】:

首先,您需要一个可以生成排除随机数的函数。以下是我使用的:

int RandomWithExclusion(int min, int max, int exclusion)
{
    int result = UnityEngine.Random.Range(min, max - 1);
    return (result < exclusion) ? result : result + 1;
}

每次调用时,都需要将结果存储在全局变量中,以便下次再次调用时将其传递给exclusion参数。

我修改了函数,这样您就不必在每次调用它时都这样做。新的RandomWithExclusion 函数将为您完成这项工作。

int excludeLastRandNum;
bool firstRun = true;

int RandomWithExclusion(int min, int max)
{
    int result;
    //Don't exclude if this is first run.
    if (firstRun)
    {
        //Generate normal random number
        result = UnityEngine.Random.Range(min, max);
        excludeLastRandNum = result;
        firstRun = false;
        return result;
    }

    //Not first run, exclude last random number with -1 on the max
    result = UnityEngine.Random.Range(min, max - 1);
    //Apply +1 to the result to cancel out that -1 depending on the if statement
    result = (result < excludeLastRandNum) ? result : result + 1;
    excludeLastRandNum = result;
    return result;
}

测试

void Update()
{
    Debug.Log(RandomWithExclusion(0, 4));
}

最后一个数字永远不会出现在下一个函数调用中。

对于您的具体解决方案,只需替换

int index = Random.Range(0, 4);

int index = RandomWithExclusion(0, 4);

【讨论】:

  • 你能解释一下为什么 (min, max -1) 为什么会有“-1”吗?这是否意味着我永远不会得到 3 号?因为数字是 0、1、2 和 3。如果它在 3 上随机排列,它将变为 3 - 1,结果为 2,这意味着 3 永远不会成为一个选项?
  • 没有。我从 Random.Range 的最大值中减去 1,然后根据 if 语句的结果将该 1 添加回结果。这是我用来删除我想要排除的数字的一种技术。您将得到数字 3。使用我在Update 函数中的答案中的测试代码进行测试,您会看到。修改答案以解决一个简单的问题并添加更多评论
  • 我花了很长时间才知道 -1 发​​生了什么。最后一个问题(我真诚地希望),为什么我们需要知道这是否是第一次运行?
  • 这很简单。如果是第一次运行,则无需进行排除,因为排除需要最后生成的数字才能起作用。问题是第一次运行没有最后生成的数字。只有在第一次运行后,您才会有最后生成的号码。我们使用firstRun 变量来确定这一点,这样我们就不必在第一次运行时进行排除,因为在第一次运行之前我们还没有最后一个随机数。
  • 优秀。谢谢
【解决方案2】:

如果RandomColor返回的颜色和prev一样,你只需要添加一个判断,再调用一次,很简单吧?

【讨论】:

  • 您会遇到像deleted 答案之一那样的冻结/锁定问题。您可以通过在协程中调用它并等待一帧来解决此问题,但这会减慢游戏速度。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多