कार्यात्मक प्रोग्रामिंग उस स्थिति को कैसे संभालती है जहां एक ही वस्तु को कई स्थानों से संदर्भित किया जाता है?


10

मैं पढ़ रहा हूं और सुन रहा हूं कि लोग (इस साइट पर भी) नियमित रूप से कार्यात्मक प्रोग्रामिंग प्रतिमान की प्रशंसा करते हैं, इस बात पर जोर देते हैं कि सब कुछ अपरिवर्तनीय होना कितना अच्छा है। विशेष रूप से, लोग इस दृष्टिकोण को पारंपरिक रूप से अनिवार्य OO भाषाओं में भी प्रस्तावित करते हैं, जैसे C #, Java या C ++, न केवल विशुद्ध रूप से कार्यात्मक भाषाओं में, जैसे हास्केल जो प्रोग्रामर पर इसे लागू करता है।

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

एक जगह जब मैं कार्यात्मक प्रतिमान के साथ समस्याओं का पता लगाता हूं, जब एक वस्तु को कई स्थानों से स्वाभाविक रूप से संदर्भित किया जाता है। इसका दो उदाहरणों पर वर्णन करता हूं।

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

इस सेटिंग में, एक एकल राक्षस को कम से कम 2 स्थानों से स्वाभाविक रूप से संदर्भित किया जा सकता है: एक खिलाड़ी की टीम और युद्धक्षेत्र, जो दो "सक्रिय" राक्षसों का संदर्भ देता है।

अब उस स्थिति पर विचार करें जब एक राक्षस मारा जाता है और 20 स्वास्थ्य बिंदु खो देता है। अनिवार्य प्रतिमान के कोष्ठक के भीतर मैं healthइस परिवर्तन को प्रतिबिंबित करने के लिए इस राक्षस के क्षेत्र को संशोधित करता हूं - और यही मैं अभी कर रहा हूं। हालाँकि, यह Monsterवर्ग को परिवर्तनशील और संबंधित कार्यों (विधियों) को अशुद्ध बनाता है , जो मुझे लगता है कि अब तक एक बुरा अभ्यास माना जाता है।

भले ही मैंने खुद को इस खेल के कोड को कम-से-आदर्श राज्य में रखने की अनुमति दी हो, ताकि भविष्य के किसी बिंदु पर वास्तव में इसे खत्म करने की कोई उम्मीद हो, मैं जानना चाहता हूं और समझना चाहता हूं कि यह कैसा होना चाहिए ठीक से लिखा है। इसलिए: यदि यह एक डिजाइन दोष है, तो इसे कैसे ठीक करें?

कार्यात्मक शैली में, जैसा कि मैं इसे समझता हूं, मैं इस Monsterऑब्जेक्ट की एक प्रति बनाऊंगा, इसे इस एक क्षेत्र को छोड़कर पुराने के समान रखता हूं; और विधि suffer_hitपुराने स्थान को संशोधित करने के बजाय इस नई वस्तु को लौटा देगी। फिर मैं वैसे Battlefieldही इस राक्षस को छोड़कर अपने सभी क्षेत्रों को एक समान रखते हुए वस्तु की नकल करूंगा ।

