2011-10-12 8 views
9

में यादृच्छिकता की गुणवत्ता में सुधार करना आप एक कालकोठरी में खड़े हैं। आपके सामने, स्तर 5 नेरड का एक समूह है। वे चाहते हैं कि आप उनके लिए एक डंगऑन और ड्रेगन अभियान चलाएं।उद्देश्य-सी

आप कुछ सत्र चलाते हैं, आपके खिलाड़ी स्तर पर हैं, और चीजें आम तौर पर सूजन होती हैं। हालांकि, मुकाबला थोड़ा धीमा है। आप उद्देश्य-सी के अपने +4 हेलबर्ड को खींचने का निर्णय लेते हैं और युद्ध में एनपीसी पासा रोलिंग स्वचालित करने के लिए एक आईपैड ऐप लिखते हैं। नरक आप की ओर बढ़ते हैं, खतरनाक रूप से। "एल्गोरिदमिक रूप से जेनरेट की गई संख्याएं," एक झुकाव, "सच यादृच्छिकता का खोखला अनुकरण है! आप हमारे पवित्र अभियान को अपने छद्म यादृच्छिक गंदगी से दबाने नहीं देंगे!"

आप उसे मनाने के लिए रोल करते हैं कि arc4random_uniform() पर्याप्त से अधिक है ... और असफल। बेवकूफ सच यादृच्छिकता से कम कुछ भी के लिए व्यवस्थित होगा। वे आपको कैदी पकड़ते हैं क्योंकि आप अपने मैकबुक से बेहद चिपकते हैं, और एक वर्ग लिखते हैं जो random.org से डेटा पुनर्प्राप्त करता है।

NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 
[formatter setDateFormat:@"YYYY/YYYY-MM-dd"]; 
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@%@", 
       @"http://www.random.org/files/", 
       [formatter stringFromDate:[NSDate date]], 
       @".bin"]]; 
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest: 
       [NSURLRequest requestWithURL:url] delegate:self]; 

एक बार डेटा सहेजा गया है, तो आप डाउनलोड बाइट्स से यादृच्छिक संख्या, 0-255 की पीढ़ी की अनुमति देते हैं।

-(int) nextInt:(int)start end:(int)end 
{ 
    int upperBound = end - start + 1; 
    unsigned char result; 
    int maxModulo = 255 - (255 % upperBound); 
    do { 
     NSRange range = {index, sizeof(char)}; 
     [randos getBytes:&result range:range]; 
     index += sizeof(char); 
    } while (result > maxModulo); //avoid modulo bias 
    result = result % upperBound; 
    result += start; 
    return result; 
} 

नरक संतुष्ट प्रतीत होते हैं, लेकिन एक नया दुश्मन प्रकट होता है: एक और डंगऑन मास्टर! वह मांग करता है कि आप उसे अपने उद्देश्यों के लिए सॉफ्टवेयर की एक प्रति दें। समस्या स्पष्ट है - यदि आप दोनों उसी दिन से random.org डेटा का उपयोग करते हैं, तो आपको पासा रोल का एक ही सेट मिल जाएगा!

तो मेरा प्रश्न इस प्रकार है: मैं random.org डेटा को कैसे संशोधित कर सकता हूं जैसे कि यह "वास्तविक यादृच्छिकता" जैसी कुछ चीज़ बनाए रखेगा लेकिन कार्यक्रम के प्रत्येक उदाहरण में अलग होगा? मैं एक समाधान की कल्पना कर सकता हूं जो उपयोगकर्ता (like TrueCrypt does) से कुछ (purportedly यादृच्छिक) टचपैड आंदोलनों को प्राप्त करने में सक्षम होगा, लेकिन एक बार जब मैं स्थिर रहता हूं तो मुझे यकीन है कि वहां से कहाँ जाना है। किसी भी तरह से मेरे निरंतर उपयोग कर सभी संख्या हैश? इससे बड़ी संख्या में उत्पादन होगा; क्या मैं सांख्यिकीय रूप से ठीक हूं अगर मैं बस पासा रोल के नीचे छोटा या छोटा कर दूं? मुझे नहीं पता कि एल्गोरिदमिक कदम क्या हैं।

