मुझे एक गतिशील, असीमित आकार के "भूलभुलैया" के लिए डेटा संरचना का निर्माण कैसे करना चाहिए?


43

मुझे वास्तव में यकीन नहीं है कि "भूलभुलैया" सही शब्द है। मूल रूप से उपयोगकर्ता एकल में शुरू Roomकरते हैं जिसमें 4 दरवाजे होते हैं (एन, एस, ई, और डब्ल्यू)। वे किसी भी दिशा में जा सकते हैं, और प्रत्येक बाद के कमरे में 1 से 4 द्वार वाले कहीं भी एक और कमरा होता है जो अन्य कमरों में जाते हैं।

"भूलभुलैया" को आकार में असीमित माना जाता है, और जैसे ही आप कमरे में बढ़ते हैं। सीमित संख्या में Roomsउपलब्ध है, हालांकि उपलब्ध संख्या गतिशील है और बदल सकती है।

मेरी समस्या यह है कि, मैं इस प्रकार के पैटर्न के लिए सर्वश्रेष्ठ डेटा संरचना के बारे में निश्चित नहीं हूं

मैंने पहली बार Roomवस्तुओं के एक [X] [X] सरणी का उपयोग करने के बारे में सोचा था , लेकिन मैं वास्तव में इससे बचना चाहूंगा क्योंकि यह बात किसी भी दिशा में बढ़ने वाली है, और केवल "विज़िट किए गए" कमरों का निर्माण किया जाना चाहिए।

दूसरी सोच यह थी कि प्रत्येक Roomवर्ग में Roomएन, एस, ई और डब्ल्यू के लिए 4 लिंक किए गए गुण हैं, और सिर्फ पिछले से लिंक है Room, लेकिन इसके साथ समस्या यह है कि मुझे नहीं पता कि उपयोगकर्ता कमरे में जाता है या नहीं एक बगल का कमरा पहले से ही "निर्मित" है

उदाहरण के लिए,

--- --- ----------
| | | |
   5 4 शुरू करो
| | | |
--- --- --- ---
--- --- ---------- --- ---
| | | | | |
| १ २ ३
| | | | | |
--- --- --- --- ----------

यदि उपयोगकर्ता स्टार्ट> 1> 2> 3> 4> 5 से चलता है, तो Room# 5 को यह जानना होगा कि डब्ल्यू में शुरुआती कमरा है, एस कमरा # 2 है और इस मामले में उपलब्ध नहीं होना चाहिए, और एन या तो एक हो सकता है नया Roomया एक दीवार (कुछ भी नहीं)।

शायद मुझे सरणी और लिंक किए गए कमरों के मिश्रण की आवश्यकता है, या शायद मैं बस इसे गलत तरीके से देख रहा हूं।

क्या इस प्रकार के "भूलभुलैया" के लिए डेटा संरचना के निर्माण का एक बेहतर तरीका है? या क्या मैं अपनी वर्तमान विचार प्रक्रिया के साथ सही रास्ते पर हूँ, और मुझे जानकारी के कुछ टुकड़े याद आ रहे हैं?

(यदि आप रुचि रखते हैं, तो परियोजना एक गेम है जो मुंचकिन क्वेस्ट के समान है )


मुझे नहीं लगता कि कमरे में किसी भी दिशा में बढ़ने के बाद किसी भी तरह की सरणी काम करेगी ... इसलिए यदि आप [0,0] पर शुरू करते हैं और बाएं चले जाते हैं? यह कोशिश करेगा [-1, 0]।
पॉल

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

मैं शायद गलत हूं, लेकिन यह GameDev.SE पर बेहतर नहीं होगा?
गतिशील

1
@ डायनामिक यह एक डेटा संरचना प्रश्न है, इसलिए यह यहां ठीक है।
इज़काता

जवाबों:


44

प्रत्येक कक्ष निर्देशांक दें (प्रारंभ होगा (0,0)) और निर्देशांक द्वारा प्रत्येक कक्ष को शब्दकोश / हैशमैप में संग्रहीत करें।

यह प्रत्येक कमरे के लिए आसन्न निर्देशांक निर्धारित करने के लिए तुच्छ है, जिसका उपयोग आप यह जांचने के लिए कर सकते हैं कि क्या कमरा पहले से मौजूद है। आप उन स्थानों का प्रतिनिधित्व करने के लिए अशक्त मान डाल सकते हैं जहां यह पहले से ही निर्धारित है कि कोई कक्ष मौजूद नहीं है। (या यदि यह संभव नहीं है, तो मुझे यकीन नहीं है कि, एक अलग शब्दकोश / निर्देशांक के लिए हैम्पस जो एक कमरा नहीं है)