यह कम से कम 2 कठिनाइयों के साथ आता है:

  1. पदानुक्रम आसानी से सिर्फ Battlefield-> के इस सरलीकृत उदाहरण से बहुत गहरा हो सकता है Monster। मुझे एक को छोड़कर सभी क्षेत्रों की ऐसी नकल करनी होगी और इस पदानुक्रम में एक नई वस्तु को वापस करना होगा। यह बॉयलरप्लेट कोड होगा, जो मुझे विशेष रूप से कष्टप्रद लगता है क्योंकि बॉयलरप्लेट को कम करने के लिए कार्यात्मक प्रोग्रामिंग माना जाता है।
  2. हालाँकि, एक और गंभीर समस्या यह है कि इससे डेटा सिंक से बाहर हो जाएगा । क्षेत्र के सक्रिय राक्षस अपने स्वास्थ्य को कम होते देखेंगे; हालांकि, यह एक ही राक्षस, अपने नियंत्रित खिलाड़ी से संदर्भित है Team, नहीं होगा। अगर मैं इसके बजाय अनिवार्य शैली को अपनाता हूं, तो डेटा का प्रत्येक संशोधन कोड के अन्य सभी स्थानों से तुरंत दिखाई देगा और इस तरह के मामलों में मुझे यह वास्तव में सुविधाजनक लगता है - लेकिन जिस तरह से मुझे चीजें मिल रही हैं वह ठीक वही है जो लोग कहते हैं अनिवार्य शैली के साथ गलत है!
    • अब Teamप्रत्येक हमले के बाद यात्रा करके इस मुद्दे पर ध्यान देना संभव होगा । यह अतिरिक्त काम है। हालांकि, क्या होगा अगर एक राक्षस को बाद में और भी अधिक स्थानों से अचानक संदर्भित किया जा सकता है? क्या होगा अगर मैं एक क्षमता के साथ आता हूं, उदाहरण के लिए, एक राक्षस एक और राक्षस पर ध्यान केंद्रित करने देता है जो आवश्यक रूप से क्षेत्र पर नहीं है (मैं वास्तव में ऐसी क्षमता पर विचार कर रहा हूं)? क्या मैं निश्चित रूप से प्रत्येक हमले के बाद तुरंत राक्षसों पर ध्यान केंद्रित करने के लिए यात्रा करना याद रखूंगा? ऐसा लगता है कि एक समय बम होगा जो कोड के रूप में अधिक जटिल हो जाएगा, इसलिए मुझे लगता है कि यह कोई समाधान नहीं है।

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

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

मुझे लगता है कि मेरे राक्षस से जूझ रहे खेल में उसी दृष्टिकोण का प्रयास किया जा सकता है ... फ़ील्ड और टीम राक्षसों का संदर्भ नहीं देते हैं; इसके बजाय वे राक्षसों की आईडी रखते हैं जो एक केंद्रीय राक्षस शब्दकोश में सहेजे जाते हैं।

हालाँकि, मैं एक बार फिर इस दृष्टिकोण के साथ एक समस्या देख सकता हूं जो मुझे समस्या के समाधान के रूप में बिना किसी हिचकिचाहट के इसे स्वीकार करने से रोकता है:

यह एक बार फिर बॉयलरप्लेट कोड का एक स्रोत है। यह आवश्यक रूप से 3-लाइनर्स बनाता है: पहले जो एकल फ़ील्ड का एक-इन-लाइन संशोधन था, उसके लिए अब आवश्यक है (a) केंद्रीय शब्दकोश से ऑब्जेक्ट को पुनर्प्राप्त करना (b) परिवर्तन करना (c) नई ऑब्जेक्ट को सहेजना केंद्रीय शब्दकोश में। इसके अलावा, संदर्भ होने के बजाय वस्तुओं और केंद्रीय शब्दकोशों की आईडी रखने से जटिलता बढ़ जाती है। चूंकि एफपीआई को जटिलता और बॉयलरप्लेट कोड को कम करने के लिए विज्ञापित किया गया है , इसलिए यह संकेत है कि मैं इसे गलत कर रहा हूं।

मैं asecond समस्या के बारे में लिखने जा रहा था जो बहुत अधिक गंभीर लगती है: यह दृष्टिकोण स्मृति लीक का परिचय देता है । अनुपयोगी वस्तुएं सामान्य रूप से एकत्रित कचरा होंगी। हालाँकि, कोई केंद्रीय शब्दकोश में रखी गई वस्तुओं को एकत्र नहीं किया जा सकता है, भले ही कोई भी पहुंच योग्य वस्तु इस विशेष आईडी को संदर्भित न करे। और जबकि सैद्धांतिक रूप से सावधान प्रोग्रामिंग मेमोरी लीक से बच सकती है (हम ध्यान रख सकते हैं कि प्रत्येक वस्तु को केंद्रीय शब्दकोश से मैन्युअल रूप से हटाने के लिए एक बार इसकी आवश्यकता नहीं है), यह त्रुटि प्रवण है और एफपी को कार्यक्रमों की शुद्धता बढ़ाने के लिए विज्ञापित किया जाता है ताकि एक बार फिर ऐसा हो सके। सही तरीका नहीं है।

