Neden System.Security.Cryptography.RandomNumberGenerator yerine C # sınıfı System.Random kullanılıyor?


86

Neden her zaman System.Security.Cryptography.RandomNumberGenerator'dan (veya RandomNumberGenerator soyut olduğu için alt sınıflarından) şifreli olarak güvenli rasgele sayı üretecini kullanmak yerine System.Random'dan "standart" rasgele sayı üretecini kullansın?

Nate Lawson, saat 13: 11'deki Google Tech Talk sunumu " Crypto Strikes Back " te Python, Java ve C # 'dan "standart" rasgele sayı üreteçlerini kullanmamamızı ve bunun yerine şifreleme açısından güvenli sürümü kullanmamızı söyledi.

Rastgele sayı üreteçlerinin iki versiyonu arasındaki farkı biliyorum (bkz. Soru 101337 ).

Ama her zaman güvenli rasgele sayı üretecini kullanmamak için hangi mantık var? Neden System.Random kullanıyorsunuz? Belki performans?


7
Hangisini yazmayı tercih edersin?
Macha

13
Çok fazla insan bunu yaptıklarının gerekçesi olarak ciddi şekilde kullanır (genellikle yüksek sesle değil). Kod yazıldığından daha fazla okunur, önemsiz uzunluk farklılıklarını kim umursar?
Mark Sowul

3
Ama yine de kriptografi yapmıyorsanız neden kriptografik RNG'leri kullanmalısınız?
Mark Sowul

3
@Macha, takma adlar bunun içindir ->using R = System.Security.Cryptography.RandomNumberGenerator; R.Create();
cchamberlain

Yanıtlar:


146

Hız ve niyet. Rastgele bir sayı oluşturuyorsanız ve güvenliğe ihtiyacınız yoksa, neden yavaş bir kripto işlevi kullanasınız? Güvenliğe ihtiyacınız yok, öyleyse neden bir başkasının numaranın güvenli bir şey için kullanılamayacağını düşünmesini sağlayasınız?


31
Niyet argümanını çok seviyorum.
Lernkurve

12
Random.GetNext'in, özellikle dizili bir ortamda rastgele sayıları spektrum üzerinde "yayma" konusunda iyi olmadığı unutulmamalıdır. Rand5 probleminden Rand7'ye farklı çözümleri test etmek için bir program yazarken bu problemle karşılaştım. Şu anda 0 ile 10 arasında 100000 rastgele sayı içeren hızlı iş parçacıklı bir testte, üretilen sayıların 82470'i 0 idi. Önceki testlerimde benzer tutarsızlıklar gördüm. Kriptografi rastgele, sayı dağılımında çok eşittir. Sanırım ders, ihtiyaçlarınız için "yeterince rastgele" olduğunu görmek için her zaman rastgele verilerinizi test etmektir.
Kristoffer L

35
@Kristoffer Bence kötüye kullandın Random. Tahmin edeyim: RandomHer sayı için sınıfın yeni bir örneğini oluşturdunuz , bu, kaba bir zamanlayıcı tarafından tohumlandığı için yaklaşık 1-16 ms'lik bir aralık için aynı değerle tohumlanacaktır.
CodesInChaos

15
@CodesInChaos: Bunun yanı sıra Random, aynı nesne birden fazla iş parçacığından kullanıldığında tüm 0'ları döndürmesine neden olan bir yarış koşulu var .
BlueRaja - Dany Pflughoeft

3
@KristofferL: Yukarıdaki yoruma bakın, bu yanıta
BlueRaja - Danny Pflughoeft

65

Hızın ve daha kullanışlı arayüzün ( NextDouble()vb.) Yanı sıra, sabit bir çekirdek değeri kullanarak tekrarlanabilir rastgele bir sıra oluşturmak da mümkündür. Bu, Test sırasında diğerleri arasında oldukça kullanışlıdır.

