2012-08-13 11 views
6

मैं सी # के लिए नया हूं।सी # मौका का खेल

मैं

मैं यहाँ मौका प्रणाली का एक खेल बनाने के लिए कोशिश कर रहा हूँ करने के लिए कोशिश कर रहा हूँ क्या

मेरा प्रश्न:

मूल रूप से इस यह कैसे है मैं कैसे पूरा करने के लिए मुझे क्या करना कोशिश कर रहा हूँ करते हैं?

+0

ध्वनि शायद सबसे सरल बात करने के लिए होगा "संभावनाएं" को सारांशित करें और 0 और योग (मौका) के बीच यादृच्छिक करें, फिर उस नंबर पर आने वाली वस्तु को चुनें। क्या यह सही लगता है? –

+0

'रैंडम' क्लास में' अगला (int MaxValue) 'विधि है आपकी मदद कर सकता है। इस पर थोड़ी सी खोज करें। –

उत्तर

5

आपके उदाहरण कोड में एक कठिन बग है: आपने 150/208 और 190/209 लिखा है। यह एक पूर्णांक विभाजन है, और दोनों परिणाम शून्य में परिणाम। आपको लिखा होगा: 150.0/208 और 190.0/209 संकलक को डबल को पूर्णांक के रूप में विभाजित करने के निर्देश देने के लिए।

संपादित करें:
मान लिया जाये कि सिस्टम के RNG सपाट है और इस प्रकार है कि अपनी मेज के रूप में:

[item] [amount] 
0  3 000 000 
25  1 500 000 
50  2 000 000 
75  300 000 
100  10 000 
150  10 000 (no typo) 
    sum = 6820000 

फिर अपने randomizer देख सकते हैं जैसे:

int randomItemNumber = Random.Next(6820000); // 0..6819999 
if(randomItemNumber < 3000000) 
    Console.WriteLine("Aah, you've won the Item type #0\n"); 
else if(randomItemNumber < 3000000+1500000) 
    Console.WriteLine("Aah, you've won the Item type #1\n"); 
else if(randomItemNumber < 3000000+1500000+2000000) 
    Console.WriteLine("Aah, you've won the Item type #2\n"); 
else if(randomItemNumber < 3000000+1500000+2000000+300000) 
    Console.WriteLine("Aah, you've won the Item type #3\n"); 
else if(randomItemNumber < 3000000+1500000+2000000+300000+10000) 
    Console.WriteLine("Aah, you've won the Item type #4\n"); 
else if(randomItemNumber < 3000000+1500000+2000000+300000+10000+10000) 
    Console.WriteLine("Aah, you've won the Item type #5\n"); 
else 
    Console.WriteLine("Oops, somehow you won nothing, the code is broken!\n"); 

विचार है कि आप सभी डाल है एक लूओंग लाइन में आइटम, एक के बाद एक, लेकिन आप उन्हें अपने समूहों में रखते हैं। तो, शुरुआत में पहली तरह के तीन मिलियन हैं, फिर दूसरे प्रकार के ढाई लाख और इतने पर। लाइन में कुल 6820000 आइटम हैं। अब आप यादृच्छिक रूप से 1 से 6820000 (या 0 से 6819 999 तक) संख्या चुनते हैं और इसे लाइन में किसी तत्व के NUMBER के रूप में उपयोग करते हैं।

चूंकि आइटम उनके सही सांख्यिकीय वितरण के साथ लाइन में मौजूद हैं, तो यदि यादृच्छिकरण 1-6820000 FLAT था, तो परिणामस्वरूप 'लॉटरी' में वही वितरण होगा जैसा आप चाहते थे।

एकमात्र चाल समझाने के लिए छोड़ दी गई है, यह अनुमान लगाने के लिए कि किस आइटम को चुना गया था। यही कारण है कि हमने वस्तुओं को समूहों में रखा था। 3000000 वस्तुओं का पहला भाग पहला प्रकार है, इसलिए यदि संख्या 3000000 से कम थी तो हमने पहले प्रकार को मारा। यदि उससे अधिक, लेकिन अगले 1500000 (4500000 से कम) से कम है तो दूसरा प्रकार हिट है .. और इसी तरह।

+0

मैंने ऐसा किया है और वह कोड अब काम करता है। धन्यवाद। लेकिन क्या आपको लगता है कि मैं जो करने की कोशिश कर रहा हूं उसके लिए पर्याप्त है? मैं आंकड़ों के साथ इतना अच्छा नहीं हूँ। – Jack

+0

आप एक अच्छे तरीके से हैं। मैंने 'टैब्यूलर वितरण के साथ जनरेटर' कैसे काम करता है इस पर एक लंबी व्याख्या जोड़ा है। कृपया मेरी पोस्ट दोबारा पढ़ें। – quetzalcoatl

