मेरे संदर्भ में इस यादृच्छिक संख्या पीढ़ी को कैसे सुधारें?


11

मेरे गेम में स्क्रीन के ऊपर एक शब्द है, ऊपर से अक्षरों की बारिश हो रही है और उपयोगकर्ता को शब्द पूरा करने के लिए अक्षरों को छूना है।

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

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

मैंने निम्नलिखित तरीकों की कोशिश की है:

  1. शब्द में सभी अक्षरों का पता लगाएं (शब्द हमेशा 6 अक्षर लंबा होता है), लंबाई 6 के अनुक्रमित की सरणी उत्पन्न करते हैं, अक्षर -2 के अक्षर से यादृच्छिक संख्या के लिए सरणी के प्रत्येक सूचकांक को असाइन करें + और अंत में यादृच्छिक रूप से एक सूचकांक चुनें दिखाने के लिए सरणी से।

  2. एक चयनकर्ता चर है जिसका मान सीमा [0..2] में है, यादृच्छिक रूप से उत्पन्न होता है, यदि चयनकर्ता == 0 तो उन अक्षरों का पता लगाएं जो शब्द बनाते हैं और एक अक्षर को यादृच्छिक रूप से उठाते हैं, अन्यथा यादृच्छिक रूप से az से कोई वर्णमाला प्राप्त करते हैं।

इन दोनों तरीकों ने मुझे कोई मदद नहीं दी है। अगर आप मेरी मदद कर सकते हैं तो मुझे बहुत खुशी होगी।

इसे पढ़ने के लिए धन्यवाद, मुझे आशा है कि आप प्रश्न को समझ गए हैं और मैं प्रतिक्रिया की प्रतीक्षा कर रहा हूं।


2
"इन दोनों तरीकों ने मुझे कोई मदद नहीं दी है " क्यों नहीं? इन तरीकों से क्या काम नहीं हुआ?
Vaillancourt

मुझे पता नहीं क्यों लेकिन अभी भी 1 मिनट की तरह बहुत समय लग रहा है सभी आवश्यक अक्षर प्राप्त करने के लिए।
दनियाल आजम

@DaniyalAzram आपको शायद आवृत्ति को कुछ और बढ़ाना चाहिए यदि ये अक्षर अक्सर पर्याप्त दिखाई नहीं दे रहे हैं, क्योंकि यह लगता है कि आपकी समस्या क्या है।
JFA

जवाबों:


21

आप वास्तव में एक यादृच्छिक वितरण नहीं चाहते हैं। मैं इसे स्पष्ट रूप से इंगित करता हूं, क्योंकि जिसे हम डिजाइन के लिए "यादृच्छिक" मानते हैं, आमतौर पर सही यादृच्छिकता नहीं होती है।

अब, इसे ध्यान में रखते हुए, आइए कुछ ट्विकिंग वैल्यूज़ जोड़ते हैं - ये वो चीज़ें हैं, जिनके साथ आप तब तक फील करेंगे, जब तक कि डिज़ाइन "सही" न हो जाए।

ChooseLetter() {
    const float WordLetterProbability = 0.5f;
    if (Random.NextFloat01() < WordLetterProbability) {
        // Pick a random letter in the word
    }
    else {
        // Pick a random letter *not* in the word
    }
}

संभावना इस बात को नियंत्रित करती है कि SelectLetter को दिए गए कॉल की संभावना आपको एक शब्द पत्र कैसे देगी - 0.5 पर, आपको हर दूसरे समय में लगभग एक शब्द पत्र मिलेगा। 0.25 पर, चार में से एक शब्द अक्षर होगा, आदि।

यह अभी भी थोड़ा सरलीकृत है - क्योंकि यादृच्छिकता है, ठीक है, यादृच्छिक , आपके पास वास्तव में इस बात की कोई गारंटी नहीं है कि आप शब्द अक्षरों के बीच कब तक जाएंगे। (सिद्धांत में, आप एक शब्द अक्षर के बिना हमेशा के लिए जा सकते हैं , यह सिर्फ बहुत ही संभावना नहीं है।) इसके बजाय, हम हर बार एक शब्द नहीं मिलने पर एक शब्द पत्र की संभावना बढ़ाने के लिए एक कारक जोड़ सकते हैं:

const float BaseWordLetterProbability = 0.5f;
const float WordLetterProbabilityIncrease = 0.25f;
float WordLetterProbability = BaseWordLetterProbability;
ChooseLetter() {
    if (Random.NextFloat01() < WordLetterProbability) {
        // Pick a random letter in the word
        WordLetterProbability = BaseWordLetterProbability;
    }
    else {
        // Pick a random letter *not* in the word
        WordLetterProbability += WordLetterProbabilityIncrease;
    }
}

ठीक है, इसलिए अब हम कभी भी एक शब्द के अक्षर के बिना दो से अधिक अक्षर नहीं जाते हैं। (क्योंकि, दो यादों के बाद, हमारे पास एक शब्द पत्र प्राप्त करने की 1.0 संभावना है।)

अंत में, हमें इस बात पर विचार करने की आवश्यकता है कि किसी शब्द में अक्षर का चयन कैसे किया जाता है। खिलाड़ी को उन पत्रों को प्रदान करने के लिए जिनकी उन्हें वास्तव में आवश्यकता होती है, हमें सेट से पत्र निकालने की आवश्यकता होती है क्योंकि वे उन्हें प्राप्त करते हैं।

उदाहरण के लिए, यदि शब्द "परीक्षण" है, और खिलाड़ी के पास पहले से ही 's' है, तो हम उन्हें एक और 's' नहीं देना चाहते, क्योंकि उन्हें इसकी आवश्यकता नहीं है!

यहाँ से, बाकी आपके डिज़ाइन को फिट करने के लिए ट्विकिंग कर रहा है।


वाह! तुम भी उस के साथ कैसे आए ?: पी मैं कल सुबह आपकी विधि का परीक्षण करूंगा और मुझे लगता है कि यह काम करेगा, मैं इस मेथोड का परीक्षण करने के बाद एक बार और प्रतिक्रिया दूंगा। ऐसे उत्तर के लिए आपका बहुत-बहुत धन्यवाद।
दनियाल आजम

4
सांख्यिकी! या तो एक गेम डिजाइनर या प्रोग्रामर के रूप में, आँकड़े बहुत सीखने लायक हैं। बहुत कम से कम, संभावना की समझ (और उन्हें कैसे संयोजित करें) अत्यंत उपयोगी है।
ACEfanatic02

1
उसी बात का सुझाव देने आए। बहुत बढ़िया जवाब। यह भी ध्यान रखें, कि इस तरह का एक समाधान कठिनाई स्तरों को पेश करने का एक तरीका हो सकता है। आसान = 0.5, मध्यम = 0.25, कठोर = 0.10। आदि
तस्सो

मैं असहमत हूं कि यह यादृच्छिक नहीं है। यह यादृच्छिक है, यह सिर्फ एक टुकड़ा वितरण है जबकि हम आमतौर पर समान वितरण के बारे में सोचते हैं। और अपने विचार में जोड़ने के लिए मैं सिर्फ "शब्द में एक यादृच्छिक पत्र चुनें" से आगे जाऊंगा "मैं उस पत्र को वितरित करूंगा जो सबसे अधिक होता है। उदाहरण के लिए "मिसिसिपी" को अधिक s की आवश्यकता है और मैं उनमें से अधिक का चयन करता हूं।
ब्लेन


21

आप अपने सभी अक्षरों की संभावना को उस आवृत्ति के अनुसार भारित कर सकते हैं जिसके साथ वे उस भाषा में होते हैं जो आपके शब्दों में है। एक अच्छा दिशानिर्देश स्क्रैबल सेट है । उदाहरण के लिए, अंग्रेजी संस्करण में 12 E है लेकिन केवल एक Z और एक Q है।

इसे लागू करने का एक सरल तरीका यह है कि प्रत्येक अक्षर को लगातार स्ट्रिंग में एक-एक अक्षर के साथ डालकर और जितनी बार वांछित हो, उतनी बार अपने आरएनजी को एक यादृच्छिक स्थिति से एक पत्र लें। स्यूडोकोड उदाहरण:

const String letters = "AAAAAAAAABBCCDDDDEEEEEEEEEEEEFFGGGHHIIIIIIIIIJ/*...and so on...*/"

char randomLetter = letters[randomIntegerBetween(0, letters.length - 1)];

2
+1 यह एक अच्छी अवधारणा है, लेकिन मुझे संदेह है कि अधिक सुरुचिपूर्ण कार्यान्वयन है।
Evorlor


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

4
इससे समस्या का समाधान नहीं होगा। समस्या यह है कि उपयोगकर्ता को खेल खत्म करने के लिए विशिष्ट पत्रों की आवश्यकता होती है । कहो उन्हें Z की आवश्यकता है? फिर क्या? इससे उपयोगकर्ता को और भी अधिक निराश करने के लिए दुर्लभ अक्षरों को कठिन बना दिया जाएगा।
अमेजिंगड्र्स

@AmazingDreams अच्छी बात की ओर इशारा करती है लेकिन हम इसे थोड़ा संशोधित कर सकते हैं ताकि मैं आवश्यक अल्फाबेट्स को और अधिक वजन और दूसरों को कम वजन प्रदान करूँ। मुझे कहना होगा कि यह पालन करने के लिए बहुत अच्छी अवधारणा है।
दनियाल आजम

4

यहां एक एकल पैरामीटर का उपयोग करके इसे सुधारने का एक तरीका है kजिसे आप ट्विक कर सकते हैं।

एक यादृच्छिक पत्र लेने के बजाय:

  1. एक यादृच्छिक पत्र चुनें A
  2. एक यादृच्छिक संख्या उठाओ X
  3. अगर X > k और A नहीं है [list of remaining needed letters], तो 1 पर फिर से कोशिश करें।

जितना छोटा kहोता है, उतनी बार अंतिम पत्र Aएक होगा जो वास्तव में आवश्यक होता है।

एल्गोरिथ्म को ट्विक करने के लिए k, उदाहरण के लिए किसी भी मूल्य के साथ खेलें k = 0.5। यदि आप पाते हैं कि खेल बहुत कठिन है, तो 0.4इसके बजाय, आदि का प्रयास करें , जब तक कि आपको उचित मूल्य न मिले। यह सीधे आपको एक कठिनाई सेटिंग देता है , जो उदाहरण के लिए आप खेल में खिलाड़ी के अग्रिम के रूप में बढ़ाना चाह सकते हैं।


उत्तर के लिए धन्यवाद, लेकिन यह ACEfanatic02 के उत्तर की तरह प्रतीत होता है।
दनियाल आजम

3

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

यदि आप चाहते हैं कि शब्द में अक्षर अधिक तेज़ी से दिखाई दें, तो शब्द-अक्षरों की अधिक प्रतियां सरणी में रखें।


0

यदि आप C ++ का उपयोग कर रहे हैं, तो आप पहले से मौजूद वितरण http://en.cppreference.com/w/cpp/numeric/random/piecewise_constant_distribution का उपयोग कर सकते हैं

इसने निरंतर समय जटिलता को भी संशोधित किया है जो भोले तरीकों से बेहतर है। उदाहरण:

#include <iostream>
#include <string>
#include <map>
#include <random>
#include <numeric>

int main()
{
    constexpr double containedLetterWeight = 3.0;
    constexpr int iterations = 10000;
    std::string word = "DISTRIBUTION";

    std::mt19937 rng(123);

    std::vector<double> values('Z' - 'A' + 2);
    std::iota(values.begin(), values.end(), 0.0);

    std::vector<double> weights('Z' - 'A' + 1, 1.0);
    for(const auto& c : word) weights[c - 'A'] = containedLetterWeight;

    std::piecewise_constant_distribution<> dist(values.begin(), values.end(), weights.begin());

    std::map<char, int> results;
    for(int n = 0; n < iterations; ++n)
    {
        ++results[static_cast<char>(dist(rng)) + 'A'];
    }
    for(const auto& p : results)
    {
        std::cout << p.first << ' ' << static_cast<float>(p.second) / iterations << '\n';
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.