Random gen1 = new Random();     // auto seeded by the clock
Random gen2 = new Random(0);    // Next(10) always yields 7,8,7,5,2,....

2
Ve anlaşılması daha kolay olabilecek BitConverter.ToInt32 (Byte [] değeri, int startIndex) var. ;)
sisve

7
Ian Bell ve David Braben, çok sınırlı hafızaya sahip geniş bir gezegen listesi ve nitelikleri (boyut, vb.) Oluşturmak için Elite bilgisayar oyununda rastgele bir jeneratör kullandılar. Bu aynı zamanda jeneratörün deterministik bir model (bir tohumdan) oluşturmasına da dayanır - Kripto'nun açıkça sunmadığı (tasarım gereği.) Burada bunu nasıl yaptıkları hakkında daha fazla bilgi var: wiki.alioth.net/index.php / Random_number_generator ve "Infinite Game Universe: Mathematical Techniques" ISBN: 1584500581 kitabında bu tür teknikler hakkında daha genel bir tartışma vardır.
Daniel James Bryars


2
@phoog "Sonuç olarak, uygulama kodunuz, aynı tohumun .NET Framework'ün farklı sürümlerinde aynı sözde rastgele sırayla sonuçlanacağını varsaymamalıdır." - Bilmiyorum, bana oldukça açık görünüyor. Ancak bu uyarıya rağmen mevcut programları bozmadan pratikte değiştiremezlerse şaşırmam.
Roman Starkov

2
@phoog: Bir şey söylüyorsunuz ve sonra tam tersini. Kendinizle doğrudan çelişiyorsunuz.
Timwi

53

Öncelikle, bağladığınız sunum, güvenlik amacıyla yalnızca rastgele sayılardan bahsediyor. Dolayısıyla Random, güvenlik dışı amaçlar için kötü olduğunu iddia etmiyor .

Ama öyle olduğunu iddia ediyorum. .Net 4 uygulaması Randombirkaç yönden kusurludur. Rastgele sayılarınızın kalitesini umursamıyorsanız, yalnızca kullanmanızı öneririm. Daha iyi üçüncü taraf uygulamaları kullanmanızı tavsiye ederim.

Hata 1: Tohumlama

Varsayılan yapıcı geçerli saat ile tohumlar. Bu nedenle Random, kısa bir zaman çerçevesi içinde (yaklaşık 10 ms) varsayılan kurucu ile oluşturulan tüm örnekler aynı sırayı döndürür. Bu belgelenmiştir ve "tasarım gereği". Kodunuzu çoklu iş parçacığı yapmak istiyorsanız, bu özellikle can sıkıcıdır, çünkü Randomher iş parçacığının çalıştırılmasının başında bir örnek oluşturamazsınız .

Çözüm, varsayılan oluşturucuyu kullanırken çok dikkatli olmak ve gerektiğinde el ile tohumlamaktır.

Buradaki bir başka sorun da çekirdek boşluğunun oldukça küçük olmasıdır (31 bit). Dolayısıyla Random, tamamen rastgele tohumlarla 50 bin örnek oluşturursanız , muhtemelen iki kez rastgele bir sayı dizisi elde edersiniz ( doğum günü paradoksu nedeniyle ). Yani manuel tohumlamanın doğru yapılması da kolay değil.

Hata 2: Döndürülen rastgele sayıların dağılımı Next(int maxValue)önyargılıdır

Next(int maxValue)Açıkça tek tip olmayan parametreler var . Örneğin, hesaplarsanız , örneklerin yaklaşık 2 / 3'ünü r.Next(1431655765) % 2alırsınız 0. (Cevabın sonundaki örnek kod.)

Hata 3: NextBytes()Yöntem verimsizdir.

Bayt başına maliyet, NextBytes()tam bir tamsayı örneği oluşturmanın maliyeti kadar büyüktür Next(). Bundan gerçekten bayt başına bir örnek oluşturduklarından şüpheleniyorum.