उत्तर

5

मेरे पास एक अलग समाधान है। एक जो हर किसी को संतुष्ट करेगा, मुझे उम्मीद करनी चाहिए। हर बार जब आप एक नया मर रोल तैयार करना चाहते हैं, तो इसे इस तरह से करें:

एक प्रगति पट्टी प्रस्तुत करें, और उपयोगकर्ता को डिवाइस को हिलाएं।

  • प्रतीक्षा करते समय, त्वरण डेटा को उपयुक्त रूप से फ़िल्टर करें (कुछ कम पास आईआईआर अच्छी तरह से करना चाहिए) और एक निश्चित दी गई परिमाण के साथ स्पाइक्स की तलाश करें। Hysteresis का उपयोग कर गणना स्तर परिवर्तन। एक प्रगति पट्टी दिखाएं जो हिलाने की मात्रा दिखाती है।
  • उसी समय, कच्चे त्वरण डेटा को एक उपयुक्त क्रिप्टोग्राफ़िक हैश फ़ंक्शन पर फ़ीड करें, कहें, SHA-2।

जब प्रगति पट्टी दाईं ओर सभी तरह से हो जाती है, पासा रोलिंग की आवाज बजाएं और मर मूल्यों को उत्पन्न करने के लिए हैश फ़ंक्शन (256 बिट्स) के आउटपुट का उपयोग करें। यह 59d20 से अधिक के लिए काम नहीं करेगा। आप हैश फ़ंक्शन स्थिति को अगले मर रोल में इनपुट के रूप में भी सहेज सकते हैं।

यहां आप उन नरों को बताते हैं: मर रोल किसी भी तरह से एल्गोरिदमिक अनुमानित नहीं है। मरने के रोल के मूल्य को निर्धारित करने में उपयोग की जाने वाली एकमात्र जानकारी यह है कि आप डिवाइस को कैसे हिलाते हैं, जो असली पासा के लिए भी सच है। सिद्धांत आप डिवाइस को दो बार उसी तरह हिला सकते हैं, जैसे कि सिद्धांत एक उच्च कुशल जुआरी असली पासा रोल कर सकता है जिससे कि वह जिस तरह से चाहता है उसे तैयार कर सके।

आउटपुट का उपयोग कैसे करें: आपके पास यादृच्छिक डेटा के 256 बिट्स हैं, और मरने के रोल प्राप्त करना चाहते हैं।

struct bits { 
    unsigned data[8]; 
    unsigned pos; 
}; 

// Get next n bits, or -1 if out of entropy. 
int get_bits(struct bits *b, int n); 

// Roll an n-sided die, or -1 if out of entropy 
int uniform(struct bits *b, int n) 
{ 
    int nbits, x; 
    for (nbits = 0; (1 << nbits) < n; ++nbits); 
    do { 
     x = get_bits(b, nbits); 
     if (x < 0) 
      return -1; 
    } while (x >= n); 
    return x + 1; 
} 

यह फ़ंक्शन आपके मरने के रोल के लिए एक समय में एन्ट्रॉपी के कुछ बिट्स को टुकड़ा करके काम करता है। तो एक डी 8 के लिए, आप 3 बिट्स का टुकड़ा करते हैं और परिणाम का उपयोग करते हैं। डी 20 के लिए, आप डी 32 के लिए 5 बिट्स को टुकड़ा करते हैं, और यदि परिणाम 20 से अधिक हो तो फिर से रोल करें। यदि आप दिए गए मर रोल के लिए एंट्रॉपी (असंभव, लेकिन संभव) से बाहर निकलना चाहते हैं, तो मैं एक "मरने का सुझाव देता हूं जैक "संदेश और उपयोगकर्ता को शेष पासा के लिए कुछ और हिलाकर पूछना।

फुटनोट: जब तक आप बड़ी संख्या में पासा रोल नहीं करते हैं, तब तक आप एन्ट्रॉपी से बाहर निकलने की संभावना बहुत कम होती है। 256 बिट्स बहुत है। एंट्रॉपी से बाहर निकलने का मौका देने से पहले 24 डी 20 लगते हैं, यहां तक ​​कि 1% तक पहुंच जाता है।

+0