+0

यह बहुत अच्छी तरह से काम करता प्रतीत होता है। मैंने थोड़ी देर के लिए इसका प्रयोग किया है। लेकिन मुझे कुछ चीजों के बारे में आश्चर्य है, क्षमा करें अगर यह बहुत सारे प्रश्न हैं। ** 1 ** - फ्लैट यादृच्छिकरण से आपका क्या मतलब है? ** 2 ** - क्या इससे कोई फर्क पड़ता है कि आखिर में सभी रकम 100% तक खत्म हो जाती है? ** 3 ** - हमें किसी भी प्रतिशत मौके का उपयोग करने की आवश्यकता क्यों नहीं है? क्या इससे कोई फर्क पड़ता है अगर हम नहीं करते? ** 4 ** - क्या मैं वैसे भी इस कोड का परीक्षण कर सकता हूं यदि मुझे पहले से ही संभावना है? उदाहरण के लिए एक्स प्राप्त करने का मौका 80% है, इसलिए मैं इस कोड को 50 बार लूप में चलाता हूं और फिर देखता हूं कि यह काम करता है या नहीं। उदाहरण के लिए, एक्स को लूप में लगभग 80% बार प्रदर्शित किया जाना चाहिए, या? – Jack

0

मैं अपने अनुप्रयोग में कुछ इसी तरह किया था और आपकी समस्या का यह नीचे में परिवर्तित कर देंगे: छद्म कोड में:

  • योग अप सभी मान (कुल प्राप्त करने के लिए)
  • 0 के बीच एक यादृच्छिक मूल्य प्राप्त करें और योग
  • सभी आइटमों के माध्यम से लूप सभी आइटमों को संक्षेप में उस आइटम तक
  • यादृच्छिक संख्या तक पहुंचने पर, वह आइटम मूल्य से संबंधित है।

वर्ग आइटम के रूप में निम्नानुसार कुछ महत्वहीन लाइनों को हटा दिया और कहा कि //

public class Items : List<Item> 
{ 
    public Items() 
    { 
     Add(new Item(0, 3000000)); 
     Add(new Item(25, 1500000)); 
     Add(new Item(50, 2000000)); 
     // etc 
    } 

