मैं Minecraft की क्राफ्टिंग ग्रिड जैसी किसी चीज़ को कैसे लागू कर सकता हूं?


55

Minecraft में क्राफ्टिंग प्रणाली एक 2x2 या 3x3 ग्रिड का उपयोग करता है। आप सामग्री को ग्रिड पर रखते हैं, और यदि आप सही सामग्री को सही पैटर्न में रखते हैं, तो यह नुस्खा को सक्रिय करेगा।

डिजाइन के बारे में कुछ दिलचस्प बिंदु:

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

मैं इसे उखाड़ फेंक सकता हूं, लेकिन यह एक दिलचस्प खोज / सेट-कमी समस्या की तरह लगता है। तो, यह कैसे काम करता है (या कर सकता है), एल्गोरिदमिक रूप से बोल रहा है?


6
बहुत बढ़िया सवाल! मुझे बहुत दिलचस्पी है! मेरे पास पहले से ही कुछ विचार हैं लेकिन मैं घर पहुंचते ही उन्हें साझा करूंगा।
जकोरा डेस

मैं वास्तव में "के रूप में करीब संभव" Minecraft प्रतिलिपि लिखने की कोशिश कर रहा हूँ। मैंने सभी इन्वेंट्री और नुस्खा प्रबंधक सामान पहले से ही लिखा है और मुझे यह कहना है कि यह बहुत साफ काम कर रहा है। मैं साफ कोड के बारे में संतुष्ट हूं। हालाँकि, इसे लिखना आसान नहीं था। मैंने लगभग 10 कक्षाएं लिखीं, ताकि यह सभी व्यंजनों, ग्रिड, इन्वेंट्री आदि पर काम कर सकें। जब मुझे कुछ समय मिलेगा, तो मैं एक उत्तर लिखूंगा।
मार्टिअन कोर्टो

आपको यह देखना चाहिए कि कैसे minecraft उनके क्राफ्टिंग व्यंजनों को कोड करता है।
ब्रैडमैन

जवाबों:


14

एक और समाधान एक जटिल पेड़ का उपयोग करना है। आपके पेड़ में शाखा नोड्स नुस्खा पर पुनरावृत्ति करके बनाया जाएगा (एक बार फिर उपयोग करके for (y) { for (x) }); यह आपकी स्टॉक-स्टैंडर्ड-टू-बुक ट्री संरचना है। आपके अंतिम नोड में एक अतिरिक्त संरचना ( Dictionary/ HashMap) होगी जो व्यंजनों के आयामों को मैप करती है।

अनिवार्य रूप से आप इसके लिए जा रहे हैं:

पकाने की विधि पेड़

काली नोड्स आपकी शाखाएं हैं जो आइटम प्रकार को इंगित करती हैं - लाल वाले आपके पत्ते (टर्मिनेटर) हैं जो आपको आकार / अभिविन्यास में अंतर करने की अनुमति देते हैं।

इस पेड़ की खोज करने के लिए आपको पहले बाउंडिंग बॉक्स मिलेगा (जैसा कि मेरे पहले उत्तर में उल्लिखित है ) और फिर उसी क्रम में नोड्स पर पुनरावृति करें जैसा कि आप जाते हैं। अंत में आप बस अपने में आयाम देखेंगे Dictionaryया HashMapआपको नुस्खा का परिणाम मिलेगा।

बस किक के लिए मैं गया और इसे लागू किया - जो शायद मेरे जवाब को स्पष्ट करेगा। इसके अलावा : मुझे एहसास है कि यह एक अलग जवाब है - और सही तो यह है: यह एक अलग समाधान है।


बहुत सीधा है। मुझें यह पसंद है।
डेविड आइक

मैं इसे स्वीकार करता हूं, क्योंकि मुझे पेड़, हैश और आरेख पसंद हैं जो इस मामले के दिल में कटौती करते हैं। एक चित्र को देखो, और मैं आपके एल्गोरिथ्म को लगभग तुरंत समझ गया।
डेविड आइक

23

आपको यह याद रखना होगा कि Minecraft केवल संभव व्यंजनों के एक बहुत छोटे सेट का उपयोग करता है, इसलिए उस सभी स्मार्ट के लिए कुछ भी करने की आवश्यकता नहीं है।