हालाँकि, मुझे समय पर पता चला कि यह एक सुलझी हुई समस्या लगती है। जावा प्रदान करता है WeakHashMapकि इस मुद्दे को हल करने के लिए इस्तेमाल किया जा सकता है। C # एक समान सुविधा प्रदान करता है - ConditionalWeakTable- यद्यपि डॉक्स के अनुसार इसका उपयोग संकलक द्वारा किया जाना है। और हास्केल में हमारे पास System.Mem.Weak है

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

कुछ विचार के बाद मुझे लगता है कि मैं एक और सवाल जोड़ूंगा: हम इस तरह के शब्दकोशों का निर्माण करके क्या हासिल कर रहे हैं? कई विशेषज्ञों के अनुसार, यह अनिवार्य प्रोग्रामिंग के साथ गलत है, जो कुछ वस्तुओं में परिवर्तन कोड के अन्य टुकड़ों के लिए प्रचारित करता है। इस मुद्दे को हल करने के लिए वस्तुओं को अपरिवर्तनीय माना जाता है - ठीक इसी कारण से, अगर मैं सही ढंग से समझता हूं, तो उनके लिए किए गए परिवर्तन कहीं और दिखाई नहीं देने चाहिए। लेकिन अब मैं आउट-ऑफ-डेट डेटा पर काम करने वाले कोड के अन्य टुकड़ों के बारे में चिंतित हूं, इसलिए मैं केंद्रीय शब्दकोशों का आविष्कार करता हूं ताकि ... एक बार फिर कोड के कुछ टुकड़ों में परिवर्तन कोड के अन्य टुकड़ों में फैल जाए! इसलिए, हम अपनी कथित कमियों के साथ अनिवार्य शैली में वापस नहीं हैं, लेकिन अतिरिक्त जटिलता के साथ?


6
इसे कुछ परिप्रेक्ष्य देने के लिए, कार्यात्मक अपरिवर्तनीय कार्यक्रम ज्यादातर डेटा प्रोसेसिंग स्थितियों के लिए होते हैं, जिसमें संगामिति होती है। दूसरे शब्दों में, ऐसे प्रोग्राम जो इनपुट डेटा को समीकरणों या प्रक्रियाओं के माध्यम से संसाधित करते हैं जो आउटपुट परिणाम उत्पन्न करते हैं। अपरिवर्तनशीलता कई कारणों से इस परिदृश्य में मदद करती है: कई थ्रेड्स द्वारा पढ़े जा रहे मूल्यों को उनके जीवनकाल के दौरान नहीं बदलने की गारंटी दी जाती है, जो डेटा को लॉक-फ्री तरीके से संसाधित करने की क्षमता को बहुत सरल करता है और एल्गोरिथ्म कैसे काम करता है, इसके बारे में तर्क देता है।
रॉबर्ट हार्वे

8
कार्यात्मक अपरिवर्तनीयता और गेम प्रोग्रामिंग के बारे में गंदा थोड़ा रहस्य यह है कि वे दो चीजें एक दूसरे के साथ असंगत हैं। आप अनिवार्य रूप से एक स्थिर, अचल डेटा संरचना का उपयोग करके एक गतिशील, कभी-बदलती प्रणाली को मॉडल करने की कोशिश कर रहे हैं।
रॉबर्ट हार्वे

