Tobias Wälde Ответов: 2

Как избежать 2 одинаковых значений подряд (new random())


Эй,
только один короткий вопрос:

Я хаваю кнопку 'получить случайный'. Если я нажму кнопку, программа установит текст метки на это значение.
иногда, если я нажимаю кнопку 2 раза, она возвращает один и тот же номер.

Как я могу избежать получения двух одинаковых значений?

Что я уже пробовал:

int newRandom = 0;
int lastRandom = 1;

private int GetRandom()
{
   Random r = new Random();
   newRandom = r.Next(0, 7);

   while (newRandom == lastRandom)
   {
      newRandom = r.Next(0, 7);
      if(newRandom != lastRandom) break;
   }
   lastRandom = newRandom;

   return newRandom;
}


label.Text = GetRandom.ToString();

Andy Lanng

То, что вы ищете, - это имитация случайности. Не совсем случайное, но то, что человеческий мозг интерпретировал бы как случайное.
В этом случае вам придется сохранить по крайней мере предыдущее число 1

2 Ответов

Рейтинг:
15

F-ES Sitecore

Случайные числа используют так называемое "семя" в качестве начального значения математического уравнения, имитирующего случайность. Если вы дадите генератору случайных чисел одно и то же семя, вы всегда получите одну и ту же последовательность значений, поэтому первое число всегда будет одним и тем же. Вы можете указать начальное значение в конструкторе

Случайный(yourSeedHere)

Для того чтобы быть действительно случайным семя также должно быть random...so вам нужно случайное число, чтобы получить случайные числа, как это работает?

Когда вы оставляете семя, как у вас есть в вашем коде (вы используете конструктор без параметров для случайных)

Random r = new Random();


затем он использует текущее время в качестве семени, или, точнее, текущее количество "тиков". Поэтому, когда вы создаете два экземпляра Random, они создаются в разное время, поэтому используйте разные семена. Однако если вы запускаете свой код в цикле, который срабатывает несколько раз за тик, все экземпляры используют одно и то же начальное значение, поэтому генерируют одно и то же число.

Решение всего этого простое...создайте случайный класс один раз и повторно используйте его, а не создавайте новый каждый раз.

Random r = new Random();
int newRandom = 0;
int lastRandom = 1;
 
private int GetRandom()
{
   newRandom = r.Next(0, 7);
 
   while (newRandom == lastRandom)
   {
      newRandom = r.Next(0, 7);
      if(newRandom != lastRandom) break;
   }
   lastRandom = newRandom;
 
   return newRandom;
}


Tobias Wälde

большое спасибо, теперь он работает отлично

Рейтинг:
0

OriginalGriff

Такова природа случайных чисел: идея состоит в том, что следующее число не зависит от предыдущего значения, подобно тому, как вы бросаете монету: шансы на голову равны 50:50 независимо от значения, когда вы бросали ее в последний раз. И чем меньше размер выборки, тем больше вероятность того, что вы получите дубликаты. Таким образом, при выборе семи значений у вас есть шанс 1:7 последовательных дубликатов.

Итак ... создайте массив и переменную:

private List<int>values = new List<int> () { 1, 2, 3, 4, 5, 6, 7 };
private int last = -1;
private Random random = new Random();

Затем использовать эту:
public int GetRandom()
    {
    if (last < 0)
        {
        int index = random.Next(0, 7);
        last = values[index];
        values.RemoveAt(index);
        }
    int result = values[random.Next(0, 6)];
    values.Remove(result);
    values.Add(last);
    last = result;
    return result;
    }

Это не даст никаких дубликатов!


Tobias Wälde

спасибо, но другое решение лучше и работает с переменной длиной...

OriginalGriff

Проблема с другим решением заключается в том, что оно может "работать с переменной длиной (как и мое, если вы удалите "магические числа" и загрузите исходный список Перечислимыми.Диапазон) - но у него есть тот недостаток, что для возврата значения потребуется переменное (и неизвестное) количество времени - мое постоянно.