Избегайте случайного выбора одной и той же точки, чтобы имитировать "человеческое" поведение - PullRequest
0 голосов
/ 13 декабря 2018

У меня есть класс, который случайным образом создает некоторые объекты на сцене. Эти объекты появляются в двух случайных точках.Проблема в том, что Random.Range имеет вероятность выбора точки несколько раз подряд, то есть я выбираю одну и ту же точку 5 или 6 раз.Я просто хочу как-то ограничиться, что если Random.Range выберет одну и ту же точку не более 3 раз, она выберет другую точку.

public ObjectSequence ObstacleSequence;
public float WaitSpawnTime;
public float DistanceFromObstacleIndex;
public Transform[] spawnPoints;
private List<int> Point = new List<int>();

void Start()
{
    InvokeRepeating("Spawn", WaitSpawnTime, DistanceFromObstacleIndex);
}

void Spawn()
{
    int spawnPointIndex;
    do
    {
        spawnPointIndex = Random.Range(0, spawnPoints.Length);
        Point.Add(spawnPointIndex);
    } while (SwitchPoint());
    if (SwitchPoint())
        Point.Clear();
    ObjectSequence obstacle = Instantiate(ObstacleSequence,
       spawnPoints[spawnPointIndex].position, spawnPoints[spawnPointIndex].rotation);
    obstacle.setRandomCurrentChildIndex();
    obstacle.CurrentChild.GetComponent<SpriteRenderer>().flipY = 
       (obstacle.transform.position == spawnPoints[1].position) ? true : false;
}

private bool SwitchPoint()
{
    if (Point.Count >= 2)
    {
        return Point[0].Equals(Point[1]) && Point[1].Equals(Point[2]);
    }
    return false;
}

У меня есть только две точки, поэтому «случайный» подход (например, Рандомизация списка или многие другие «уникальные случайные» сообщения) не работает.

Ответы [ 2 ]

0 голосов
/ 14 декабря 2018

В зависимости от вашей реальной цели использование жестко закодированной таблицы «случайного» выбора может быть хорошим вариантом.Это хороший выбор для игр, в которых геймплей выиграет от правильного предсказания следующего выбора (например, «тупые враги-роботы» с фиксированным поведением, таким как «Левый», «Левый», «Правый», «Левый», «Повторить»).

В качестве альтернативы, чтобы получить «истинно случайный с человеческой точки зрения», вы можете подсчитать, как часто в последнее время происходит определенный выбор, и если он превышает пороговое значение, принудительно выбирайте другой выбор (и счетчики сброса).Более сложный подход был бы выбором веса на основе некоторых предыдущих результатов.

Вот пример, который будет генерировать не более 3 одинаковых значений подряд:

class NiceRandom
{
   static Random rand = new Random();
   int count = 0;
   int prevChoice = -1;
   public int Next()
   {
       int r = rand.Next(0,2);
       if (r == prevChoice)
       {
           count++;
           // switch our "random" result if there are 3 of the same rolls
           r = count < 3 ? r : (r == 0 ? 1 : 0);
       }

       if (r != prevChoice)
       {
           // reset count if we roll other value.
           prevChoice = r;
           count = 0;
       }

       return r;
   }
}

Предупреждение: сделать "случайным"«числа, которые ведут себя по-разному, чтобы казаться более« естественными »(как приведенный выше код), скорее всего, приведут к тому, что распределения больше не будут равномерными / случайными - убедитесь, что результат выглядит хорошо для вашей игры / приложения, и вам действительно не нужна истинная случайность.Вы можете проверить требования к случайности для игровых автоматов Какой тип генератора случайных чисел используется в игровой индустрии казино? , чтобы узнать больше.

0 голосов
/ 13 декабря 2018

Общая идея, независимо от того, сколько людей считают ее неэффективной, состоит в том, чтобы просто отбрасывать значения до тех пор, пока не будет получено хорошее, и я гарантирую, что это более эффективно для небольшого числа выборов, чем для любого решения, основанного на перетасовке целого списка.,В любом случае, чтобы решить вашу проблему, вам нужно сохранить последние 3 сгенерированных числа и, если они все одинаковые, вы можете просто выбрать другую точку появления, например так:

if (generated[0] == generated[1] && generated[0] == generated[2])
    return 1 - generated[0]; // flip 0 to 1 and 1 to 0
else
    return Random.Range(0, 2);

Однако, если выиметь более 2 чисел, вот что вы будете делать (все еще на основе повторных попыток, и все же более эффективно, чем перетасовка):

if (generated[0] == generated[1] && generated[0] == generated[2])
{
    int newNumber;
    do
        newNumber = Random.Range(0, maximum);
    while (newNumber == generated[0]);
}
else
    return Random.Range(0, maximum);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...