2
एक धार्मिक हठधर्मिता के रूप में उत्परिवर्तन बनाम अपरिहार्यता को न लें। ऐसी स्थितियाँ हैं जिनमें से प्रत्येक दूसरे से बेहतर है, अपरिवर्तनीयता हमेशा बेहतर नहीं होती है, जैसे कि जीयूआई टूलकिट को अपरिवर्तनीय डेटा प्रकारों के साथ लिखना एक पूर्ण दुःस्वप्न होगा।
whatsisname

1
यह C # -स्पेशल प्रश्न और इसके उत्तर बॉयलरप्लेट के मुद्दे को कवर करते हैं, जिसके परिणामस्वरूप ज्यादातर किसी मौजूदा अपरिवर्तनीय वस्तु के थोड़ा-संशोधित (अपडेटेड) क्लोन बनाने की आवश्यकता होती है।
रॉन्ग

2
एक प्रमुख अंतर्दृष्टि यह है कि इस खेल में एक राक्षस को एक इकाई माना जाता है। इसके अलावा, प्रत्येक लड़ाई का परिणाम (युद्ध क्रम संख्या, राक्षसों की इकाई आईडी, लड़ाई से पहले और बाद में राक्षसों की स्थिति) एक निश्चित समय-बिंदु (या समय-चरण) पर एक राज्य माना जाता है। इस प्रकार, खिलाड़ी ( Team) लड़ाई के परिणाम को पुनः प्राप्त कर सकते हैं और इस प्रकार राक्षसों की स्थिति एक (लड़ाई संख्या, राक्षस इकाई आईडी) टपल से होती है।
रॉलोंग

जवाबों:


19

कार्यात्मक प्रोग्रामिंग कैसे कई स्थानों से संदर्भित वस्तु को संभालता है? यह आपको अपने मॉडल को फिर से दिखाने के लिए आमंत्रित करता है!

समझाने के लिए ... आइए देखें कि कभी-कभी नेटवर्क गेम कैसे लिखे जाते हैं - खेल राज्य की एक केंद्रीय "सुनहरा स्रोत" प्रतिलिपि के साथ, और आने वाले ग्राहक घटनाओं का एक सेट जो उस राज्य को अपडेट करता है, और फिर अन्य ग्राहकों को वापस प्रसारित करता है। ।

आप मज़ेदार के बारे में पढ़ सकते हैं जो फैक्टरियो टीम ने कुछ स्थितियों में अच्छा व्यवहार करने के लिए प्राप्त किया था ; यहाँ उनके मॉडल का एक संक्षिप्त अवलोकन है:

हमारा मल्टीप्लेयर जिस तरह से काम करता है, वह यह है कि सभी क्लाइंट गेम स्टेट का अनुकरण करते हैं और वे केवल खिलाड़ी इनपुट (जिसे इनपुट एक्शन कहते हैं) प्राप्त करते हैं और भेजते हैं। सर्वर की मुख्य जिम्मेदारी इनपुट क्रियाओं को समीप रखना और सुनिश्चित करना है कि सभी ग्राहक एक ही टिक में एक ही क्रिया को अंजाम देते हैं।

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

फैक्टरियो में हमारे पास गेम स्टेट है, यह मैप, प्लेयर, एंटाइटाइट्स, सब कुछ की पूर्ण स्थिति है। यह सर्वर से प्राप्त क्रियाओं के आधार पर सभी क्लाइंट पर नियत रूप से सिम्युलेटेड है। यह पवित्र है और अगर यह कभी सर्वर या किसी अन्य क्लाइंट से अलग होता है, तो एक desync होता है।

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

मुख्य बात यह है कि प्रत्येक वस्तु की स्थिति समय रेखा में विशिष्ट टिक पर अपरिवर्तनीय है । वैश्विक मल्टीप्लेयर राज्य में सब कुछ अंततः एक नियतात्मक वास्तविकता में परिवर्तित होना चाहिए।

