Как я могу генерировать числа, которые варьируются от диапазона в зависимости от ввода пользователя - PullRequest
0 голосов
/ 26 мая 2018

Я пытаюсь генерировать случайные числа с различными диапазонами в зависимости от ввода пользователя.В моей программе пользователь будет вводить iLvl как число от 1 до 100, в зависимости от этого числа я сгенерирую число, соответствующее диапазону уровня, и назначу его preRoll, который затем распечатывается на форуме.Проблема, с которой я сталкиваюсь, заключается в том, что независимо от того, какой номер я ввожу, я получаю одинаковые номера (которые варьируются от 5 до 8).Я не уверен, почему это происходит, но я полагаю, что это связано с системными часами, которые генерируют число.Я прошу прощения, если вопрос слишком расплывчатый или действительно простой, но у меня есть некоторые проблемы с пониманием того, как генератор случайных чисел работает в c #.Спасибо за все отзывы и, пожалуйста, дайте мне знать, если есть еще вопросы

        //Function to get random number
    private static readonly Random getrandom = new Random();

    public static int GenRan(int min, int max)
    {
        lock (getrandom) // synchronize
        {
            return getrandom.Next(min, max);
        }
    }

    private void selButt_Click(object sender, EventArgs e)
    {
        int iLvl = 0;
        int preRoll = 0;
        iLvl = int.Parse(itemLvl.Text);
        if (ringType.SelectedIndex == 0)
        {
            ringpic.Load("E:\\ProgProj\\POERingMaker  Alpha 1.0\\POERingMaker  Alpha 1.0\\Resources\\Steel_Ring.png");
            Random obj = new Random();
            if ( iLvl >= 1 || iLvl <= 4)       // teir 8
            {
                preRoll = obj.Next(5, 9);
            }
            else if (iLvl >= 5 || iLvl <= 10)  // teir 7
            {
                preRoll = obj.Next(10, 19);
            }
            else if (iLvl >= 11 || iLvl <= 17)  // teir 6
            {
                preRoll = obj.Next(20, 29);
            }
            else if (iLvl >= 18 || iLvl <= 23)  // teir 5
            {
                preRoll = obj.Next(30, 39);
            }
            else if (iLvl >= 24 || iLvl <= 29)  // teir 4
            {
                preRoll = obj.Next(40, 49);
            }
            else if (iLvl >= 30 || iLvl <= 35)  // teir 3
            {
                preRoll = obj.Next(50, 59);
            }
            else if (iLvl >= 36 || iLvl <= 43)  // teir 2
            {
                preRoll = obj.Next(60, 69);
            }
            else if (iLvl >= 44 || iLvl <= 100)  // teir 1
            {
                preRoll = obj.Next(70, 79);
            }
            else
            {
                MessageBox.Show("Item Level incorrect! ");
            }
            prefixBox.Text = preRoll.ToString();
        }
        else if (ringType.SelectedIndex == 1)
        {
            ringpic.Load("E:\\ProgProj\\POERingMaker  Alpha 1.0\\POERingMaker  Alpha 1.0\\Resources\\Opal_Ring.png");
        }
        else if (ringType.SelectedIndex == 2)
        {
            ringpic.Load("E:\\ProgProj\\POERingMaker  Alpha 1.0\\POERingMaker  Alpha 1.0\\Resources\\Prismatic_Ring.png");
        }
    }

Ответы [ 3 ]

0 голосов
/ 26 мая 2018

Вы неправильно используете логическое ИЛИ в своих операторах if.

if(someNumber >= 1 || someNumber <= 4) // do things

Все числа больше или равны 1 ИЛИ меньше или равны 4, поэтому это условие всегдаМатчи.Поскольку вы устанавливаете границы, вы хотите использовать логическое AND.

if(someNumber >= 1 && someNumber <= 4) // do things

Это соответствует только числам 1..4 включительно.3 больше или равно 1 И меньше или равно 4, поэтому оно совпадает.5 больше или равно 1, но также больше 4, поэтому оно не соответствует вашему состоянию.

0 голосов
/ 26 мая 2018

Системные часы на самом деле не «используются для генерации случайного числа» - они используются для предоставления единовременного начального значения для алгоритма генерации случайных чисел, на котором будет основана его последующая последовательность чисел.Использование основанного на времени начального значения является проблемой только тогда, когда вы создаете несколько случайных экземпляров очень близко по времени, а затем ожидаете, что каждый из них будет использовать разные начальные значения.Нечто подобное покажет проблему:

  Random rand1 = new Random();
  Random rand2 = new Random();
  Thread.Sleep(2000);
  Random rand3 = new Random();