कहा कि मैं जो करूंगा वह सबसे छोटा ग्रिड है जो फिट बैठता है (यानी एक 2x2 या 3x3, या 2x3 (दरवाजा)) यह जानने के लिए कि खाली पंक्तियों और स्तंभों को अनदेखा करें। फिर उस आकार के साथ व्यंजनों की सूची के माध्यम से लूप करें, बस यह जांचें कि क्या आइटम प्रकार समान है (अर्थात, न्यूनतम से कम 9 पूर्णांक की तुलना में मिनीक्राफ्ट में है क्योंकि यह आइटम और ब्लॉकों के लिए पूर्णांक प्रकार आईडी का उपयोग करता है) और जब आप एक मैच पाते हैं तो रोक दें।

इस तरह से वस्तुओं की सापेक्ष स्थिति भी अप्रासंगिक हो जाती है (आप क्राफ्टिंग ग्रिड पर कहीं भी एक मशाल लगा सकते हैं और यह काम करेगा क्योंकि यह 1x2 बॉक्स के रूप में देखता है, न कि 3x3 बॉक्स जो ज्यादातर खाली है)।

यदि आपके पास व्यंजनों की एक बड़ी मात्रा है ताकि संभावित मैचों के माध्यम से एक रेखीय खोज करने में लंबा समय लगे तो सूची को सॉर्ट करना और एक द्विआधारी खोज (O (लॉग) (N)) बनाम O (N)) करना संभव होगा। यह सूची बनाने में कुछ अतिरिक्त काम करेगा, लेकिन यह एक बार स्टार्टअप पर किया जा सकता है और बाद में मेमोरी में रखा जा सकता है।

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

यदि आप इसे दूसरी रेसिपी में शामिल किए बिना करना चाहते हैं, तो आप यह जांच सकते हैं कि इनपुट रेसिपी में आइटम है [0,0] में उच्च आईडी के साथ [2x2 के लिए] (या [0,1], कोई चेक की आवश्यकता नहीं है 1x2 के लिए और यदि ऐसा है तो इसे मिरर करें, यदि आप अगली पंक्ति की जाँच तब तक जारी न रखें जब तक कि आप अंतिम छोर पर न पहुँच जाएँ। इसके उपयोग से आपको यह भी सुनिश्चित करना होगा कि व्यंजनों को सही घुमाव में जोड़ा गया है।


1
मुझे आश्चर्य है कि अगर Minecraft में व्यंजनों की छोटी संख्या खुद को एक रैखिक खोज में उधार नहीं दे सकती है।
डेविड आईके

1
यह करता है, और मूल रूप से जो मैंने ऊपर लिखा है (बाइनरी खोज के संभावित अनुकूलन के साथ)। हालांकि, यह मशाल क्राफ्टिंग के लिए कुछ विकल्प छोड़ता है जिसे आप मूल रूप से कहीं भी फिट कर सकते हैं। नुस्खा के आकार को प्राप्त करने से पहले आपको मशालों के लिए 6 व्यंजनों को जोड़ने की आवश्यकता नहीं है और आप अपनी खोज को केवल एक चरण में सही आकार तक सीमित करते हैं। - तो मूल रूप से आपके बिंदु 2 के विकल्प आकार द्वारा समूह हैं, नुस्खा को एक कोने में ले जाएं या अधिक डुप्लिकेट व्यंजनों को जोड़ें।
इलावा

15

यह देखना कि क्या एक निश्चित ग्रिड कॉन्फ़िगरेशन एक निश्चित नुस्खा से मेल खाता है यदि आप एक स्ट्रिंग के रूप में 3x3 ग्रिड को एनकोड करते हैं और एक नियमित अभिव्यक्ति मैच का उपयोग करते हैं । लुक को तेज करना एक अलग मामला है, जिसके बारे में मैं अंत में बात करूंगा। अधिक जानकारी के लिए आगे पढ़िए।

चरण 1) स्ट्रिंग के रूप में एनकोड ग्रिड

बस इस क्रम में प्रत्येक प्रकार के सेल को एक चार-चार आईडी दें और हर चीज को साइड में कर दें:

123
456 => 123456789
789

और अधिक ठोस उदाहरण के रूप में, स्टिक रेसिपी पर विचार करें, जहां डब्ल्यू लकड़ी की है और ई एक खाली सेल है (आप बस एक खाली चार '' का उपयोग कर सकते हैं):

EEE
WEE => EEEWEEWEE
WEE

चरण 2) रेगुलर एक्सप्रेशन (या String.Contains को डेटा पर थोड़ी प्रोसेसिंग के साथ प्रयोग करके मैच रेसिपी)

