Bir piramit yapıda rastgele oyuncu güçlerini oluşturmak (PHP)

6 Cevap php

Bir online oyun (MMORPG) için rastgele mukavemet değerlerine sahip karakterler (oyuncular) oluşturmak istiyorum. Güçlü karakterler az, bu tür var olmalıdır, vardır.

Örnek:

  • 12.000 gücü 1 oyuncu
  • 10.500 gücü 2 oyuncu
  • 8,500 gücü 3 oyuncu
  • 6.000 gücü 4 oyuncu
  • 3.000 gücü 5 oyuncu

Aslında, ben 1,1-9,9 yüzen, ilerici gücü değerleri gerekir ama bu örnek için tamsayı güçlü ile açıklamak daha kolay oldu.

Eğer PHP bu kodu nasıl bir fikriniz var mı? Tabii ki, ben rastgele sayı üretmek için () mt_rand gerekir. Ama nasıl bu piramit yapıyı elde edebilirsiniz?

Ne işlevi nedir? Kök fonksiyonu, üstel fonksiyon, güç işlevi veya logaritma fonksiyonu?

Şimdiden teşekkürler!

Grafiğin bu gibi görünmelidir:

Pyramid graph

6 Cevap

Böyle bir logaritmik fonksiyonu kullanarak tarif olarak bir dağıtım taklit edebilirsiniz. Aşağıdaki 1.1 ve 9.9 arasında rastgele bir mukavemet değeri dönecektir:

function getRandomStrength() 
{
    $rand = mt_rand() / mt_getrandmax();
    return round(pow(M_E, ($rand - 1.033) / -0.45), 1);
}

1000 çalışan üzerinde Dağılımı (burada S katlı gücü değeri):

S | Count
--+------
1 -  290
2 -  174
3 -  141
4 -  101
5 -  84
6 -  67
7 -  55
8 -  50
9 -  38

Note:

Bu cevap (çünkü yuvarlaklaşma önce dahil değildi) 1.1 bir mukavemet değerine dahil etmek ve mt_getrandmax() işlevin adını düzeltmek için güncellendi

Bunu yapmanın kolay yolu rastgele bir sayı nereye gitmeli için 'bantlar' sağlamak olacaktır. Eğer olabilir böylece örnekte, 15 oyuncu var:

rand < 1/15, highest strength
1/15 < rand < 3/15, second highest
3/15 < rand < 6/15, third highest
6/15 < rand < 10/15, fourth highest
10/15 < rand < 15/15, lowest strength

Ayrıca sonraki en yüksek içine toplamıştır duyacağız bandı dolu olduğunda ve bu (ayrı alt gruptan, sonraki en düşük mevcut bant içine toplamıştır edilmektedir izin, her grubun bir 'max' numarası ile böyle bir işlevi parametreleştirilmesi olabilir ) rasgele bir dağılımı ile, her biri sadece belirli sayıda sağlamak.

Benim yorumlardan ekleme edit:

Bir kayan aralık piramit yapısı almak için en iyi fonksiyon büyük olasılıkla bir logaritma olacaktır. Formülü:

11 - log10(rand)

Böyle aralıkları verecek gibi (log10 tabanına 10 ile bir logaritma olmak) ile çalışacak:

1 < rand < 10 = 9 < strength < 10
10 < rand < 100 = 8 < strength < 9
100 < rand < 1000 = 7 < strength < 8
etc.

ama rand rastgele bir sürü (en rastgele jeneratörler yönetebilirsiniz daha fazla) gerektirecek 1'den 10 ^ 10 arasında gerekir. Birlikte bazı çarpma olabilir aralık bu tür rastgele bir sayı elde etmek. 3 rasgele sayılar yönetmek olabilir:

11 - log10(rand1 * rand2 * rand3)

rand1 aralığı 1-10000 ve rand2 olan ve aralık 1-1000 sahip rand3 ile. Bu uzak biraz (ben inanıyorum merkezinde numaraları olması daha muhtemeldir) olsa doğru bir piramit dağılımını eğmek olur bu yüzden uygun olmayabilir.