हां! यह सही रहेगा। हमें क्रिप्टोग्राफी मिलती है और हमें आउटपुट पर नियंत्रण रखने की भावना मिलती है। अन्य उत्तरों स्पष्ट करते हैं कि मेरे खिलाड़ी वास्तव में नहीं समझते हैं कि यादृच्छिक संख्याएं कैसे उत्पन्न होती हैं, लेकिन उन्हें क्यों सिखाएं जब मैं उन्हें खुश कर सकता हूं? – iameli

+1

इससे भी बेहतर, क्या उपयोगकर्ता यह सब करते हैं और बेहतर "यादृच्छिक" संख्या जनरेटर जैसे arc4random या SecRandomCopyBytes का उपयोग करते हैं। सिस्टम में बेहतर और अधिक एन्ट्रॉपी स्रोत हैं। तो, यह सोचकर कि एक "घर उगाया गया" समाधान अच्छी तरह से पेश किए गए पेशेवर डिजाइन सिस्टम से बेहतर हो सकता है, वह सिर्फ पागल है। – zaph

+0

@ कोकोआफू: मुझे नहीं लगता कि आप इस एप्लिकेशन के उद्देश्य को समझते हैं। इसके दो उद्देश्य हैं: 1) एक समझदार, मूर्त तंत्र है जिसे आसानी से समझाया जा सकता है, 2) आरपीजी के लिए पर्याप्त संख्याएं उत्पन्न करें। यह सोचकर कि घर पर कुछ दोस्तों के साथ आरपीजी खेलने के लिए आपको एक अनुभवी, पेशेवर रूप से डिजाइन किए गए पीआरएनजी की जरूरत है, वह सिर्फ पागल है। (एक साइड नोट के रूप में, अधिकांश आरपीजी खिलाड़ियों में काफी चौंकाने वाली पूर्वाग्रहों के साथ पासा होता है।) इसके अलावा, एसएचए -2 एक उत्कृष्ट पीआरएनजी बनाता है। –

1

डाउनलोड बिन-files.txt और बेतरतीब ढंग से प्रविष्टियों में से एक चुनना (जैसे, NSDate timeIntervalSinceNow सापेक्ष प्रविष्टियों की संख्या txt फ़ाइल में उपयोग करें)। फिर उस फ़ाइल को डाउनलोड करें।

आगे, एक बार जब आप फ़ाइल डाउनलोड करते हैं, तो एक अलग यादृच्छिकता के आधार पर कुछ ऑफ़सेट शुरू करें।

4

यह वास्तव में एक उत्तर नहीं है और एक टिप्पणी है, लेकिन यह लंबा हो गया और यहां यह है।

मैं एक समाधान है कि उपयोगकर्ता से कुछ (कथित रूप से यादृच्छिक) टचपैड आंदोलनों हो रही करना पड़ेगा,

ध्यान दें कि arc4random_stir()/dev/urandom से पढ़ता है कल्पना कर सकते हैं, को देखने के the man page। तो यह खुद को "पर्यावरण" के साथ बीज देता है।

या, एक रेडियोधर्मी स्रोत और एक गीजर-काउंटर खरीद यह यूएसबी से कनेक्ट, और उत्पन्न काउंटर के पढ़ने के आधार पर यादृच्छिक संख्या। परमाणु क्षय क्वांटम यांत्रिक रूप से यादृच्छिक है।

+0

बस मैन पेज से arc4random() का उपयोग करें: "arc4random() का उपयोग करने से पहले arc4random_stir() को कॉल करने की आवश्यकता नहीं है, क्योंकि arc4random() स्वचालित रूप से स्वयं को प्रारंभ करता है।" – zaph

2

क्रिप्टोग्राफिक रूप से सुरक्षित यादृच्छिक बाइट्स की एक सरणी उत्पन्न करता है।

int SecRandomCopyBytes (
    SecRandomRef rnd, 
    size_t count, 
    uint8_t *bytes 
); 

Apple Randomization Services Reference Docs

या बस का उपयोग arc4random(), यह यह स्वचालित रूप से/dev/urandom से वरीयता प्राप्त है यादृच्छिक के रूप में पास के रूप में देखा जा सकता है।