2009-09-29 14 views
5

Ok, więc mam rzut kostką aplikacji ...Kod w języku C# daje oczekiwane wyniki tylko po kroku?

Kiedy przejdę przez kod, działa normalnie, a "wyniki" zawierają poprawną liczbę wyników rzutu i wydają się być losowe, kiedy zostawiam kod uruchomić i zrobić dokładnie to samo, co tworzy zestaw identycznych liczb.

Jestem pewien, że jest to błąd logiczny, którego nie widzę, ale błądzenie nim przez wiele godzin nie poprawiło sytuacji, więc każda pomoc jest bardzo przydatna. :)

class Dice 
{ 

    public int[] Roll(int _throws, int _sides, int _count) 
    { 
     Random rnd = new Random(); 
     int[] results = new int[_throws]; 
     // for each set of dice to throw pass data to calculate method 
     for (int i = 0; i < _throws; i++) 
     { 
      int thisThrow = Calculate(_sides, _count); 
      //add each throw to a new index of array... repeat for every throw 
      results[i] = thisThrow; 
     } 

     return results; 
    } 


    private int Calculate(int _sides, int _count) 
    { 
     Random rnd = new Random(); 
     int[] result = new int[_count]; 
     int total = 0; 
     //for each dice to throw put data into result 
     for (int i = 0; i < _count; i++) 
     { 
      result[i] = rnd.Next(1, _sides); 
     } 
     //count the values in result 
     for (int x = 0; x < _count; x++) 
     { 
      total = total + result[x]; 
     } 
     //return total of all dice to Roll method 
     return total; 
    } 
} 

Odpowiedz

12

pierwszy błąd: nie wolno używać wielu instancji losowy, użycie pojedynczej instancji i przekazać, że wraz z innymi parametrami.

+0

dzięki modyfikacji teraz :) – Yoda

+0

Cholernie szybkie losowanie! –

+1

@Ian: Widziałem to zdarzało się zbyt wiele razy, aby natychmiast go nie dostrzec :) – leppie

-1

Daj konstruktorowi Losowe nasienie. To jest problem.

http://msdn.microsoft.com/en-us/library/aa329890%28VS.71%29.aspx

Random r = new Random(DateTime.Now.Millisecond); 
+2

Użycie milisekundy jako materiału siewnego jest nawet gorsze niż domyślne użycie kleszczy. Nasiona kleszczy są w większości przypadków dobre, tak jak powiedzieli inni, nie odtwarzaj ponownie klasy Losowe, a zatem ponownie je posadź z powrotem do tej samej wartości. –

+0

Ah. Jestem tak przyzwyczajony do funkcji randowych w stylu C. –

5

Po utworzeniu "Random rnd = new Random();" jest zaszczepiony przez bieżący czas. Kiedy debugujesz swój kod (który wymaga czasu), za każdym razem będzie on rozrzucany inaczej.

Utwórz 1 wystąpienie losowe i odwołaj się do niego wszędzie.

1

Tworzysz losową klasę za każdym razem, gdy potrzebujesz utworzyć numer. Wykonanie tego da ci orzechowe rezultaty.

Zobacz tutaj: FROM MSDN

Ten problem można uniknąć poprzez utworzenie jednego Losowa obiekt zamiast wielu z nich.

Aby poprawić wydajność, utwórz jeden obiekt losowy, aby wygenerować wiele losowych liczb w czasie, zamiast powtarzać tworzenie nowych obiektów losowych w celu wygenerowania jednej liczby losowej.

E.g. utworzyć prywatną instancji Random ...

1

oprócz tego, co zostało już wcześniej wspomniano ...

Używaj Losowo dla rzeczy takich jak kości, gry w karty, wybierając losowo zdjęć i tak dalej. Jeśli kiedykolwiek będziesz potrzebował stworzyć losową liczbę dla bezpieczeństwa, użyj System.Security.Cryptography.RandomNumberGenerator. Ten prosty przykład pokazuje tworzenie losowej liczby całkowitej.

 RandomNumberGenerator gen = RandomNumberGenerator.Create(); 
     byte[] myBytes = new byte[4]; 
     gen.GetBytes(myBytes); 
     int myValue = (BitConverter.ToInt32(myBytes, 0)); 

NIE używać tego, chyba że masz potrzebę bezpieczeństwa. Wydajność jest mniejsza niż w klasie Losowe. Przypuszczam, że możesz użyć tego do rozsiewania Losowego, ale to może być przesada.

EDYCJA: Przyszło mi do głowy, że nigdy tego nie testowałem. Szybki test wydajności pokazał, co następuje:

1 000 000 liczb losowych: Losowy numer alarmowy: 2,6 sekundy Losowo: 0,015 sekundy.

Tak Losowo jest około 150 razy szybsze.

+2

Dwie rzeczy. Po pierwsze, użycie losowej liczby do zaszczepienia generatora liczb pseudolosowych faktycznie nie daje większej losowości; wynik pseudo-RNG jest nadal przewidywalny. –

+1

Po drugie, wydajność krypto-wytrzymałości RNG jest zamknięta nie tylko w matematyce, którą ma do zrobienia, ale także w zdolności maszyny do dostarczenia * entropii * dla RNG do działania. RNG nie wymyślają entropii z niczego, wiesz! Ta entropia musi skądś pochodzić, a entropia jest tak samo ograniczona, jak zasób, na przykład, przepustowość, pamięć lub czas procesora. Dostajesz tyle entropii na sekundę; próba użycia ogromnych ilości entropii będzie oczywiście blokowana, dopóki nie stanie się dostępna większa entropia, podobnie jak próba użycia bloków przepustowości procesora lub sieci. –

Powiązane problemy