Öngörülebilir rasgele jeneratör ihtiyacı


151

Ben bir web oyunu geliştiricisiyim ve rastgele sayılarla ilgili bir sorunum var. Diyelim ki bir oyuncunun kılıcı ile kritik vuruş yapma şansı% 20. Bu, her 5 isabetten 1'inin kritik olması gerektiği anlamına gelir. Sorun şu ki, çok kötü gerçek hayat sonuçları elde ettim - bazen oyuncular 5 vuruşta 3, bazen 15 vuruşta hiç yok. Savaşlar oldukça kısadır (3-10 vuruş), bu yüzden iyi rastgele dağılım elde etmek önemlidir.

Şu anda PHP kullanıyorum mt_rand(), ancak kodumuzu C ++ 'a taşıyoruz, bu yüzden oyunumuzun yeni motorunda bu sorunu çözmek istiyorum.

Çözümün düzgün bir rasgele jeneratör olup olmadığını bilmiyorum, ya da uygun dağılımı zorlamak için önceki rastgele durumları hatırlamak belki.


58
Gerçek rastgele sayılar varsayarak, tam olarak 3 kritik isabet ve% 2 kritik olmayan isabet olasılığı yaklaşık% 0,5 ve arka arkaya 15 kritik olmayan isabet şansı% 3,5 olur.
Nixuz

10
+1'den yukarı. Rasgele sayıların bir özelliği aykırı değerlere sahip olmanızdır.
endişeli

45
@Nixus: Hayır, 3 kritik isabet ve 2 kritik olmayan isabetin yaklaşık% 5 şansı, (5! / (3! * 2!)) = 10 ile çarpmayı unutuyorsunuz. 5 grevde 3 kritik isabet olması muhtemel değildir.
erikkallen

7
İlk başta bunun aptalca bir soru olduğunu düşündüm ... bir kez daha, SO tarafından tökezlendim.
SergioL

Yanıtlar:


39

Önceki cevaplara, bazı oyunların küçük koşularında gerçek rastgeleliğin istenmeyen olduğunu kabul ediyorum - bazı kullanım durumları için çok adil görünmüyor.

Ruby'de uygulama gibi basit bir Shuffle Bag yazdım ve bazı testler yaptım. Uygulama bunu yaptı:

  • Hala adil görünüyorsa veya minimum rulo eşiğine ulaşmamışsak, normal olasılığa göre adil bir isabet verir.
  • Eğer geçmiş atışlardan gözlemlenen olasılık haksız görünüyorsa, "adil bir iftira" vuruşu döndürür.

Sınır olasılıklarına göre haksız kabul edilir. Örneğin,% 20 olasılık için% 10'luk bir alt sınır ve% 40'ınızı bir üst sınır olarak ayarlayabilirsiniz.

Bu sınırları kullanarak, 10'luk isabetlerle, gerçek sahte sözde uygulamanın% 14.2'sinin bu sınırların dışında sonuçlar ürettiğini buldum . Zamanın yaklaşık% 11'i, 10 denemede 0 kritik isabet aldı. Zamanın% 3.3'ü, 5 veya daha fazla kritik isabet 10'dan çıkarıldı. Doğal olarak, bu algoritma kullanılarak (minimum rulo sayısı 5 ile), "Fairish" koşularının çok daha küçük bir miktarı (% 0.03) sınırların dışındaydı . Aşağıdaki uygulama uygun olmasa bile (kesinlikle daha akıllıca şeyler yapılabilir), kullanıcılarınızın gerçek bir sahte çözümle haksız olduğunu hissedeceklerini belirtmek gerekir.

İşte FairishBagRuby'de yazdığım et . Tüm uygulama ve hızlı Monte Carlo simülasyonu burada mevcuttur (gist) .

def fire!
  hit = if @rolls >= @min_rolls && observed_probability > @unfair_high
    false
  elsif @rolls >= @min_rolls && observed_probability < @unfair_low
    true
  else
    rand <= @probability
  end
  @hits += 1 if hit
  @rolls += 1
  return hit
end

def observed_probability
  @hits.to_f / @rolls
end

Güncelleme: Bu yöntemi kullanmak, kritik sınırlar elde etme olasılığını, yukarıdaki sınırları kullanarak yaklaşık% 22'ye çıkarır. "Gerçek" olasılığını biraz daha düşük ayarlayarak bunu dengeleyebilirsiniz. Fairish modifikasyonu ile% 17.5'lik bir olasılık, yaklaşık% 20'lik gözlemlenen uzun vadeli bir olasılık verir ve kısa vadeli koşuları adil hissettirir.


Bu benim ihtiyaçlarıma en uygun çözüm olduğunu düşünüyorum. En iyi sivri cevapta bahsedilen shuffle çantası kötü değil, ancak çok fazla hesaplama gerekiyor ve hedefe götüren en basit çözümü seviyorum.
Thinker

Steve Rabin oyunlarda rastgelelik hakkında ilginç bir makale yazdı. Kısacası, gerçek "rastgele" davranış pek çok insana gerçekten "rastgele" hissetmez ve çalışmalar bunu desteklemiştir. Makalesine AI Kararları ve Oyun Mantığı için Filtrelenmiş Rastgele denir ve "AI Game Programming Wisdom 2" (2003) kitabında yer almaktadır. Bunu kontrol etmelisiniz, muhtemelen sizin için yararlı olacaktır.
Jeff Tucker

