Ошибка случайного случайного числа .Net.

Я уверен, что я делаю что-то неправильно; но это уже немного смутило меня.

Я сделал небольшую игру Silverlight (старый клон Galaxian). Когда игра начинается ~ 90% времени, в игровой зоне случайно помещается куча звезд. Есть три типа звезд - более крупные звезды быстрее, маленькие звезды двигаются медленнее.

Он выглядит следующим образом:

ScreenShot1

~ 10% времени, когда все звезды появляются в "полосах", ScreenShot2

Я думаю, стоит упомянуть, что хотя они и в узких полосах; они не все в одном и том же положении. Таким образом, он все равно генерирует случайное число - просто крошечное.

Чтобы воспроизвести ошибку, я просто ударил 'f5' в браузере. Почти все время он работает так, как ожидалось. Редко, я получаю группы. Еще раз нажмите "F5", чтобы устранить проблему.

Без публикации гигантской стены кода; Я думаю, что это самый подходящий код. Он появляется в классе Base, из которого унаследованы все мои звезды. Он называется один раз, когда каждая звезда создается.

Protected Sub SetInitialPosition()
    myElipse.Height = GetStarSize()
    myElipse.Width = GetStarSize()

    _location.X = GetRandom.Next(-1 * Settings.StarEdge, CType(GameCanvas.Width, Integer) + Settings.StarEdge)
    _location.Y = GetRandom.Next(0, CType(GameCanvas.Height, Integer))

    myElipse.Fill = New SolidColorBrush(GetStarColor)

End Sub

Я не вижу ничего плохого. GetRandom() возвращает класс Singleton Random, и я в зависимости от GameCanvas.Height и GameCanvas.Width действителен, но опять же .Width работает точно так, как ожидалось.

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

Если это поможет, я могу опубликовать ссылку на игру.
(http://robdude.weebly.com/cci.html)

РЕДАКТИРОВАТЬ # 1:
Вот код из GetRandom()

Protected Shared Function GetRandom() As Random
    If _random Is Nothing Then _random = New Random()

    Return _random
End Function

РЕДАКТИРОВАТЬ № 2: Я действительно ценю любые мысли/советы по этому поводу.

Ответ 1

Я хотел сделать этот ответ как можно более общим, в надежде, что он может быть полезен кому-то другому. Я собрал здесь другие ответы (вместе с фактическим исправлением моей проблемы), которые могут быть полезны для тех, кто испытывает странное поведение с произвольно сгенерированными номерами.

Использование разных экземпляров случайных

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

потоковая безопасность

Случайный не является потокобезопасным.

Условная точка останова

Я иногда забываю, что это вариант. В некоторых случаях акт "перебора кода" скроет ошибки, появляющиеся при запуске. Установка условной точки останова - хороший способ проверить это. В моем случае 'CType (GameCanvas.Height, Integer) < 750 ' - это условие, которое я использовал.

Logging

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

В конце концов, по причинам, которые я не понимаю, редко, значение GameCanvas.Height было установлено неправильно. Моя теория заключается в том, что я делаю что-то еще неправильно или ненадлежащим образом в другом месте, когда создаю/позицию/размер GameCanvas.

Пошаговое выполнение кода, по-очереди, казалось, затрудняло задачу. В моей ситуации размер игрового поля фиксирован; поэтому вместо того, чтобы проверять размер элемента управления GameCanvas, я теперь вытаскиваю его из объекта "Настройки".

Спасибо за команду - отлаживают всех. Это было очень оценено.

Ответ 2

Если GetRandom() каждый раз возвращает новый экземпляр Random, то это объясняет ошибку. У вас должен быть только экземпляр Random.

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