Почти наверняка, rand1 и rand2 получат ту же последовательность случайных чисел, что и другие, тогда как rand3 - нет.Но это не проблема - этого можно избежать, просто создав один экземпляр Random и используя его для всех случайных чисел, а не для нескольких экземпляров (если вы не можете гарантировать, что они не будут иметь одинаковое начальное значение времени).

В коде вы вначале создаете экземпляр getrandom и функцию для генерации ранжированного случайного числа следующим образом:

private static readonly Random getrandom = new Random();

public static int GenRan(int min, int max)
{
    lock (getrandom) // synchronize
    {
        return getrandom.Next(min, max);
    }
}

Но вы никогда не используете GenRan.Вместо этого вы создаете новый случайный объект в событии Click:

Random obj = new Random();

Хотя это выглядит как какая-то ошибка, это не вызовет описанную вами проблему, потому что вы просто используете этообъект для генерации каждого случайного числа.Поэтому, по крайней мере, внутренне, похоже, это сработает.

Поскольку рассматриваемый код находится внутри метода _Click, я предполагаю, что он вызывается для события.Вы генерируете не более одного случайного числа за вызов метода, и при каждом вызове вы создаете новый случайный экземпляр.Кажется маловероятным, чтобы обработчик событий пользовательского интерфейса был вызван достаточно близко, чтобы иметь эту проблему.Кроме того, проблема не в том, что вы получаете одинаковую последовательность случайных чисел (что случается с несколькими случайными экземплярами, созданными слишком близко по времени), а в том, что это не соответствуетПараметры следующего метода, которые указывают диапазон для случайного числа.Таким образом, это вообще не имеет ничего общего с основанным на времени начальным значением.

Так что все это то, что на самом деле НЕ является неправильным.Вместо этого это неправильно из-за неправильного написания условных выражений.Вот несколько примеров из вашего кода:

        if ( iLvl >= 1 || iLvl <= 4)       // teir 8
        {
            preRoll = obj.Next(5, 9);
        }
        else if (iLvl >= 5 || iLvl <= 10)  // teir 7
        {
            preRoll = obj.Next(10, 19);
        }
        else if (iLvl >= 11 || iLvl <= 17)  // teir 6
        {
            preRoll = obj.Next(20, 29);
        }

Вот так начинается блок условных выражений.Давайте пройдемся со значением 3.

Сначала мы нажмем на это:

        if ( iLvl >= 1 || iLvl <= 4)       // teir 8

И первое условие выполнено - iLvl> = 1. А остальное условие "ИЛИ iLvl <= 4 ".Таким образом, при выполнении любого условия будет выполнено следующее утверждение: </p>

        {
            preRoll = obj.Next(5, 9);
        }

Обратите внимание, что это точно описывает диапазон результатов, которые вы получаете.

Если у вас нетпока не видели проблему, давайте перейдем к значению 6.

        if ( iLvl >= 1 || iLvl <= 4)       // teir 8
        {
            preRoll = obj.Next(5, 9);
        }
        else if (iLvl >= 5 || iLvl <= 10)  // teir 7
        {
            preRoll = obj.Next(10, 19);
        }

Если вы ожидаете, что первый блок будет ложным, а второй - истиной, то есть ошибка.Первый блок удовлетворяется ВСЕМИ значениями, которые либо больше нуля, или любое значение <5. И, конечно, наше новое значение "6" больше нуля, итак что это первое условие.Фактически, ВСЕ значения> 0 будут использовать это условие, и это ваша проблема.

Чтобы исправить, вы должны использовать «&&» вместо «||», чтобы гарантировать, что ОБА условия выполнены для блока, чтобывыполнять.

0 голосов
/ 26 мая 2018

Вы проверяете, если iLvl >= 1 ИЛИ iLvl <= 4, поэтому, если iLvl меньше единицы, это всегда будет верно.Используйте && (и) вместо || (или), чтобы убедиться, что оба условия выполняются.

Кроме того, вы можете упростить свои утверждения следующим образом:

if (iLvl < 1 || iLvl > 100)
{
    MessageBox.Show("Item Level incorrect! ");
}
else if (iLvl <= 4)   // teir 8
{
    preRoll = obj.Next(5, 9);
}
else if (iLvl <= 10)  // teir 7
{
    preRoll = obj.Next(10, 19);
}
else if (iLvl <= 17)  // teir 6
{
    preRoll = obj.Next(20, 29);
}
else if (iLvl <= 23)  // teir 5
{
    preRoll = obj.Next(30, 39);
}
else if (iLvl <= 29)  // teir 4
{
    preRoll = obj.Next(40, 49);
}
else if (iLvl <= 35)  // teir 3
{
    preRoll = obj.Next(50, 59);
}
else if (iLvl <= 43)  // teir 2
{
    preRoll = obj.Next(60, 69);
}
else  // teir 1
{
    preRoll = obj.Next(70, 79);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...