@IanTerrell Testlerinizin örneklem büyüklüğünün ne kadar büyük olduğunu, yani bu olasılıkları belirlemek için kaç savaş olduğunu belirtmek iyi olur.

@ user677656: Özünde, ama 100 bin
Ian Terrell

223

Bu, her 5 isabetten 1'inin kritik olması gerektiği anlamına gelir. Sorun şu ki, çok kötü gerçek yaşam sonuçları elde ettim - bazen oyuncular 5 vuruşta 3, bazen 15 vuruşta hiç yok.

İhtiyacınız olan şey bir shuffle çantası . Gerçek rasgele oyunlar için çok rasgele olma sorununu çözer.

Algoritma şu şekildedir: Bir torbaya 1 kritik ve 4 kritik olmayan isabet koydunuz. Sonra çantadaki sıralarını rastgele seçer ve her seferinde bir tane seçersiniz. Torba boş olduğunda, aynı değerlerle tekrar doldurur ve rastgele hale getirirsiniz. Bu şekilde, her 5 isabet için ortalama 1 kritik isabet ve arka arkaya en fazla 2 kritik ve 8 kritik olmayan isabet elde edersiniz. Daha fazla rastgelelik için çantadaki öğe sayısını artırın.

İşte bir uygulama (Java'da) ve bir süre önce yazdığım test senaryolarına bir örnek .


21
Eleştirisi olmayan iyi fikir için + 1.
Torbayı

16
10 çanta büyüklüğüne sahip olabilirsiniz. 1 vuruş, artı% 30'luk bir saniye koyun. Kritik şans değişirse, çantayı atıp yeni bir şans başlatabilirsiniz. Bu tür herhangi bir şemanın, siz (veya rakibiniz) kritik vuruş olasılığınızı ve çantanın boyutunu bildiğinizde, bazen belirli sayıda rulo için başka bir kritik almamanız gerektiğinden emin olabileceğinizi unutmayın. Bu taktikleri etkileyebilir.
Steve Jessop

3
Evet ... böyle bir şeyde, kart sayımına benzer bir şey yapıyorsunuz. Bir peon riske atıyor muyum yoksa büyük öldürmeye mi gidiyorum ... küçük bir sabit potansiyel sonuç kümesi kayıp riskini azaltabilir ve "oyun oynama" şansını artırabilir
Matthew Whited

8
Ben shuffle çanta fikir gibi ama bu maç "ruh" maç sanmıyorum çünkü kritik isabet olasılığı% 20 (yani 10 hit hiçbiri yapabilirsiniz anlamına gelir) artık bir olasılık değil. Her 5 vuruşta tam 1 vuruş olur. Dahası, kritik isabet olasılığı değişikliği durumunda torbanın yeniden sürülmesi oyunda bir aksaklığa neden olacaktır. Eleştirel vuruşum gerçekleştiyse, daha önce bir sonraki eleştirmeni almak için kendime büyü yapacağım: p
Michaël Carpentier

2
@Jonathan: Torbayı verdiğiniz büyük boyutta yapmak aslında tüm çanta fikrini geri alır: Kabul edilebilir miktarda atışta bir şeyin (elde edilen kritik) emin olmak için. Torbayı 50000 büyük yapmak, rastgele sayı üretecini kullanmakla aynıdır.
dstibbe

113

Rastgele ne anlama geldiğini yanlış anladın.

Bunlardan hangisi daha rastgele?

resim açıklamasını buraya girin resim açıklamasını buraya girin

İkinci arsa daha eşit dağılmış gibi görünse de, daha rastgele aslında ilk arsadır. İnsan aklı genellikle kalıpları rastgelelik olarak görür, bu yüzden ilk arsadaki kümeleri kalıp olarak görüyoruz, ama değiller - sadece rastgele seçilen bir örneğin parçası.


25
İyi Numb3rs açıklaması!
RMAAlmeida

9
Teknik olarak, rastgeleliği ölçemezsiniz. Her iki dağıtım da benim için oldukça keyfi görünüyor, ancak tahminim her ikisi de algoritmik olarak oluşturuldu. İlk arsa üzerinde bir dizi test yapabilir ve puanları tekdüze bir dağılıma göre yerleştiren bir işlemden gelme olasılığını belirleyebilirsiniz, ancak daha rastgele olduğu sonucuna varamayacaksınız. Karşı örnek olarak, lineer bir kongüjasyon jeneratörü kullanarak birincisi gibi bir komplo oluşturabilir, daha sonra bir zener diyotundan yükseltilmiş gürültü kullanarak ikinci gibi bir komplo oluşturabilirsiniz. Rastgele yerine ilgisiz kelimeyi deneyin.
Dietrich Epp

8
Bahsedilen dağılımın rastgele olma olasılığını ölçebilirsiniz.
ceejayoz


2
Adil olmak gerekirse, OP doğru terimleri kullanmıyor olsa da, rasgele sayı üretecinin, kullanıcıya daha "adil" hissettiği için ikinci grafik gibi bir şey istediğinde ona ilk grafik gibi bir şey verdiğini anlar .
Kip

88

İstediğiniz davranış göz önüne alındığında, bence yanlış değişkeni rastgele seçiyorsunuz.

Bu isabetin kritik olup olmayacağını rastgele sıralamak yerine , bir sonraki kritik isabet gerçekleşene kadar dönüş sayısını rasgele ayarlamayı deneyin. Örneğin, oyuncu her kritik olduğunda 2 ile 9 arasında bir sayı seçin ve ardından birçok tur geçtikten sonra onlara bir sonraki kritik değerlerini verin. Normal bir dağılıma yaklaşmak için zar yöntemlerini de kullanabilirsiniz - örneğin, bir sonraki kritikinizi 2D4 dönüşlerde elde edersiniz.

Bu tekniğin, dünya üzerinde rastgele karşılaşmalar olan RPG'lerde kullanıldığına inanıyorum - bir adım sayacını rastgele seçiyorsunuz ve bundan sonra birçok adımdan sonra tekrar vuruluyorsunuz. Çok daha adil hissettiriyor çünkü neredeyse üst üste iki karşılaşmadan asla etkilenmiyorsunuz - bu bir kez bile olsa oyuncular sinirli oluyor.


Bunun harika bir çözüm olduğunu düşünüyorum, ama% 80 şansı ne olacak?
Düşünür

Bazen çok boyutlu rasgele jeneratörler kullanmayı seviyorum. Vurma şansı + Güç şansı + Kritik şans. Tıpkı D&D'de birkaç farklı zar atmak gibi
Matthew Whited

Bu fikri beğendim ve adım sayacı hakkında tamamen haklısın, bu son fantezide çok uzun bir süredir kullanılıyor, örneğin
Ed James

Bununla ilgili bir sorun, sadece kritik bir olasılığın isabetler arasında kabaca sabit olması durumunda çalışmasıdır. Savaşın ortasında oyuncunun kritik vuruş olasılığını iki katına çıkaran bir büyü yaptığını varsayalım. Peki dönüş sayısını nasıl ayarlıyorsunuz?
Alex319

+1 Çok hoş, aynı zamanda% 20'den çok daha az raund vurma olasılığı çok kolay.
Alice Purcell

53

İlk olarak, "uygun" dağılımı tanımlayın. Rastgele sayılar, rasgele - gördüğünüz sonuçlar (sözde) rastgele ile tamamen tutarlıdır.

Bunu genişleterek, istediğin şeyin "adalet" hissi olduğunu varsayıyorum, bu yüzden kullanıcı başarılı olmadan 100 dönüş yapamaz. Eğer öyleyse, son başarıdan bu yana başarısızlık sayısını takip eder ve oluşturulan sonucu ağırlıklandırırdım. Diyelim ki her 5 rulodan 1'i "başarılı" olsun. Yani rastgele 1'den 5'e kadar bir sayı üretiyorsunuz ve 5 ise harika.

Değilse, hatayı kaydedin ve bir dahaki sefere 1'den 5'e kadar bir sayı oluşturun, ancak diyelim ki kat (numFailures / 2) ekleyin. Bu sefer yine 5 şansta 1 şansları var. Başarısız olursa, bir dahaki sefere kazanan aralık 4 ve 5'tir; başarı şansı 2'de 2. Bu seçimlerle, 8 başarısızlıktan sonra başarılı olacakları kesin.


Bu notta ... rasgele sayılar aralığı dağılımı etkiler mi ... örneğin bir Rastgele seçim yapmak r = new Random (); r.Sonraki (1,5) vs. r.Sonraki (1, 1000000)% 200000
Eoin Campbell

23
+1'ye OP'ye rastgele yanlış anladığını söylemek yerine sorunun arkasındaki sorunu görmek için.
Boris Callens

4
Bunu yaparsanız, başarıların toplam oranının 5'te 1'den fazla olacağını unutmayın. Bunun için bir yol (örneğin) 1..100 aralığından rastgele 20 farklı sayı seçmek ve bunların onların eleştirmeni olun. Yine de bir sürü daha defter tutma.
Steve Jessop

"5 in 1'den büyük olacak" - uzun vadede olması bekleniyor, yani.
Steve Jessop

Başlangıç ​​olasılığını biraz azaltabilirsiniz, böylece toplam oran 1/5'e düşürülür. Onu ne kadar azaltmanız gerektiğine karar vermedim, ancak her şey süreklidir, bu yüzden doğru bir cevap olmalı.
Steve Jessop

35

Mt_rand () yerine böyle bir şey koymaya ne dersiniz?

XKCD komik (RFC 1149.5, standart IEEE tarafından denetlenen rastgele sayı olarak 4'ü belirtir.)

(RFC 1149.5, standart IEEE tarafından denetlenen rastgele sayı olarak 4'ü belirtir.)

Gönderen XKCD .


İyi olan, ama bu OPs rasgele sayı dağıtım sorunu çözecek? ;-)
Arjan Einbu

Pek sayılmaz; Bu işlevi kullanabileceği rastgele olmayan bir RNG istiyor; ama gerçekten istediği şu anki en iyi cevapla daha iyi açıklanıyor ( stackoverflow.com/questions/910215/910224#910224 )
Colin Pickard

28
Bu OP'nin istediğinden daha rastgele
Çağdaş Tekin

-1 çünkü RFC1149'un bölüm 5'i yoktur (ve alternatif olarak 1149.5 yoktur); Adil rastgelelik için +1.
greyfade

34

Umarım bu makale size yardımcı olacaktır: http://web.archive.org/web/20090103063439/http://www.gamedev.net:80/reference/design/features/randomness/

Bu 'rastgele sayılar' üretme yöntemi rpg / mmorpg oyunlarında yaygındır.

Çözdüğü sorun şudur (özü):

Boğazında bir bıçak örümceği var. Vurur ve özlüyorsun. Tekrar vurur ve tekrar özlüyorsun. Ve tekrar tekrar, vuracak hiçbir şey kalmayıncaya kadar. Sen öldün ve cesedin üzerinde iki tonluk bir eklembacaklı var. İmkansız? Hayır. Evet. Ancak yeterli oyuncu ve yeterli zaman verildiğinde, ihtimal dışı olan neredeyse kesinleşir. Bıçak örümceğinin sert olması değildi, sadece kötü şanstı. Ne kadar sinir bozucu. Bir oyuncuyu bırakmak istemek için yeterlidir.


1
Bunun bir varyantı duydum - "milyonda bir olay dünya nüfusunda 6.000 kez oluyor".
ceejayoz

19

İstediğiniz rastgele sayılar değil, bir insana rastgele görünen sayılardır. Diğerleri, Shuffle Bad gibi size yardımcı olabilecek bireysel algoritmalar önerdi.

Bu alanın iyi ayrıntılı ve kapsamlı bir analizi için bkz. AI Game Programming Wisdom 2 . Tüm kitap herhangi bir oyun geliştiricisi için okumaya değer, "görünüşte rastgele sayılar" fikri bölümde ele alınmıştır:

AI Kararları ve Oyun Mantığı için Filtrelenmiş Rastgelelik :

Özet: Geleneksel bilgelik, rastgele sayı üreteci ne kadar iyi olursa, oyununuzun o kadar öngörülemez olacağını gösterir. Bununla birlikte, psikoloji çalışmalarına göre, kısa vadede gerçek rastgelelik genellikle insanlar için kesin olarak rastgele görünüyor. Bu makalede, hala güçlü istatistiksel rastgele olma özelliğini korurken, rastgele AI kararlarının ve oyun mantığının oyuncular için nasıl daha rastgele görüneceği gösterilmektedir.

Ayrıca ilginç bir bölüm daha bulabilirsiniz:

Rasgele Sayıların İstatistikleri

Özet: Rasgele sayılar en çok Yapay Zeka ve genel olarak oyunlar tarafından kullanılır. Potansiyellerini görmezden gelmek, oyunu öngörülebilir ve sıkıcı hale getirmektir. Bunları yanlış kullanmak, onları açıkça görmezden gelmek kadar kötü olabilir. Rastgele sayıların nasıl üretildiğini, sınırlamalarını ve yeteneklerini anlamak, bunları oyununuzda kullanmanın birçok zorluğunu ortadan kaldırabilir. Bu makale, rastgele sayılara, bunların üretilmesine ve iyi olanları kötülerden ayırma yöntemlerine ilişkin bilgiler sunmaktadır.


8

Şüphesiz herhangi bir rasgele sayı üretme, bu tür koşuları üretme şansına sahiptir? Uygun yüzdeleri görmek için 3-10 rulo halinde yeterince büyük bir örnek seti almayacaksınız.

Belki istediğin şey merhamet eşiğidir ... son 10 atışını hatırla ve eğer kritik bir isabet almadılarsa, onlara bir freebie ver. Rastgele sapanları ve okları yumuşatın.


8

En iyi çözümünüz, birden fazla farklı rasgele olmayan şema ile oyun testi yapmak ve oyuncuları en mutlu yapanı seçmek olabilir.

Ayrıca, belirli bir karşılaşmada aynı numara için bir geri çekilme politikası deneyebilirsiniz, örneğin, bir oyuncu 1ilk turda atarsa kabul eder. Başka bir tane almak için arka arkaya 12 1s yuvarlamaları gerekir . Üçte birini almak için 1üst üste 3, reklam sonsuz gerekir.


7

Maalesef istediğiniz şey etkili bir şekilde rastgele olmayan bir sayı üreteci - çünkü bir sonraki sayıyı belirlerken önceki sonuçların dikkate alınmasını istiyorsunuz. Korkarım rastgele sayı üreteçleri bu şekilde çalışmaz.

Her 5 isabetten 1'inin kritik olmasını istiyorsanız, 1 ile 5 arasında bir sayı seçin ve bu isabetin kritik olacağını söyleyin.


1
o oyun dostu rastgele istiyor, bazı durumlarda sıkı rastgele üretilen sayılar kullanırsanız, sonuçta "kore rastgele" sonuçları elde edersiniz. Bunlar, oyuncuları çok sık sinirlendiren ve sinirlendiren rastgele sonuçlardır (herhangi bir soy 2 oyuncuya sorun);)
Juan Techera

Sonuç olarak, eğer ilk vuruş kritik ise, sonraki dört oyuncu olmayacak. Bu OP'nin istediği gibi geliyor, ancak bunu böyle ifade ettiğinizde engelli geliyor. Bunun için UV'mi aldın.
belgariontheking

-1 "rasgele" ile "hatıra" arasında kafa karıştırıyor gibi görünüyorsunuz - en.wikipedia.org/wiki/Memorylessness
Alice Purcell

7

mt_rand (), Mersenne Twister uygulamasına dayanır , yani alabileceğiniz en iyi rastgele dağıtımlardan birini verir.

Görünüşe göre istediğiniz şey rastgele değil, bu yüzden tam olarak ne istediğinizi belirtmeye başlamalısınız. Muhtemelen çelişkili beklentileriniz olduğunu fark edeceksiniz - sonuçların gerçekten rastgele ve öngörülebilir olmaması gerekir, ancak aynı zamanda belirtilen olasılıktan yerel varyasyonlar sergilememeleri gerekir - ancak daha sonra tahmin edilebilir hale gelir. Arka arkaya en fazla 10 suçsuzluk ayarlarsanız, oyunculara "arka arkaya 9 suçsuzunuz varsa, bir sonrakinde% 100 kesinlikte kritik olacak" dediniz. hiç rastgele değil rahatsız.


6

Bu kadar az sayıda testte şöyle sonuçlar beklemelisiniz:

Gerçek rastgelelik sadece büyük bir set boyutu üzerinde tahmin edilebilir, böylece bir madeni parayı çevirmek ve ilk kez üst üste 3 kez kafa almak oldukça mümkündür, ancak birkaç milyondan fazla çevirmek yaklaşık 50-50 ile sonuçlanacaktır.


7
Birkaç milyon dönüşten sonra hala madalyonun sadece bir tarafını görme şansınız olmasına rağmen. Bu gerçekleşirse de, muhtemelen sonsuz bir olasılık dışı sürücüye çok yakın oturuyorsunuz: P
Grant Peters

haha, evet ama şans o kadar inanılmaz derecede düşük ki matematik kanunları eşit (ish) bir dağılım görmeniz gerektiğini söylüyor.
Ed James

6

Önceden oluşturulmuş sayıları takip etmeyi veya olası tüm değerleri karıştırmayı öneren birçok cevap görüyorum.

Şahsen ben aynı fikirdeyim, arka arkaya 3 suçun kötü olduğunu. Ben de arka arkaya 15 suçsuz kötü olduğunu kabul ediyorum.

Sorunu, her sayıdan sonra kritik şansını değiştirerek çözerdim. Örnek (fikri göstermek için):

int base_chance = 20;
int current_chance = base_chance;

int hit = generate_random_number(0, 100) + 1; // anything from 1 to 100
if(hit < current_chance)//Or whatever method you use to check
{
    //crit!
    if(current_chance > base_chance)
        current_chance = base_chance; // reset the chance.
    else
        current_chance *= 0.8; // decrease the crit chance for the NEXT hit.
}
else
{
    //no crit.
    if(current_chance < base_chance)
        current_chance = base_chance; // reset the chance.
    else
        current_chance *= 1.1; // increase the crit chance for the NEXT hit.
    //raise the current_chance
}

Ne kadar uzun süre bir eleştiriye sahip olmazsanız - bir sonraki işleminizin eleştirmesi için daha yüksek şansınız olur. Eklediğim sıfırlama tamamen isteğe bağlıdır ve gerekli olup olmadığını test etmek gerekir. Uzun bir kritik olmayan eylem zincirinden sonra arka arkaya birden fazla eylem için bir kriterin daha yüksek bir olasılığının verilmesi arzu edilebilir veya edilmeyebilir.

Sadece 2 sentime atıyorum ...


Bu tür bir yaklaşımı seviyorum. Muhtemelen başka türlü yapardım. Daha düşük bir şansla başlayın ve isabet edene kadar maksimum% 20 + ilave edilen bir yüzdeye kadar yükseltin ve tekrar düşük bir miktara sıfırlayın.
Matthew

5

Sadece yaparken "kötü çizgiler" olasılığını üzerinde kontrol sağlar bir algoritma odaklanacağız böylece üst birkaç cevaplar, büyük açıklamalardır asla deterministik olma. Yapmanız gerektiğini düşündüğüm şey:

Bunun yerine belirleme p , Kritik isabet sizin olasılığıdır bir Bernoulli dağılımının parametresi, belirtmek bir ve b , beta dağılımının parametreleri, Bernoulli dağılımının "eşlenik önsel". Şimdiye kadarki kritik ve kritik olmayan isabetlerin sayısı olan A ve B'yi takip etmeniz gerekiyor .

Şimdi a ve b belirtmek için a / (a ​​+ b) = p, kritik vuruş şansı olduğundan emin olun. Temiz olan şey, (a + b) 'nin A / (A + B)' nin genel olarak p'ye ne kadar yakın olmasını istediğinizi ölçmesidir.

Örneklemenizi şu şekilde yaparsınız:

izin p(x)p dağılımının olasılık yoğunluk fonksiyonu. Birçok yerde kullanılabilir, ancak GSL'de gsl_ran_beta_pdf olarak bulabilirsiniz.

S = A+B+1
p_1 = p((A+1)/S)
p_2 = p(A/S)

P_1 / (p_1 + p_2) olasılığı olan bir bernoulli dağılımından örnek alarak kritik bir vuruş seçin

Rastgele sayıların çok fazla "kötü çizgi" olduğunu fark ederseniz, a ve b'yi ölçeklendirin , ancak sınırda, a ve b sonsuza giderken, daha önce açıklanan shuffle bag yaklaşımına sahip olacaksınız.

Bunu uygularsanız, lütfen bunun nasıl geçtiğini bana bildirin!


5

Tekrar değerlerini engelleyen bir dağıtım istiyorsanız, basit bir tekrar reddetme algoritması kullanabilirsiniz.

Örneğin

int GetRand(int nSize)
{
    return 1 + (::rand() % nSize);
}
int GetDice()
{
    static int nPrevious=-1;
    while (1) {
        int nValue = GetRand(6);
        // only allow repeat 5% of the time
        if (nValue==nPrevious && GetRand(100)<95)
            continue;
        nPrevious = nValue;
        return nValue;
    }
}

Bu kod, tekrarlama değerlerini% 95 oranında reddederek tekrarlama olasılığını ortadan kaldırır, ancak imkansız değildir. İstatistiksel olarak biraz çirkin, ancak muhtemelen istediğiniz sonuçları üretecektir. Tabii ki, "5 4 5 4 5" gibi bir dağıtımı engellemez. Daha meraklı olabilir ve zamanın ikinci sonunu (diyelim)% 60'ı ve üçüncü son (diyelim)% 30'unu reddedebilirsiniz.

Bunu iyi bir oyun tasarımı olarak önermiyorum. Sadece istediğiniz şeyi nasıl başaracağınızı önermek.


Oyunumdaki kritik vuruş gibi bazı değerlerin% 50'den fazla şansı olamaz, bu yüzden tekrarlamayı hiç engellemiyorum, ancak bu bazı yüzdeler için etkinlik şansını düşürüyor.
Düşünür

4

Ne istediğini gerçekten belli değil. İlk 5 kez çağırdığınızda, 1-5 sayısını rastgele bir sırayla döndürecek şekilde bir işlev oluşturmak mümkündür.

Ama bu gerçekten rastgele değil. Oyuncu, sonraki 5 atakta tam olarak bir 5 alacağını bilecek. Yine de istediğiniz şey olabilir ve bu durumda, sadece kendiniz kodlamanız gerekir. (sayıları içeren bir dizi oluşturun ve bunları karıştırın)

Alternatif olarak, mevcut yaklaşımınızı kullanmaya devam edebilir ve mevcut sonuçlarınızın kötü bir rastgele oluşturucudan kaynaklandığını varsayabilirsiniz. Mevcut numaralarınızda hiçbir şeyin yanlış olmayabileceğini unutmayın. Rastgele değerler rastgele. bazen arka arkaya aynı değerin 2, 3 veya 8'ini alırsınız. Çünkü onlar rastgele. İyi bir rastgele jeneratör sadece ortalama olarak tüm sayıların eşit sıklıkta döndürüleceğini garanti eder.

Tabii ki, kötü bir rastgele jeneratör kullanıyorsanız, sonuçlarınızı çarpıtmış olabilir ve eğer öyleyse, daha iyi bir rastgele jeneratöre geçmek sorunu çözmelidir. (Daha iyi jeneratörler için Boost.Random kütüphanesine bakın)

Alternatif olarak, rastgele işleviniz tarafından döndürülen son N değerlerini hatırlayabilir ve sonucu bunlarla tartabilirsiniz. (basit bir örnek, "yeni sonucun her gerçekleşmesinde, değeri atmamız ve yeni bir tane almamız için% 50 şans var" şeklinde olacaktır.

Tahmin etmek zorunda kalsaydım, "gerçek" rastgelelikle uğraşmanın en iyi seçenek olduğunu söyleyebilirim. İyi bir rastgele jeneratör kullandığınızdan emin olun ve şimdi yaptığınız gibi devam edin.


Aslında, kullandığı işlev boost kütüphanesindeki en iyi RNG ile aynıdır.
Michael Borgwardt

MT "en iyi" değil, son kontrol ettim. Güzel, basit ve hızlı, ancak en iyi dağıtımı üretmiyor. Her neyse, bir milyon rastgele sayı al ve dağılımı kontrol et. Rastgele fonksiyonunuzun aslında size eşit bir dağılım sağlayıp sağlamadığını öğrenin. Değilse, daha iyi bir jeneratör bulun. Eğer öyleyse, ya emin ve zaman zaman oluşan suç sırasını kabul edin ya da hile yapın ve sonuçları daha az rastgele ve daha öngörülebilir hale getirin.
jalf

4

1'den 5'e kadar olan sayıları içeren bir liste oluşturabilir ve bunların rasgeleliğe göre sıralanmasını sağlayabilirsiniz. Ardından oluşturduğunuz listeyi gözden geçirin. Her sayıya en az bir kez girme garantiniz var ... İlk 5'i bitirdiğinizde, sadece 5 sayı daha oluşturun ...


4

Blizzard'ın kullandığı aşamalı bir yüzde sistemi öneriyorum: http://www.shacknews.com/onearticle.x/57886

Genellikle bir RNG yuvarlar ve başarılı olup olmadığını belirlemek için bir değerle karşılaştırırsınız. Bu şöyle görünebilir:

if ( randNumber <= .2 ) {
   //Critical
} else {
   //Normal
}

Yapmanız gereken tek şey temel şansta giderek artan bir artış ...

if (randNumber <= .2 + progressiveChance ) {
   progressiveChance = 0;
   //Critical
} else {
   progressiveChance += CHANCE_MODIFIER;
   //Normal hit
}

Daha süslü olmanız gerekiyorsa, daha fazla eklemek oldukça kolaydır. ProgressiveChance'ın% 100 kritik bir şansı önlemek veya belirli olaylarda sıfırlamak için alabileceği miktarı sınırlayabilirsiniz. Ayrıca progressiveChance + = (1 - progressiveChance) * ÖLÇEK <1 gibi bir ölçekle her bir artışı daha küçük miktarlarda progressiveChance artışına sahip olabilirsiniz.


4

Eğer biraz matematiğe giriyorsanız , muhtemelen Üstel dağılımı deneyebilirsiniz

Örneğin, lambda = 0,5 ise, beklenen değer 2 ise (bu makaleyi okuyun!), Muhtemelen her 2. turda (% 50 gibi, ha? Ancak bu olasılık dağılımı ile, 0. turda (olayın zaten meydana geldiği ve turn_counter'ın sıfırlandığı) kesin olarak özleyeceksiniz (veya herhangi bir şeyin tersini yapacaksınız), bir sonraki dönüşü% 40 gibi bir şansa sahip olacaksınız, yaklaşık% 65 şansı 2. (sonraki sonraki) dönüş, yaklaşık% 80 3. vurmak vb.

Bu dağılımın tüm amacı, birinin% 50 isabet şansına sahip olması ve arka arkaya 3 kez kaçırması durumunda, shurely (% 80'in üzerinde şans ve bir sonraki her turda artar) vurur. Fazla% 50 şansı değiştirmeden daha "adil" sonuçlara yol açar.

% 20 kritik şansınızı değerlendirerek,

  • 1. dönüşü eleştirmek için% 17
  • % 32, önceki turlarda hiçbir eleştirinin gerçekleşmemesi durumunda 2. turu eleştirir.
  • % 45'ini eleştirmek, daha önce yapılmış olanlarda hiçbir eleştirinin olmaması durumunda.
  • % 54'ü daha önceki tüm eleştirilerde herhangi bir eleştiri olmazsa, 4. turu eleştirir.
  • ...
  • Öncekilerin hiçbirinde eleştiride bulunulmuyorsa,% 80'i 8. turda eleştirir.

Hâlâ yaklaşık% 0.2 (bu% 5'e kıyasla), 3 sırayla + 2 sırayla 5 sırayla olma şansı. Ve 4 sonuçta oluşan 4 suçsuz,% 5 5,% 1.5, 6 için% 1.5, 7 için% 0.3, sonuçta ortaya çıkan 8 suçsuz için% 0.07. Bahse girerim "daha adil"% 41,% 32,% 26,% 21 ve% 16.

Umarım hala ölüme sıkılmazsın.


bu benim çözümüme oldukça benziyor, sadece son kritik vuruştan bu yana geçen zamanı "hatırlıyor". Bu çözüm altında, 4 kritik vuruş dizisi, geleceğe ilişkin olasılıklara kadar 1 kritik vuruş dizesiyle aynıdır. Bu nedenle, kritik isabetler iyi ise, bu çözüm aşağı yönlü riskinizi sınırlar, ancak tersinizi değil. Benim çözümüm her ikisini de etkiliyor.
Neil G

Farklı çözümlerin kendi yararları olduğu açıktır. Bu, rastgele bakış açısını bilim açısından temizlemeye odaklanmaktadır. Bu, shuffle çantası veya başka bir şeyden bir şekilde daha iyi olduğu anlamına gelmez. Bu sadece denemeye değer görünen bir çözüm.
Karanlık

3

Kritik olma şansı son N ataklarına bağlıdır. Basit bir şema bir çeşit markov zinciridir: http://en.wikipedia.org/wiki/Markov_chain ama kod yine de çok basit.


IF turns_since_last_critical < M THEN 
   critial = false
   turns_since_last_critical++;
ELSE
   critial = IsCritical(chance);
   IF Critial THEN
       turns_since_last_critica = 0;
   ELSE
       turns_since_last_critica++;
   END IF;
END IF;

Tabii ki matematiğinizi yapmalısınız, çünkü sonuncusundan bu yana yeterli dönüş olduğunu bildiğinizde, bir kritik şansın kritik şanstan daha düşük olması


Etkinin çoğunu sadece son saldırıyı dikkate alarak elde edersiniz. P gözlenen isabet oranı olsun, bir özledim sonra isabet oranı R ve bir isabet sonra isabet oranı R / 2 olsun. Tanım olarak, herhangi bir noktada P = P * R + (1-P) * (R / 2) 'yi vurma şansınız olur. Bu, P = R / (2-R) anlamına gelir
MSalters 27:09

2

OP,

Hemen hemen adil olmasını istiyorsanız, rastgele olmayacaktır.

Oyununuzun sorunu gerçek maç uzunluğudur. Maç ne kadar uzun olursa, o kadar az rastlantısallık görürsünüz (suçlar% 20 olacaktır) ve amaçlanan değerlerinize yaklaşacaktır.

İki seçeneğiniz var, önceki toplara göre saldırıları önceden hesaplayın. Hangi her 5 saldırıda bir kritik alırsınız (sizinki% 20'ye göre), ancak rastgele gerçekleştiği sırayı yapabilirsiniz.

listOfFollowingAttacks = {İsabet, İsabet, İsabet, Bayan, Kritik};

İstediğiniz desen bu. Bu yüzden listeden rastgele seçim yapın, boş olana kadar yeniden oluşturun.

Bu oyunum için oluşturduğum bir desen, yapmasını istediğim şey için oldukça iyi çalışıyor.

ikinci seçeneğiniz, kritik şansınızı artıracak, muhtemelen tüm saldırıların sonunda daha eşit bir sayı göreceksiniz (maçlarınızın oldukça hızlı sona erdiğini varsayarak). Daha az şans, daha fazla RNG elde ettiniz.


2

Muhtemelen normal bir dağılım istediğinizde doğrusal bir dağılıma bakıyorsunuz.

Eğer gençliğinizde D&D oynadığınızı hatırlarsanız, sizden çok sayıda n-taraflı kalıp yuvarlamanız istendi, sonra sonuçları toplayın.

Örneğin, 4 x 6 taraflı kalıbın yuvarlanması, 1 x 24 taraflı zarın yuvarlanmasından farklıdır.


2

City of Heroes aslında tam olarak bu sorunu çözen "streakbreaker" adlı bir tamirciye sahip. Çalışma şekli, dizideki en düşük isabet olasılığı ile ilgili bir uzunluktaki bir dizi kaçırmadan sonra, bir sonraki saldırının bir vuruş olacağı garantilidir. Örneğin, şansınızı% 90'ın üzerinde olan bir saldırıyı kaçırırsanız, bir sonraki saldırınız otomatik olarak vurur, ancak vurma şansınız% 60 gibi düşükse "streakbreaker" ı tetiklemek için art arda birkaç kaçırmanız gerekir (I kesin sayıları bilmiyorum)



0

Değeri ağırlıklandırmaya ne dersiniz?

Örneğin, kritik isabet için% 20 şansınız varsa, kritik isabeti temsil eden bir sayı ile 1 ile 5 arasında bir sayı veya kritik isabet olarak 20 sayı ile 1 ile 100 arasında bir sayı oluşturun.

Ancak, rasgele veya sözde sayılarla çalıştığınız sürece, şu anda gördüğünüz sonuçlardan potansiyel olarak kaçınmanın bir yolu yoktur. Rasgeleliğin doğasıdır.


Ve bu neden bir fark yaratsın ki? Her iki sayı kümesi için de kritik olma şansı tam olarak eşittir.
samjudson

Kesinlikle. % 20 örneği için onun için iki seçenek sunuyorum. Eğer tam sayı yüzdeleri ile uğraşıyorsanız 100 muhtemelen daha iyi çalışır, ancak böyle bir düşünmek istiyorsanız, sadece bir "ölümü" simüle etmeniz gerekir.
Thomas Owens

Sunduğunuz seçenekler tam olarak zaten yaptığı şeydir.
ceejayoz

2
Ne istediği için değil. Rastgele bir sayı üreteci deniyor olsa bile, rastgele olmayan bir sayı üreteci istiyor.
ceejayoz

0

Tepki: "Sorun şu ki, gerçek hayatta çok kötü sonuçlar aldım - bazen oyuncular 5 vuruşta 3, bazen 15 vuruşta hiç yok."

15 vuruşta% 3 ile 4 arasında hiçbir şey alma şansınız var ...


Dakikada 10000 savaşta çevrimiçi 3500 oyuncunuz olduğunda, savaşların% 3'ünde meydana gelen sorun çok yaygın bir sorundur.
Düşünür

Sonra tekrar, savaşların% 3'ünde meydana gelen kötü şans hala kötü şanstır.
MSalters

0

Ben aşağıdaki "rastgele gecikmeli gerileme ölmek" öneriyoruz:

  • Biri in-arraybaşlangıçta 0 ile n-1 arasında bir değerle doldurulmuş iki diziyi koruyun , diğeri (out-array ) boş ) boş olan
  • Bir sonuç istendiğinde:
    • tanımlananlardan rastgele bir değer döndürür değerlerdenin-array
    • bu değeri şuradan taşı in-array içinout-array
    • bir rastgele ( tanımsız! dahil tüm öğeler üzerinde ) öğeyi out-arrayarkadanin-array

Bu, daha büyük olan n'ye daha yavaş tepki gösterme özelliğine sahiptir . Örneğin,% 20 şans istiyorsanız, n'yi 5'e ayarlamak ve 0'a vurmak, n'yi 10'a ayarlamaktan ve 0 ya da 1'e vurmaktan "daha az rastgele" olur ve 1000'den 0'a 199 yapmak neredeyse küçük bir örnek üzerinde gerçek rastgelelikten ayırt edilemez. Sen ayarlamak zorunda kalacak n sizin örneklem büyüklüğü.


0

Her oyuncu için rastgele bir kritik isabet önceden hesaplayın .

// OBJECT
//...
// OnAttack()
//...
c_h = c_h -1;
if ( c_h == 0 ) {
 // Yes, critical hit!
 c_h = random(5) + 1 // for the next time
 // ...
}

0

Sanırım yanlış rasgele dağıtım işlevini kullanıyorsunuzdur. Muhtemelen rakamlar arasında eşit dağılım istemezsiniz. Kritik isabetler 'normal' isabetlerden daha nadir hale gelmek için bunun yerine normal bir dağılım deneyin.

Java ile çalışıyorum, bu yüzden normal bir dağıtım ile rastgele sayılar veren C ++ için bir şey bulabileceğinizden emin değilim ama orada bir şey olmalı.

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.