ऊपर दिए गए उदाहरण से जारी रखते हुए, भले ही हम गठन को चारों ओर ले जाते हैं, फिर भी स्ट्रिंग में एक पैटर्न है (दोनों तरफ ई द्वारा लिखित पैड):

EEW
EEW => EEWEEWEEE
EEE

तो कोई फर्क नहीं पड़ता कि आप छड़ी को किस ओर घुमाते हैं, यह अभी भी निम्नलिखित नियमित अभिव्यक्ति से मेल खाएगा: /^E*WEEWE*$/

नियमित अभिव्यक्तियाँ आपको आपके द्वारा उल्लिखित सशर्त व्यवहार करने देती हैं। उदाहरण के लिए (बनाया गया नुस्खा), यदि आप एक ही परिणाम देने के लिए लोहे या पत्थर से बने पिकैक्स चाहते हैं , अर्थात:

III    SSS
EWE or EWE
EWE    EWE

आप दोनों को नियमित अभिव्यक्ति में जोड़ सकते हैं: /^(III)|(SSS)EWEEWE$/

क्षैतिज फ़्लिप को भी आसानी से जोड़ा जा सकता है (| ऑपरेटर भी) का उपयोग करके।

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

चरण 3) लुकअप को गति देना

खोज को कम करने के लिए, आपको समूह व्यंजनों के लिए कुछ डेटा संरचना एक साथ बनाने और लुकअप के साथ मदद करने की आवश्यकता होगी। ग्रिड को स्ट्रिंग के रूप में मानने से यहाँ कुछ फायदे भी हैं :

  1. आप पहले गैर-खाली चरित्र और अंतिम गैर-खाली चरित्र के बीच की दूरी के रूप में एक नुस्खा की "लंबाई" को परिभाषित कर सकते हैं। एक साधारण Trim().Length()आपको यह जानकारी देगा। व्यंजनों को लंबाई द्वारा समूहीकृत किया जा सकता है और एक शब्दकोश में संग्रहीत किया जा सकता है।

    या

    "लंबाई" की एक वैकल्पिक परिभाषा गैर-खाली वर्णों की संख्या हो सकती है। और कुछ नहीं बदलता। आप इस मानदंड द्वारा भी व्यंजनों को समूहित कर सकते हैं।

  2. यदि बिंदु संख्या 1 पर्याप्त नहीं है, तो रेसिपी को पहले घटक के प्रकार से और भी समूहीकृत किया जा सकता है जो रेसिपी में दिखाई देता है। यह करना उतना ही सरल होगा Trim().CharAt(0)(और ट्रिम से बचाव के लिए एक रिक्त स्ट्रिंग उत्पन्न होती है)।

तो उदाहरण के लिए आप व्यंजनों को एक में संग्रहीत करेंगे:

Dictionary<int, Dictionary<char, List<string>>> _recipes;

और लुकअप कुछ इस तरह से करें:

// A string encode of your current grid configuration 
string grid;

// Get length and first char in our grid
string trim = grid.Trim();
int length = trim.Length();
char firstChar = length==0 ? ' ' : trim[0];

foreach(string recipe in _recipes[length][firstChar])
{
    // Check for a match with the recipe
    if(Regex.Match(grid, recipe))
    {
        // We found a matching recipe, do something with it
    }
}

3
यह है ... बहुत बहुत होशियार।
रवेलीन 13:28

18
आपको कोई समस्या है और आप इसे नियमित अभिव्यक्तियों का उपयोग करके हल करना चाहते हैं? अब आपको 2 समस्याएं हैं :)
क्रॉम्स्टर का कहना है कि मोनिका का समर्थन

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

2
@ दाविदगौविया, यह सिर्फ उन लोगों के लिए एक वाक्यांश है जो रेगेक्स के साथ बहुत सहज नहीं हैं। यदि वे regex के साथ एक समस्या को हल करने का निर्णय लेते हैं, तो उन्हें अब दो समस्याएं हैं: (1) वास्तविक समस्या जिसे वे हल करना चाहते हैं (2) उस समस्या को हल करने के लिए regex पैटर्न लिखना
iamserious