workmad3 bunun başlangıcını aşağı var, ben düşünüyorum, ama bir nokta vardır - onlar tam konum olsun veya olmasın kova boyutları izlemek gerekir ve. Bir rasgele sayı üreteci garanti vermez. Eğer kova değerleri (strenghs) ve boyutları (insan sayısı) atamanız gerekir, ve rastgele içine düşürmeyin hangi kepçe size izin vereceğim - Bir sonraki daha düşük olduğu bir dolu ise, 'taşma'.

Belirli bir güç değeri için kova boyutlarını atamak gibi, bu zor biraz (ve ben gerçekten de çalışıyoruz ne düşünüyorsunuz). İstediğiniz dağıtım özellikleri önemlidir. Eğer doğrusal bir damla (piramit şekli ima ki), formun bir çizgi isterseniz

strength = max_strength - m(number_characters)

çalışmaya devam eder. M değeri değişen hat düşüyor hızını değiştirmek istiyorsunuz, ve temelde toplam karakter, maksimum sayısını sınırlayacaktır. Eğer düşüyorlar mukavemet değerleri için daha sofistike bir yol arıyorsanız, bir parabolik veya hiperbolik eğri kullanabilirsiniz - bu biraz daha karmaşık, ama size çok farklı özelliklere verir.

Böyle bir şey

<?php

$rand = rand(1,10);

switch ($rand) {

case 1:
echo "band 1";
break;

case 2:
case 3:
echo "band 2";
break;

case 4:
case 5:
case 6:
echo "band 3";
break;

default:
echo "band 4";
break;

}

?>

Band 1 bant 4 zayıf olmak, güçlü olmak.

Tabii bu temel, bu yerine kodlanmış anahtarlarının döngüler kullanmak refactor isterim, ama fikir olsun :)

Bu durumda yüzdeleri kullanmak için muhtemelen en kolay.

Lütfen örneklerle yaklaşık (daha sonra kullanım kolaylığı için bir dizi dönüştürülür) olacaktır:

$strength[1] = .3;  // start with a key of 1
$strength[2] = .26;
$strength[3] = .21;
$strength[4] = .15;
$strength[5] = .08;

Bu şekilde, mt_rand() kullanarak rasgele bir sayı üretmek ve 0 ile 1 arasında bir sayı elde etmek için mümkün olan maksimum değeri tarafından bölebilirsiniz:

$rand = mt_rand() / mt_getrandmax(); // rand is some random value between 0 and 1

Sonra her durumda izole etmek için bir foreach deyimi kullanabilirsiniz:

$comparisonPercentage = 1;
$selectedLevel = count($strength); // covers the case where mt_rand() returns 0
foreach($strength as $level => $currentPercentage) 
{
    $comparisonPercentage -= $currentPercentage;
    if ($rand >  $comparisonPercentage) 
    {
        $selectedLevel = $level;
        break;
    }
}

// $selectedLevel contains the level you need...

Eğer bu şekilde yaparsanız, sadece yüzdeleri ile keman gerekiyorsa $strength dizisini değiştirmek zorunda.

onun 0 ile 12000 arasında, 12000 ve 22500 atamak 2 vb arasındaki, gücünü 1 atarsanız, 0 ile 40000 arasında rastgele bir sayı üretmek

Edit: 0 ile 10 arasında ilerici değerler 0 ile 100 arasında rastgele bir sayının karekökünü kullanmak için, sonra çıkartmak ise 10 ila

  • rand -> mukavemet
  • 0-1 -> 9.9 -> 9 (% 1)
  • 2-4 -> 9 -> 8 (% 2)
  • ...
  • 81-100 -> 1 - 0 (19%)

1.1 ve 9.9 arasındaki sonuçlar için formül pseudocode) olacaktır

gücü = 10 - sqrt (rand (1 .. 79))