Her örnekten 3 bayt kullanan daha iyi bir uygulama NextBytes(), neredeyse 3 faktör kadar hızlanacaktır .

Bu kusur sayesinde makinemden (Win7, Core i3 2600MHz) Random.NextBytes()sadece yaklaşık% 25 daha hızlı System.Security.Cryptography.RNGCryptoServiceProvider.GetBytes.

Eminim biri kaynak / derlenmiş bayt kodunu incelese, kara kutu analizimde bulduğumdan daha fazla kusur bulacaktır.


Kod örnekleri

r.Next(0x55555555) % 2 çok önyargılı:

Random r = new Random();
const int mod = 2;
int[] hist = new int[mod];
for(int i = 0; i < 10000000; i++)
{
    int num = r.Next(0x55555555);
    int num2 = num % 2;
    hist[num2]++;
}
for(int i=0;i<mod;i++)
    Console.WriteLine(hist[i]);

Verim:

byte[] bytes=new byte[8*1024];
var cr=new System.Security.Cryptography.RNGCryptoServiceProvider();
Random r=new Random();

// Random.NextBytes
for(int i=0;i<100000;i++)
{
    r.NextBytes(bytes);
}

//One sample per byte
for(int i=0;i<100000;i++)
{   
    for(int j=0;j<bytes.Length;j++)
      bytes[j]=(byte)r.Next();
}

//One sample per 3 bytes
for(int i=0;i<100000;i++)
{
    for(int j=0;j+2<bytes.Length;j+=3)
    {
        int num=r.Next();
        bytes[j+2]=(byte)(num>>16);   
        bytes[j+1]=(byte)(num>>8);
        bytes[j]=(byte)num;
    }
    //Yes I know I'm not handling the last few bytes, but that won't have a noticeable impact on performance
}

//Crypto
for(int i=0;i<100000;i++)
{
    cr.GetBytes(bytes);
}

1
İlginç, bulduğunuzu doğrulayabilirim: Makinemde Next (1431655765) ayrıca herhangi bir tohumlama ile 2/3 verir. 1431655765'in büyüsü nedir? Bu numaraya nasıl ulaştınız?
citykid

1
@citykid Sayıya onaltılık veya bit olarak bakın. Bu sihir, Random31 bitlik bir tamsayıyı belirtilen üst sınıra sahip bir sayıya dönüştürmek için kullanılan şüpheli yoldan ortaya çıkar . Detayları unuttum ama bir şey gibi randomValue * max / 2^{31}.
CodesInChaos

1431655765_10 = 1010101010101010101010101010101_2
Tim S.

6
Hm. Peki, C # için Random'ın hangi uygulamasını kullanmanızı tavsiye edersiniz?
Arsen Zahray

1
Next()Burada sizin tarafınızdan gösterilen , dağılımının tekdüzelik olmaması kutsal inek oldukça muhteşem bir böcek - ve bulgularınızı ilk yazmanızdan 6 yıl sonra bugün hala mevcut. (Yalnızca "kusur" yerine "hata" diyorum, çünkü dokümanlar "Sözde rastgele sayıların sonlu bir sayı kümesinden eşit olasılıkla seçildiğini" iddia ediyor . Öyle değil ve buradaki kodunuz bunu kanıtlıyor.)
Mark Amery

24

System.Random, kriptografik olarak güvenli rasgele sayılar üretmediği için çok daha başarılıdır.

Makinemde 4 baytlık bir arabelleği rastgele verilerle 1.000.000 kez dolduran basit bir test, Random için 49 ms, RNGCryptoServiceProvider için 2845 ms sürüyor. Doldurduğunuz arabelleğin boyutunu artırırsanız, RNGCryptoServiceProvider ek yükü daha az alakalı olduğundan farkın daralacağını unutmayın.


2
Bunu gerçek bir testle gösterdiğiniz için teşekkür ederiz.
Lernkurve