2
'अब आपको दो समस्याएं हैं' पर वापस जा रहे हैं - जब तक आपका regex प्रोसेसर यूनिकोड का समर्थन करता है और जब तक आप कुछ विशेष संयोजनों को rexx NFA कंपाइलर ट्रिप नहीं कर सकते हैं, तो आप गारंटी दे सकते हैं कि जब तक आपके पास ASCII प्रिंट करने योग्य रेंज की तुलना में अधिक आइटम हैं, तब Regex में समस्याएँ होंगी। यूपी। आप अपने खुद के डीएफए (काफी आसानी से वास्तव में) को पैटर्न के साथ जोड़ सकते हैं; लेकिन regex प्रोटोटाइपिंग के दौरान जाने का सबसे अच्छा तरीका होगा।
जोनाथन डिकिंसन

3

मैं आपको यह नहीं बता सकता कि Minecraft एक कैसे काम करता है - हालांकि मुझे यकीन है कि अगर आप MCP को देखते हैं (यदि आपके पास Minecraft की कानूनी प्रति है) तो आप पता लगा सकते हैं।

मैं इसे इस प्रकार लागू करूंगा:

  1. कुछ डिस्क-आधारित डिक्शनरी / हैशमैप ( बी + ट्री / एसक्यूएल-लाइट ) लें - मूल्य रेसिपी परिणाम की आइटम आईडी होगी।
  2. एक उपयोगकर्ता कुछ क्राफ्टिंग किया जाता है तो बस एक आइटम के साथ पहली पंक्ति / स्तंभ को खोजने के स्वतंत्र रूप से ; उन लोगों को एक ऑफसेट में मिलाएं।
  3. किसी आइटम के साथ अंतिम पंक्ति / कॉलम को फिर से, स्वतंत्र रूप से ढूंढें।
  4. आइटम से चौड़ाई और ऊंचाई की गणना करें और इसे कुंजी में जोड़ें।
  5. आप केवल गणना की गई बाउंडिंग बॉक्स की सीमा पर लूप करें और प्रत्येक आइटम की आईडी को जोड़ें (अपने सामान्य उपयोग करके for (y) { for (x) })।
  6. डेटाबेस में कुंजी को देखें।

तो उदाहरण के लिए हम दो अवयवों को कहते हैं; X और Y और खाली होना *। निम्नलिखित नुस्खा लें:

**X
**Y
**Y

पहले हम बाउंडिंग बॉक्स, पैदावार का काम करते हैं (2,0)-(2,2)। इसलिए हमारी कुंजी इस तरह दिखाई देगी [1][3](1 चौड़ाई, 3 ऊंचाई)। अगला हम बाउंडिंग बॉक्स के भीतर प्रत्येक आइटम पर लूप करते हैं और आईडी को जोड़ते हैं, इस प्रकार कुंजी बन जाती है [1][3][X][Y][Y]- फिर आप इसे अपने शब्दकोश / डीबी में देखते हैं और आपको उस नुस्खा का परिणाम मिलेगा।

चरण 2 में स्वतंत्रता को स्पष्ट रूप से समझाने के लिए, निम्नलिखित नुस्खा पर विचार करें:

*XX
XXX
XX*

शीर्ष / बाईं ओर 0,0 पर स्पष्ट रूप से है - हालांकि आपका पहला आइटम आम तौर पर 0,1 या 1,0 होगा (आपके लूप के आधार पर)। हालाँकि यदि पहले गैर-खाली कॉलम के साथ-साथ पहली गैर-रिक्त पंक्ति खोजें और उन को-ऑर्डिनेट्स को मिलाएं जो आपको 0,0 मिलेंगे - वही प्रिंसिपल बाउंडिंग बॉक्स के नीचे / दाएं पर लागू होता है।


बुककिट रिपॉजिटरी का कोई Minecraft कोड नहीं है, आपको MCP (और Minecraft की एक प्रति) की आवश्यकता होगी
BlueRaja - Danny Pflughoeft

क्या यह सिर्फ आपके दूसरे उत्तर का उलटा नहीं है?
डेविड आईके

@DavidEyk (यह मेरा पहला उत्तर है) वास्तव में नहीं, यह एक हैशमैप संरचना पर निर्भर है (चाहे वह बिगटेबल-लाइक या मेमोरी में हो)। मैंने फिर से जवाब दिया क्योंकि मैं हैश टकराव के बारे में चिंतित था जो खराब प्रदर्शन के लिए अग्रणी था - कम से कम इन-मेमोरी हैशमैप। मेरे अन्य उत्तर अधिक वस्तुओं और इन-मेमोरी संरचना के लिए बेहतर काम करेंगे - जहां यह SQL / आदि में बेहतर होगा।
जोनाथन डिकिंसन

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.