Ошибка случайного случайного числа .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.
Если он возвращает новый экземпляр, есть вероятность, что новые экземпляры получат одно и то же начальное значение при повторных вызовах. Если семена совпадают, то два разных экземпляра возвращают одинаковые "случайные" значения.