और - यह आपके प्रश्न की कुंजी हो सकती है। प्रत्येक इकाई की स्थिति किसी दिए गए टिक के लिए अपरिवर्तनीय है, और आप संक्रमण की घटनाओं पर नज़र रखते हैं जो समय के साथ नए उदाहरण उत्पन्न करते हैं।

यदि आप इसके बारे में सोचते हैं, तो सर्वर से आने वाली ईवेंट कतार को संस्थाओं की एक केंद्रीय निर्देशिका तक पहुंच प्राप्त करनी होती है, ताकि वह इन घटनाओं को लागू कर सके।

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

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

  1. इनपुट की प्रक्रिया करें और संबंधित घटनाओं को उत्पन्न करें
  2. आंतरिक घटनाएँ (जैसे वस्तु टकराव आदि के कारण)
  3. वर्तमान अपरिवर्तनीय राक्षसों के लिए घटनाओं को लागू करें, अगले टिक के लिए नए राक्षस उत्पन्न करने के लिए - जहां संभव हो, ज्यादातर पुराने अपरिवर्तित राज्य की नकल करना, लेकिन जहां आवश्यक हो, नए राज्य ऑब्जेक्ट बनाना।
  4. प्रस्तुत करें और अगले टिक के लिए दोहराएं।

या कुछ इस तरह का। मुझे लगता है कि "मैं इसे कैसे वितरित करूँगा?" काफी अच्छी मानसिक कसरत है, आम तौर पर, मेरी समझ को परिष्कृत करने के लिए जब मैं उलझन में हूं कि चीजें कहां रहती हैं और उन्हें कैसे विकसित होना चाहिए।

@ AaronM.Eshbach के एक नोट के लिए धन्यवाद, यह दर्शाते हुए कि यह इवेंट सोर्सिंग और CQRS पैटर्न के लिए एक समान समस्या डोमेन है , जहां आप समय के साथ अपरिवर्तनीय घटनाओं की एक श्रृंखला के रूप में एक वितरित प्रणाली में राज्य में बदलाव को मॉडलिंग कर रहे हैं । इस मामले में, हम सबसे अधिक संभावना एक जटिल डेटाबेस ऐप को साफ करने की कोशिश कर रहे हैं, जिसे अलग करते हुए (जैसा कि नाम से पता चलता है!) क्वेरी / व्यू सिस्टम से उत्परिवर्ती कमांड हैंडलिंग। अधिक जटिल पाठ्यक्रम, लेकिन अधिक लचीला।


2
अतिरिक्त संदर्भ के लिए, इवेंट सोर्सिंग और CQRS देखें । यह एक समान समस्या डोमेन है: किसी वितरित सिस्टम में समय के साथ अपरिवर्तनीय घटनाओं की एक श्रृंखला के रूप में बदलने के लिए मॉडलिंग परिवर्तन।
हारून एम। एशबैक

@ AaronM.Eshbach वह एक है! क्या आपको बुरा लगता है अगर मैं जवाब में आपकी टिप्पणी / उद्धरण शामिल करता हूं? यह ध्वनि को अधिक आधिकारिक बनाता है। धन्यवाद!
सुसैनडब्ल्यू

कृपया नहीं, कृपया।
आरोन एम। एशबैक

3

आप अनिवार्य शिविर में अभी भी आधे हैं। एक समय में एक ही वस्तु के बारे में सोचने के बजाय अपने खेल के बारे में सोचें जैसे कि नाटकों या घटनाओं का इतिहास

p1 - send m1 to battlefield
p2 - send m2 to battlefield
m1 - attacks m2 (2 dam)
m2 - attacks m1 (10 dam)
p1 - retreats m1

आदि

आप एक स्थिर राज्य वस्तु का उत्पादन करने के लिए एक साथ क्रियाओं का पीछा करके किसी भी बिंदु पर खेल की स्थिति की गणना कर सकते हैं। प्रत्येक नाटक एक फ़ंक्शन है जो एक राज्य ऑब्जेक्ट लेता है और एक नई स्टेट ऑब्जेक्ट लौटाता है

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