    /// <summary> 
    /// Returns a random item based on value. 
    /// </summary> 
    /// <returns></returns> 
    public Item GetRandomItem() 
    { 
     var sum = this.Sum(item => item.Value); 
     var randomValue = new Random().Next(sum); 

     // Iterate through itemsuntil found. 
     var found = false; 
     var itemIndex = 0; 
     var visitedValue = 0; 
     while (!found) 
     { 
      var item = this[itemIndex]; 
      if ((visitedValue + item.Value) > randomValue) 
      { 
       found = true; 
      } 
      else 
      { 
       itemIndex++; 
       visitedValue += item.value;     
      } 
     } 

     return this[itemIndex];   
    } 

साथ टिप्पणी मद वर्ग नाम और मूल्य के लिए एक प्लेसहोल्डर से ज्यादा कुछ नहीं है लग रहा है (।

यह लंबे समय से लग रहा है, लेकिन यह कुछ लाभ हैं:

  • एक मूल्य परिवर्तन, योग स्वचालित रूप से गणना की जाती है।
  • कोई आइटम जोड़ते समय, केवल एक पंक्ति को बदलने की आवश्यकता है।
1

जैसा कि अन्य ने कहा है, आपके कोड में एक पूर्णांक विभाजन बग है।

किसी भी मामले में, आप देखना चाहते हैं: उलटा रूपांतरण नमूनाकरण।

असल में, यह आपको एक समान यादृच्छिक संख्या (जो अधिकांश पीआरएनजी आपको देता है) लेने और किसी भी वितरण से इसे यादृच्छिक नमूना में बदलने की अनुमति देता है। ऐसा करने के लिए, आपको लक्ष्य वितरण के सीडीएफ का उपयोग करने की आवश्यकता है।

संदर्भ & उपयोगी पृष्ठों:

[CiteHistory Record]

संपादित: मैं वास्तव में बहु वितरण वितरण नहीं, वर्गीकृत वितरण का मतलब था। ये दो वितरण अक्सर स्वीकार किए जाते हैं (विशेष रूप से मेरे क्षेत्र में), लेकिन अंतर महत्वपूर्ण है। दो वितरण केवल तभी समकक्ष होते हैं जब बहु-वितरण वितरण n = 1 (यानी एक परीक्षण) के साथ पैरामीटर किया जाता है।

0

विभाजन से शून्य को रोकने के लिए एक विभाजक एक डबल होना चाहिए। संभावना आप 100% (या 1) के लिए उन्हें cumulate करने की जरूरत है की गणना करने के लिए:

//  Element  - Probability  - Cumulative Probability 
//  Item100  10000/6820000  0.001466275659824 
//  Item75  300000/6820000  0.0439882697947214 + 0.001466275659824 
//  Item50  2000000/6820000  0.2932551319648094 + 0.0454545454545454 
//  Item25  1500000/6820000  0.219941348973607 + 0.3387096774193548 
const double Item100 = 0.001466275659824; 
const double Item75 = 0.0454545454545454; 
const double Item50 = 0.3387096774193548; 
const double Item25 = 0.5586510263929618; 

int getRandomItem(Random rnd) 
{ 
    double value = rnd.NextDouble(); 
    if (value <= Item100) 
    { 
     // use one of both possible items (100 or 150) 
     int which = rnd.Next(0, 2); 
     return which == 0 ? 100 : 150; 
    } 
    else if (value <= Item75) 
     return 75; 
    else if (value <= Item50) 
     return 50; 
    else if (value <= Item25) 
     return 25; 
    else 
     return 0; 
} 

आप इसे कैसे प्रयोग करेंगे:

var rnd = new Random(); 
var items = new List<int>(); 
for (int i = 0; i < 100; i++) 
    items.Add(getRandomItem(rnd)); 
Console.Write(string.Join(Environment.NewLine, items)); 

ध्यान दें कि मैं यादृच्छिक उदाहरण पुन: उपयोग। अगर मैं इसे लूप में बनाउंगा, तो "यादृच्छिक मूल्य एक ही समय के साथ बीजित होगा क्योंकि

+0

मैंने पहले से ही इस तरह कुछ करने की कोशिश की, समस्या यह थी कि 25 कभी प्रदर्शित नहीं हुआ, बल्कि 50 ने हर समय लिया। – Jack

+0

@ जैक: मुझे लगता है कि उस व्यवहार का कारण यह था कि आप हमेशा एक लूप में एक नया यादृच्छिक उदाहरण इस्तेमाल करते थे। यादृच्छिक वर्तमान समय के साथ बीजित किया जाएगा। एक लूप में यह हमेशा एक ही समय होगा, क्योंकि आप हमेशा एक ही "यादृच्छिक" मान प्राप्त करेंगे। यही कारण है कि मैं यादृच्छिक उदाहरण विधि के पैरामीटर के रूप में पास करता हूं। आपको लूप के बाहर यादृच्छिक उदाहरण बनाना चाहिए और हमेशा इसका पुन: उपयोग करना चाहिए। एक और विकल्प कक्षा में यादृच्छिक सदस्य चर बनाने के लिए होगा। –

+0

@ जैक: उपरोक्त प्रदर्शन करने के लिए मेरे उत्तर को संपादित किया, संभावनाओं को भी बदल दिया क्योंकि उन्हें संचयी होने की आवश्यकता है। –

0

ऐसा कुछ आपको करना चाहिए। शायद दुनिया में सबसे अच्छा उदाहरण नहीं है, लेकिन यह पर्याप्त होना चाहिए:। जैसे आप एक यादृच्छिक संख्या पैदा करते हैं और बेतरतीब ढंग से एक सूची है, जहां सूची में प्रत्येक आइटम उठाया जा रहा है की एक भारित मौका है में से एक आइटम लेने के लिए कोशिश कर रहे हैं

class Item 
{ 
    public string Name { get ; private set ; } 
    public int Amount { get ; private set ; } 

    public Item(string name , int amount) 
    { 
     if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("name") ; 
     if (amount < 0) throw new ArgumentException("amount") ; 

     this.Name = name ; 
     this.Amount = amount ; 

     return ; 
    } 
} 
static void Main(string[] args) 
{ 
    Random rng = new Random() ; 
    Item[] items = { new Item("item--0" , 3000000) , 
        new Item("item-25" , 1500000) , 
        new Item("item-50" , 2000000) , 
        new Item("item-75" , 300000) , 
        new Item("item-100" , 10000) , 
        new Item("item-150" , 10000) , 
        } ; 
    int total = items.Sum(x => x.Amount) ; 

    for (int i = 0 ; i < 100 ; ++i) 
    { 
     int r = rng.Next(0, total) ; // get a random integer x such that 0 <= x < total 
     int n = 0 ; 
     Item selected = null ; 
     int lo = 0 ; 
     int hi = 0 ; 
     for (int j = 0 ; j < items.Length ; ++j) 
     { 
      lo = n ; 
      hi = n + items[j].Amount ; 
      n = hi ; 

      if (r < n) 
      { 
       selected = items[j] ; 
       break ; 
      } 

     } 
     Console.WriteLine("iteration {0}. r is {1} <= {2} < {3}. Selected item is {4}" , 
      i , 
      lo , 
      r , 
      hi , 
      selected.Name 
      ) ; 


    } 

    return; 
} 
संबंधित मुद्दे