2
प्रत्येक कमरे की वस्तु को कमरे की अन्य वस्तुओं के लिए उत्तर-पूर्व-दक्षिण-पश्चिम की जानकारी में रखें, ताकि आप शब्दकोश (हैशमैप) के साथ-साथ भूलभुलैया को नेविगेट करने के लिए कक्ष कार्डिनल दिशाओं का उपयोग कर सकें (कभी-कभी आप निरपेक्ष समन्वय के साथ खोजना चाहेंगे) कभी-कभी आप जानना चाहेंगे कि कक्ष ऑब्जेक्ट एक्स के उत्तर में क्या है)।
नील

2
@Paul मुझे लगता है कि यह विचार कमरों का एक शब्दकोश बनाने के लिए है, और एक नया निर्माण करते समय Room, शब्दकोश में आसन्न कमरों की तलाश करें और Roomशेष पक्षों में नए कमरे जोड़ने से पहले ऑब्जेक्ट से उनके लिंक जोड़ें । तो केवल एक ही बार जब शब्दकोश खोज होगी, तब एक नई Roomवस्तु बनाते समय , जब बीच में यात्रा न होRooms
राहेल

7
किसी Roomऑब्जेक्ट के अंदर अन्य कमरों के लिंक को स्टोर करने का कोई कारण नहीं है । यदि आप कमरे में हैं (x,y)और उत्तर की यात्रा करना चाहते हैं, तो आप (x,y+1)शब्दकोश में कमरा देखते हैं , अगर यह मौजूद नहीं है तो इसे बनाएगा। शब्दकोश लुकअप बहुत तेज़ हैं O(1),।
कार्ल ब्वेलफेल्ट

3
@KarlBielefeldt: कमरा @ (x,y+1)मौजूद हो सकता है, लेकिन (x,y)उत्तर की ओर जाने योग्य नहीं है । यह कहना है, कि एक किनारे से सीधे नहीं जा सकता (x,y)है (x,y+1)
स्टीवन एवर्स

2
आप लोग इसे जटिल बना रहे हैं। यह मूल रूप से एक सरणी के समान है .. सिवाय इसके कि आप इसे दो आयामी सरणी के बजाय एक शब्दकोश में देख रहे हैं। किसी भी मुद्दे के साथ आप एक सरणी के साथ आएंगे ... लेकिन वह किसी भी तरह एक सरणी का उपयोग करने जा रहा था।
user606723

15

ज्यादातर मामलों में, आप एक ग्राफ़ की तरह ध्वनियों का वर्णन कर रहे हैं। आपकी कुछ आवश्यकताओं (बढ़ते हुए पहलू) को देखते हुए मैं शायद कार्यान्वयन के रूप में एक आसन्न सूची चुनूंगा (अन्य सामान्य विकल्प एक आसन्न मैट्रिक्स होगा )।

मुझे यकीन नहीं है कि आप किस भाषा का उपयोग कर रहे हैं, लेकिन .NET में आसन्न सूची के साथ लागू किए गए ग्राफ़ के कार्यान्वयन के विवरण के साथ एक अच्छा ट्यूटोरियल / स्पष्टीकरण यहाँ है


1
निश्चित नहीं है कि यह वर्णन करने के लिए एक ग्राफ पर्याप्त है क्योंकि एन / ई / एस / डब्ल्यू वास्तव में ग्राफ अवधारणा का हिस्सा नहीं हैं; केवल जुड़ा हुआ है और संभवतः / बाहर है।
एडवर्ड स्ट्रेंज

3
@CrazyEddie: ध्यान रखें कि / एक डेटा संरचना किसी विशेष डोमेन के लिए सीधे मैप करने के लिए नहीं है (वास्तव में, यह उनका लाभ है)। इस विशेष उदाहरण में, ग्राफ़ दिशात्मक होगा और किनारों को एक एनम के साथ तुच्छ रूप से एनोटेट किया जा सकता है।
स्टीवन एवर्स

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

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

2
@MarkBooth लेकिन फिर हम आवश्यकताओं को बदल दिया है, नहीं?
यहोशू ड्रेक

9

कार्यान्वयन के बारे में कुछ विचार (मैंने कारस्केन के बारे में सोचा है जिसमें मैट्रिक्स के निर्माण के लिए कई अन्य चुनौतीपूर्ण पहलू हैं - यह एक साक्षात्कार प्रश्न भी था जिसे मैंने एक बार पूछा था)।

इस संरचना से कुछ प्रश्न पूछे जाते हैं:

  1. क्या X, Y में एक कमरा है?
  2. क्या खाली स्थान X, Y का एक कमरा [N / S / E / W] है?