3
Bunun sert olduğunu düşünebilirsiniz, ancak kıyaslama kodunu eklemeden bir performans karşılaştırmasının sonuçlarını yayınlamak için -1. Performans özellikleri son 8 yılda değişmemiş Randomve RNGCryptoServiceProviderdeğişmemiş olsa bile (ki bildiğim kadarıyla), Stack Overflow'da kodu olan bir karşılaştırmanın sonuçlarına güvenmemek için yeterince tamamen bozuk kıyaslama gördüm. herkese açık değil.
Mark Amery

21

En bariz nedenlerden daha önce bahsedilmişti, bu yüzden burada daha belirsiz bir tane var: kriptografik PRNG'lerin tipik olarak "gerçek" entropi ile sürekli olarak yeniden beslenmesi gerekir. Bu nedenle, bir CPRNG'yi çok sık kullanırsanız, sistemin entropi havuzunu tüketebilirsiniz, bu da (CPRNG'nin uygulanmasına bağlı olarak) onu zayıflatır (böylece bir saldırganın tahmin etmesine izin verir) veya doldurmaya çalışırken bloke eder. entropi havuzu (böylece bir DoS saldırısı için bir saldırı vektörü haline gelir).

Her iki durumda da, uygulamanız artık - sizinkinin aksine - gerçekten hayati bir şekilde CPRNG'nin kriptografik özelliklerine bağlı olan diğer, tamamen ilgisiz uygulamalar için bir saldırı vektörü haline geldi .

Bu, uygulamaların /dev/randomher türlü kernel CPRNG'yi yanlış kullandığı Linux çalıştıran başsız sunucularda (fare ve klavye girdisi gibi entropi kaynakları olmadığı için doğal olarak oldukça küçük entropi havuzlarına sahip olan) gözlemlenen gerçek bir gerçek dünya problemidir, BTW Doğru davranış, küçük bir tohum değerini okumak /dev/urandomve bunu kendi PRNG'lerini tohumlamak için kullanmak olacaktır .


Wikipedia makalesini ve entropi ve entropi tükenmesi hakkındaki diğer bazı İnternet kaynaklarını okudum ve tam olarak anlamıyorum. Rastgele sayı üreteci sistem zamanı, boş bayt sayısı vb. İle beslendiğinde entropi havuzunu nasıl tüketebilirim? Başkaları bunu rastgele sayıları tahmin etmek için bir saldırı vektörü olarak nasıl kullanabilir? Kolay bir örnek verebilir misiniz? Belki de bu tartışma çevrimdışına alınmalıdır. en.wikipedia.org/wiki/Entropy_%28computing%29
Lernkurve

3
Sistem zamanı bir entropi kaynağı değildir çünkü tahmin edilebilirdir. Serbest bayt sayısından emin değilim, ancak bunun da yüksek kaliteli bir entropi kaynağı olduğundan şüpheliyim. Saldırgan, sunucuya daha fazla istek göndererek, serbest bayt sayısının azalmasına neden olarak, onu kısmen belirleyici hale getirebilir. Uygulamanız bir saldırı vektörü haline gelir, çünkü entropi havuzunu tüketerek, güvenlik açısından kritik diğer uygulamayı daha az rastgele sayılar kullanmaya veya entropi kaynağı yenilenene kadar beklemeye zorlar.
quant_dev

Örneğin 32 bitlik bir tohumla beslenen sözde rastgele bir jeneratör varsa, kaba kuvvet saldırısının genellikle oldukça kolay olacağını anlıyorum; 64 bitlik bir tohum bile doğum günü saldırılarına maruz kalabilir. Tohum bundan çok daha büyük olduğunda, yine de riski tam olarak görmüyorum. Her bir çıktı baytı için 128 bitlik bir durumu bir blok şifreleme algoritmasından geçiren ve ardından en alttaki 8 biti çıkaran rastgele bir üreteci varsa, bir saldırgan, ardışık çıktı baytları konserlerinde bile durumu nasıl anlayabilir? şifreleme algoritmasının kendisi?
supercat

11

Çevrimiçi bir kart oyunu veya piyango programlıyorsanız, sekansın tahmin edilmesinin neredeyse imkansız olduğundan emin olmak istersiniz. Bununla birlikte, kullanıcılara, örneğin günün bir sözünü gösteriyorsanız, performans güvenlikten daha önemlidir.


9

Bu biraz uzun uzadıya tartışılmıştır, ancak nihayetinde performans konusu, bir RNG seçerken ikinci bir husustur. Dışarıda çok sayıda RNG var ve çoğu sistem RNG'sinin oluşturduğu konserve Lehmer LCG en iyisi ve hatta en hızlısı değil. Eski, yavaş sistemlerde mükemmel bir uzlaşmaydı. Bu uzlaşma bugünlerde nadiren gerçekten alakalı. Bu şey günümüz sistemlerinde devam eder çünkü A) bu şey zaten inşa edilmiştir ve bu durumda 'tekerleği yeniden icat etmek' için gerçek bir neden yoktur ve B) insanların büyük çoğunluğunun onu ne için kullanacağı için, bu 'yeterince iyi'.

Nihayetinde, bir RNG seçimi Risk / Ödül oranına indirgenir. Bazı uygulamalarda, örneğin bir video oyununda, hiçbir şekilde risk yoktur. Lehmer RNG, fazlasıyla yeterlidir ve küçük, özlü, hızlı, iyi anlaşılmış ve 'kutudadır'.

Uygulama, örneğin, gerçek ödüllerin dahil olduğu ve denklemin bir noktasında gerçek paranın oyuna girdiği bir çevrimiçi poker oyunu veya piyango ise, 'kutuda' Lehmer artık yeterli değildir. 32 bitlik bir sürümde, en iyi şekilde döngüye başlamadan önce yalnızca 2 ^ 32 olası geçerli duruma sahiptir . Bugünlerde bu, kaba kuvvet saldırısına açık bir kapı. Böyle bir durumda, geliştirici , bazı türlerin Çok Uzun Dönem RNG'si gibi bir şeye gitmek isteyecek ve muhtemelen onu kriptografik olarak güçlü bir sağlayıcıdan tohumlamak isteyecektir . Bu, hız ve güvenlik arasında iyi bir uzlaşma sağlar. Böyle bir durumda, kişi dışarıda Mersenne Twister veya bir tür Çoklu Özyinelemeli Oluşturucu gibi bir şey arıyor olacaktır .

Uygulama, büyük miktarlarda finansal bilgiyi bir ağ üzerinden iletmek gibi bir şeyse, şimdi çok büyük bir risk vardır ve olası herhangi bir ödülden çok daha ağırdır. Hâlâ zırhlı araçlar var, çünkü bazen ağır silahlı adamlar yeterli olan tek güvenliktir ve bana güvenin, eğer tanklar, savaşçılar ve helikopterlerle özel harekatçılardan oluşan bir tugay mali açıdan uygun olsaydı, tercih edilen yöntem olurdu. Böyle bir durumda, kriptografik olarak güçlü bir RNG kullanmak mantıklıdır, çünkü elde edebileceğiniz güvenlik düzeyi ne olursa olsun, istediğiniz kadar değildir. Böylece bulabildiğiniz kadarını alacaksınız ve maliyet, hem zaman hem de para açısından çok, çok uzak bir ikinci sırayı sorun. Ve bu, her rastgele dizinin çok güçlü bir bilgisayarda oluşturulmasının 3 saniye sürdüğü anlamına geliyorsa, 3 saniyeyi bekleyeceksiniz,


3
Bence büyüklükleriniz konusunda yanılıyorsunuz; finansal verilerin gönderilmesi son derece hızlı olmalıdır; ticaret algoritmanız sonuca rekabetten 0,1 ms daha hızlı ulaşırsa, al / sat / stop-loss / fiyat teklifi kuyruğunda daha iyi sonuçlanırsınız. 3 saniye sonsuzluktur. Tüccarların inanılmaz derecede iyi bilgisayarlara yatırım yapmasının nedeni budur. Önceki cevaba bakın; Crypt.RNG, yeni numara başına yalnızca 0,0028 ms sürer; 0,0000028 saniye, yani ne kadar işlem gerektirdiği ve ayrıca hızın ne kadar önemli olduğu konusunda 9 büyüklüğündeysiniz.
Henrik


4

Herkesin kriptografik olarak güvenli rasgele sayılara ihtiyacı yoktur ve daha hızlı düz bir programdan daha fazla faydalanabilirler. Belki daha da önemlisi, System.Random sayılarının sırasını kontrol edebilmenizdir.

Yeniden oluşturmak isteyebileceğiniz rastgele sayılar kullanan bir simülasyonda, simülasyonu aynı çekirdekle yeniden çalıştırırsınız. Belirli bir hatalı senaryoyu yeniden oluşturmak istediğinizde de hataları izlemek için kullanışlı olabilir - programınızı programı çökerten aynı rasgele sayı dizisiyle çalıştırmak.


2

Eğer güvenliğe ihtiyacım yoksa, yani sadece kriptografik açıdan güçlü değil, nispeten belirsiz bir değer istiyorum, Random'ın kullanımı çok daha kolay bir arayüze sahip.


2

Farklı ihtiyaçlar, farklı RNG'leri gerektirir. Kripto için, rastgele sayılarınızın olabildiğince rastgele olmasını istersiniz. Monte Carlo simülasyonları için, alanı eşit şekilde doldurmalarını ve RNG'yi bilinen bir durumdan başlatabilmelerini istersiniz.


1
Keşke System.Random ikisini de yapsaydı .. oh, peki.
user2864740

2

Random bir rasgele sayı üreteci değildir, adını tarihsel nedenlerle alan deterministik sözde rasgele dizi üretecidir.

Kullanmanın nedeni, System.Randombu özellikleri, yani aynı tohumla başlatıldığında aynı sonuç dizisini üretmesi garantili olan deterministik bir diziyi istiyorsanız.

Arayüzü feda etmeden "rastgeleliği" geliştirmek istiyorsanız, System.Randombirkaç yöntemi geçersiz kılmaktan miras alabilirsiniz .

Neden deterministik bir dizi istiyorsun

Gerçek rastgelelikten çok deterministik bir diziye sahip olmanın bir nedeni, tekrarlanabilir olmasıdır.

Örneğin, sayısal bir simülasyon çalıştırıyorsanız, diziyi (gerçek) rastgele bir sayı ile başlatabilir ve hangi sayının kullanıldığını kaydedebilirsiniz .

Daha sonra, aynı simülasyonu, örneğin hata ayıklama amacıyla tekrarlamak isterseniz, bunun yerine diziyi kaydedilen değerle başlatarak yapabilirsiniz.

Neden bu özel, çok iyi olmayan diziyi istiyorsun?

Aklıma gelen tek neden, bu sınıfı kullanan mevcut kodla geriye dönük uyumluluk olabilir.

Kısacası, kodunuzun geri kalanını değiştirmeden sıralamayı iyileştirmek istiyorsanız, devam edin.


1

Haritaya "rastgele" bir dizi mücevher (görüntü) yerleştirecek bir oyun yazdım (iPhone'da Crystal Sliders: Burada ) ve siz haritayı istediğiniz gibi döndürüp seçiyordunuz ve onlar gitti. - Bejeweled'e benzer. Random () kullanıyordum ve telefon açıldığından beri 100ns tik sayısı ile tohumlandı, oldukça rastgele bir tohum.

Birbiriyle neredeyse aynı olan oyunlar üretmesini şaşırtıcı buldum - 90 ya da daha fazla mücevherden, 2 renkten, 1 ila 3 mücevher haricinde TAM OLARAK aynı olan iki tane elde edecektim! 90 jeton çevirirseniz ve 1-3 çevirme dışında aynı kalıbı elde ederseniz, bu ÇOK olası değildir! Onları aynı gösteren birkaç ekran görüntüsü var. System.Random () 'un ne kadar kötü olduğuna şaşırdım! Kodumda korkunç derecede yanlış bir şey yazmam GEREKTİ ve yanlış kullandığımı varsaydım. Yine de yanılmışım, bu jeneratördü.

Bir deney - ve son bir çözüm olarak, 1985'ten beri kullandığım rastgele sayı üretecine geri döndüm - ki bu ÇOK DAHA iyi. Daha hızlıdır, tekrarlamadan önce 1.3 * 10 ^ 154 (2 ^ 521) periyodu vardır. Orijinal algoritma 16 bitlik bir sayı ile tohumlandı, ancak bunu 32 bitlik bir sayıya değiştirdim ve ilk tohumlamayı iyileştirdim.

Orijinal olan burada:

ftp://ftp.grnet.gr/pub/lang/algorithms/c/jpl-c/random.c

Yıllar boyunca, aklıma gelen her rastgele sayı testini yaptım ve hepsini geride bıraktım. Kriptografik olarak herhangi bir değere sahip olmasını beklemiyorum, ancak "return * p ++;" kadar hızlı bir sayı döndürüyor 521 bit bitene kadar biter ve sonra yeni rastgele bitler oluşturmak için bitler üzerinde hızlı bir işlem yürütür.

Bir C # sarıcı oluşturdum - buna JPLRandom (), Random () ile aynı arayüzü uyguladı ve kodda onu çağırdığım tüm yerleri değiştirdim.

Aradaki fark ÇOK daha iyiydi - Aman Tanrım - sadece 90 kadar mücevherin ekranlarına bir modelde bakmaktan anlamam mümkün değildi, ancak bundan sonra oyunumun acil bir sürümünü yaptım.

Ve System.Random () 'u bir daha asla hiçbir şey için kullanmam. Sürümlerinin şu anda 30 yaşında olan bir şey tarafından havaya uçurulmasından ŞAŞIRTIM!

-Traderhut Oyunları


3
İlk tahminim, Randomçok sık yeniden yarattığın . Yalnızca Nextbu örneği birçok kez çağırdıktan sonra oluşturulmalıdır .Randomkötü, ama o kadar da kötü değil . Bu sorunu sergileyen bir çift tohumla birlikte örnek bir program yayınlayabilir misiniz?
CodesInChaos

Kod, her seviyenin başında bir Rastgele () oluşturacaktı (ancak bu, sonraki seviyelerden daha fazla seviye 1 ile ilgili büyük bir sorundu) Kod kabaca aşağıdaki gibiydi:
Traderhut Oyunları

Rnd = new Random ((uint) GameSeed); NextGameSeed = Rnd.Next (2000000000); Her seviyede yeni bir tohumla oluşturulan yeni bir Rastgele kullanıldı - Tohum her seviye için kaydedildi, böylece haritayı yeniden oluşturabilir ve aynı zamanda eşleşen rastgele tohumların sırasını onaylayabilirdim. Bu, oyunun çözülmüş geçerli bir harita dizisi olduğunu onaylamama ve oyunu yeniden oluşturmama izin veriyor.
Traderhut Games

Ve başlangıçta, Rastgele, System.DateTime.Now.Ticks (veya 0) temelinde oluşturuldu ve ardından GameSeed, yukarıdaki Rnd.Next () ile aynı çağrı kullanılarak seçildi. Bunu yapamazsam, rastgele sayı üretecinin tohumlanmasıyla ilgili ciddi bir sorun var demektir.
Traderhut Oyunları

bu orijinal sorunun cevabı değil!
Mike Dinescu
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.