सरल सूचियों और रेखांकन के साथ समस्या

सरल सूचियों के साथ कठिनाई यह है कि किसी को दिए गए स्थान पर रखा जा सकता है, तो परीक्षण करने के लिए संरचना को चलना होगा। सिस्टम को एक मनमाना स्थान O (1) तक पहुंचने का एक तरीका चाहिए।

विचार करें:

1 2 3 ? 4
5 . . * 6
7 8 9 A B

जानकारी को संभावित स्थान '?' खोजने के लिए, जब 3 पर, किसी को पाने के लिए चारों ओर चलना पड़ता है। 4. अतिरिक्त जानकारी के साथ लिंक का उत्तर कितने नोड्स में कूदता है (ताकि 3 को 4 से जोड़ा जाए? एक 'जंप 1' अतिरिक्त जानकारी के साथ 6 या ए से '*' की आसन्नता खोजने पर अभी भी चलने की आवश्यकता होती है।

सरल, बड़ा, सरण

सीमित संख्या में कमरे उपलब्ध हैं

यदि यह एक बड़ी संख्या नहीं है, तो बस 2N x 2N सरणी बनाएं और इसे वहां छोड़ दें। एक 100 x 100 सरणी 'केवल' 10,000 पॉइंटर्स और 50 ऑब्जेक्ट्स हैं। सूचकांक सीधे सरणी में।

इसे केवल NxN तक कम किया जा सकता है यदि सीमा से बाहर गतिविधियों ने सरणी को हमेशा बाधाओं के भीतर स्थानांतरित कर दिया। उदाहरण के लिए, यदि एक कक्ष जोड़ा जाना था जो कि सरणी को कम करेगा, तो प्रत्येक तत्व को एक स्थान पर स्थानांतरित करने के लिए ग्रिड होगा ताकि अब कोई भी प्रवाह न हो। इस बिंदु पर, 50 कमरों के लिए दुनिया का आकार 2500 पॉइंटर्स और 50 ऑब्जेक्ट होगा।

विरल सरणियों और मैट्रिक्स

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

मेरा पसंदीदा तरीका एक संरचना के रूप में कमरे (आसन्न कमरे के लिए संकेत, और निर्देशांक) होगा और कमरे में एक हैश तालिका से एक सूचक भी है जो समन्वय पर हैशेड है। इस स्थिति में यह पूछने के लिए कि एक अशक्त कमरे से कौन सा कमरा [N / S / E / W] है, कोई हैश तालिका को क्वेरी करेगा। यह, संयोग से, विरल मैट्रिक्स के भंडारण के लिए 'डीओके' प्रारूप है।


1
बुलबुला जवाब के रूप में अच्छा जवाब, हालांकि, यह बताता है कि कुंजी के रूप में एक स्थिति टपल के साथ एक शब्दकोश एक उचित मैट्रिक्स को लागू करने के लिए उपयोग करने के लिए एक उचित संरचना है।
मार्क बूथ

2

इस बारे में कैसा है..

प्रत्येक सेल को उसके प्रत्येक पड़ोसी को एक लिंक दें। प्रत्येक सेल को किसी प्रकार का नाम दें (जैसे "0/0", "-10/0" (मान लें कि आप 0,0 से शुरू करते हैं)। इसमें सभी नामों के साथ एक HashSet जोड़ें। जैसा कि आप किसी अन्य सेल में जाने की कोशिश करते हैं, बस जांच लें कि पड़ोसी पहले से ही हैशसेट में मौजूद नहीं है।

इसके अलावा, यदि आप दूसरे कमरे में एक ओपनिंग बनाते हैं, तो क्या इसका मतलब यह है कि कमरे मौजूद हैं? तो आप किसी खाली कमरे का लिंक बनाएंगे, जिसमें किसी भी कमरे का लिंक नहीं होगा। आप शायद नए कमरों के पड़ोसियों की भी जाँच करना चाहेंगे। यदि कोई मौजूद है, और आपके नए कमरे में खुलेगा, तो उस कमरे में एक दरवाजा जोड़ें।

   Empty   
   (0,1)        

---    ---            ----------
|        |            |        |
    0,0       1,0        2,0       Empty
|        |            |        |   (3,0)
---    --- ---------- ---    ---
|        | |        | |        |
|   0,-1      1,-1       2,-1      Empty
|        | |        | |        |   (3,-1)
---    --- ---    --- ----------

   Empty     Empty   
  (0,-2)    (1,-2)

हैशसेट = {० | १, ०; २; ०; ३; ०; ०; ०, १; —१। ....} १.०: डब्ल्यू = ०,० / द्वार; 1,0: एन = 1,1 / खाली; ई = 2,0 / दरवाजा; एस = 1, -1 / दीवार

आपको यह भी सुनिश्चित करना होगा कि आप प्रत्येक नए कमरे को कम से कम एक गैर-आसन्न (दूसरे कमरे में) द्वार दें ताकि भूलभुलैया उस दिशा में बढ़ सके।


1

आप जो डिज़ाइन कर रहे हैं वह एक ग्राफ़ की तरह लगता है।

भूलभुलैया का एक ग्राफ

ये अक्सर राज्यों के एक सेट के रूप में प्रतिनिधित्व कर रहे हैं क्यू , एक प्रारंभिक राज्य क्ष 0क्यू , और कुछ बदलाव Δ । तो, मेरा सुझाव है कि आप इसे इस तरह स्टोर करें।

  • एक सेट Q : {s, 1, 2, 3, 5, 6}
  • एक प्रारंभिक अवस्था q 0 : s
  • संक्रमण संबंधों का एक नक्शा Δ : {s → 1, s → 5, 1 → 2, 2 → 3, 3 → 4, 4 → →}

अधिकांश उचित भाषाओं में नक्शे और सेट दोनों होते हैं।


0

आप 4 तरह से जुड़ी सूची पर विचार कर सकते हैं ...

मैंने पहली बार कमरे की वस्तुओं के एक [X] [X] सरणी का उपयोग करने के बारे में सोचा था, लेकिन मैं वास्तव में इससे बचना चाहूंगा क्योंकि यह बात किसी भी दिशा में बढ़ने वाली है, और केवल "विज़िट किए गए" कमरों का निर्माण किया जाना चाहिए।

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

आप आलसी मूल्यांकन को लागू करके केवल विज़िट किए गए कमरों का निर्माण कर सकते हैं। एक ऑब्जेक्ट उस जगह पर हो सकता है जिसमें एक कमरा होता है, और उस कमरे का निर्माण नहीं होता है जब तक उस room()पर कॉल नहीं किया जाता है। फिर यह हर बार उसी के बाद वापस आता है। करना मुश्किल नहीं है।


1
क्या आप "4 वे लिंक की गई सूची" के माध्यम से अपना विस्तार कर सकते हैं? केवल एक चीज जो मुझे मिल सकती थी, वह कोडप्रोजेक्ट लेख था, जो एक आसन्न सूची होने का दावा करता है।
स्टीवन एवर्स

0

मैंने "क्रिएटिंग एडवेंचर गेम्स ऑन योर कंप्यूटर" पुस्तक के माध्यम से ऐसा करना सीखा। यदि आप बेसिक कोड (पुस्तक पुरानी है) के माध्यम से खुदाई करने के लिए तैयार हैं, तो यहां पढ़ें:

http://www.atariarchives.org/adventure/chapter1.php

शॉर्टकट के लिए, वे जो करते हैं वह एक कमरे का एक सरणी है, जिसमें प्रत्येक सरणी में एक तत्व दूसरे कमरे के लिए एक पॉइंटर है जिसमें आप जा सकते हैं, 0 के साथ (मैं इन दिनों का उपयोग करूंगा) यह इंगित करने के लिए कि आप नहीं कर सकते उस रास्ते जाओ। उदाहरण के लिए, आप एक कमरे की संरचना (या कक्षा या क्या-क्या-आप) करेंगे

room {
 int north_dir;
 int south_dir;
 int west_dir;
 int east_dir;
 // All other variables and code you care about being attached to the rooms here
}

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

जैसा कि अन्य लोगों ने कहा है, अगर आपको लोगों को दर्ज करने के लिए नए कमरे को गतिशील रूप से उत्पन्न करने की आवश्यकता है, तो आप ऐसा भी कर सकते हैं।


0

एक संरचना के साथ सभी समस्याओं का प्रयास करें और हल न करें।

कमरे के बारे में चीजों को स्टोर करने के लिए अपने कमरे की वस्तु को परिभाषित करें, न कि अन्य कमरों से इसके संबंधों को। फिर एक 1D सरणी, सूची आदि आप की तरह बढ़ सकते हैं।

एक अलग संरचना "रीचैबिलिटी" धारण कर सकती है - मैं किस कमरे में पहुँचा जा सकता है। तब तय करें कि सकर्मक अभिकर्मक को त्वरित गणना की आवश्यकता है या नहीं। तुम एक क्रूर बल गणना और एक कैश चाहते हो सकता है।

शुरुआती अनुकूलन से बचें। वास्तव में सरल संरचनाओं का उपयोग करें और आसानी से समझे जाने वाले एल्गोरिदम को गूंगा करें और जो उपयोग किए जाते हैं उनका अनुकूलन करें।

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