खेल 2048 के लिए इष्टतम एल्गोरिथ्म क्या है?


1919

मैंने हाल ही में 2048 खेल पर ठोकर खाई है । आप समान टाइलों को "बड़ी" टाइल बनाने के लिए किसी भी चार दिशाओं में स्थानांतरित करके विलय करते हैं। प्रत्येक चाल के बाद, 2या तो मान के साथ एक नया टाइल यादृच्छिक खाली स्थिति में दिखाई देता है 4। खेल तब समाप्त होता है जब सभी बक्से भरे जाते हैं और ऐसी कोई चाल नहीं होती है जो टाइलों को मर्ज कर सकती है, या आप एक मान के साथ एक टाइल बनाते हैं 2048

एक, मुझे लक्ष्य तक पहुंचने के लिए एक अच्छी तरह से परिभाषित रणनीति का पालन करने की आवश्यकता है। इसलिए, मैंने इसके लिए एक कार्यक्रम लिखने के बारे में सोचा।

मेरा वर्तमान एल्गोरिथ्म:

while (!game_over) {
    for each possible move:
        count_no_of_merges_for_2-tiles and 4-tiles
    choose the move with a large number of merges
}

क्या मैं कर रहा हूँ किसी भी बिंदु पर, मैं मूल्यों के साथ टाइल्स विलय करने की कोशिश करेंगे है 2और 4यह है कि, मैं करने की कोशिश, 2और 4टाइल संभव के रूप में कम से कम के रूप में,। अगर मैं इसे इस तरह आज़माता हूँ, तो अन्य सभी टाइलें स्वतः विलीन हो रही हैं और रणनीति अच्छी लगती है।

लेकिन, जब मैं वास्तव में इस एल्गोरिथ्म का उपयोग करता हूं, तो मुझे खेल समाप्त होने से पहले केवल 4000 अंक मिलते हैं। अधिकतम अंक AFAIK 20,000 से थोड़ा अधिक अंक है जो मेरे वर्तमान स्कोर से बड़ा है। क्या उपरोक्त की तुलना में बेहतर एल्गोरिदम है?


84
यह मदद कर सकता है! ov3y.github.io/2048-AI
Cegprakash

5
इस तरह से @ nitish712, आपका एल्गोरिथ्म लालची है क्योंकि आपके पास choose the move with large number of mergesजल्दी से स्थानीय ऑप्टिमा होता है
खालिद। के।

21
@ 500-इंटरनलसेवरर्र: यदि मैं अल्फा-बीटा गेम ट्री प्रूनिंग के साथ एक एआई को लागू करने वाला था, तो यह माना जाएगा कि नए ब्लॉक प्रतिकूल रूप से रखे गए हैं। यह एक सबसे खराब स्थिति है, लेकिन उपयोगी हो सकता है।
चार्ल्स

6
एक मजेदार व्याकुलता जब आपके पास उच्च स्कोर के लिए लक्ष्य करने का समय नहीं होता है: सबसे कम स्कोर प्राप्त करने का प्रयास करें। सिद्धांत रूप में यह 2s और 4s को वैकल्पिक कर रहा है।
मार्क हर्ड

7
इस प्रश्न की वैधता पर चर्चा मेटा पर पाई जा सकती है: meta.stackexchange.com/questions/227266/…
Jeroen Vannevel

जवाबों:


1266

मैंने @ ओवल्यूज़ एल्गोरिथ्म द्वारा उपयोग की जाने वाली न्यूनतम खोज के बजाय, अपेक्समैक्स ऑप्टिमाइज़ेशन का उपयोग करके 2048 एआई विकसित किया। एआई बस सभी संभावित चालों पर अधिकतमकरण करता है, इसके बाद सभी संभावित टाइल स्पैन (टाइलों की संभावना से भारित, अर्थात् 4 के लिए 10% और 2 के लिए 90%) पर अपेक्षा करता है। जहाँ तक मैं जानता हूँ, यह अपेक्सिमैक्स ऑप्टिमाइज़ेशन को छाँटना संभव नहीं है (सिवाय उन शाखाओं को हटाने के जो कि अत्यधिक संभावना नहीं हैं), और इसलिए उपयोग किया जाने वाला एल्गोरिथ्म एक सावधानी से अनुकूलित ब्रूट फोर्स सर्च है।

प्रदर्शन

अपने डिफ़ॉल्ट कॉन्फ़िगरेशन में AI (8 की अधिकतम खोज गहराई) बोर्ड की स्थिति की जटिलता के आधार पर, एक चाल को निष्पादित करने के लिए 10ms से 200ms तक कहीं भी ले जाता है। परीक्षण में, AI पूरे खेल के दौरान 5-10 चाल प्रति सेकंड की औसत चाल प्राप्त करता है। यदि खोज गहराई 6 चालों तक सीमित है, तो AI आसानी से प्रति सेकंड 20 + चालों को निष्पादित कर सकता है, जो कुछ दिलचस्प देखने के लिए बनाता है ।

एआई के स्कोर प्रदर्शन का आकलन करने के लिए, मैंने एआई को 100 बार (रिमोट कंट्रोल के माध्यम से ब्राउज़र गेम से जुड़ा) चलाया। प्रत्येक टाइल के लिए, यहां उन खेलों के अनुपात हैं जिनमें उस टाइल को कम से कम एक बार हासिल किया गया था:

2048: 100%
4096: 100%
8192: 100%
16384: 94%
32768: 36%

सभी रनों पर न्यूनतम स्कोर 124024 था; अधिकतम अंक 794076 प्राप्त किया गया। माध्यिका स्कोर 387222 है। AI कभी भी 2048 टाइल प्राप्त करने में विफल नहीं हुआ (इसलिए इसने 100 खेलों में एक बार भी खेल नहीं खोया); वास्तव में, इसने प्रत्येक रन में कम से कम एक बार 8192 टाइल हासिल की !

यहाँ सबसे अच्छा रन का स्क्रीनशॉट है:

32768 टाइल, स्कोर 794076

इस गेम ने 96 मिनट से अधिक 27830 चालें चलीं, या औसतन 4.8 चाल प्रति सेकंड।

कार्यान्वयन

मेरा दृष्टिकोण पूरे बोर्ड (16 प्रविष्टियों) को एक एकल 64-बिट पूर्णांक (जहां टाइलें नायबल्स हैं, यानी 4-बिट विखंडू) के रूप में एन्कोड करता है। 64-बिट मशीन पर, यह पूरे बोर्ड को सिंगल मशीन रजिस्टर में पास करने में सक्षम बनाता है।

बिट शिफ्ट ऑपरेशन का उपयोग व्यक्तिगत पंक्तियों और स्तंभों को निकालने के लिए किया जाता है। एक एकल पंक्ति या स्तंभ एक 16-बिट मात्रा है, इसलिए आकार 65536 की तालिका उन परिवर्तनों को एन्कोड कर सकती है जो एकल पंक्ति या स्तंभ पर काम करते हैं। उदाहरण के लिए, चालों को एक पूर्ववर्ती "चाल प्रभाव तालिका" में 4 लुकअप के रूप में कार्यान्वित किया जाता है जो बताता है कि प्रत्येक चाल एक पंक्ति या स्तंभ को कैसे प्रभावित करती है (उदाहरण के लिए, "चाल सही" तालिका में प्रविष्टि "1122 -> 0023" है जिसमें बताया गया है कि कैसे चाल पंक्ति [2,2,4,4] पंक्ति बन जाती है [0,0,4,8] जब दाईं ओर ले जाया जाता है)।

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

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

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

heuristics

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

प्रारंभ में, मैंने दो बहुत ही साधारण उत्तराधिकारियों का उपयोग किया, खुले वर्गों के लिए "बोनस" और किनारे पर बड़े मूल्यों को देने के लिए। इन अनुमानों ने बहुत अच्छा प्रदर्शन किया, अक्सर 16384 हासिल किए, लेकिन कभी भी 32768 तक नहीं पहुंचे।

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

इसके अलावा, पेट्र ने "मेटा-ऑप्टिमाइज़ेशन" रणनीति ( सीएमए-ईएस नामक एल्गोरिथ्म का उपयोग करते हुए ) का उपयोग करके हेटरिस्टिक वेट को भी अनुकूलित किया , जहां वेट स्वयं उच्चतम संभव औसत स्कोर प्राप्त करने के लिए समायोजित किया गया था।

इन परिवर्तनों का प्रभाव अत्यंत महत्वपूर्ण है। एल्गोरिथ्म 16384 टाइल को प्राप्त करने से 13% समय के आसपास प्राप्त हुआ, और 90% समय के 1/3 से अधिक 32768 प्राप्त करना शुरू कर दिया (जबकि पुराने आंकड़े कभी एक 32768 टाइल का उत्पादन नहीं करते थे) ।

मेरा मानना ​​है कि उत्तराधिकार पर सुधार के लिए अभी भी जगह है। यह एल्गोरिथ्म निश्चित रूप से अभी तक "इष्टतम" नहीं है, लेकिन मुझे लगता है कि यह बहुत करीब हो रहा है।


एआई अपने खेल के एक तिहाई से अधिक में 32768 टाइल प्राप्त करता है एक विशाल मील का पत्थर है; मुझे यह सुनकर हैरानी होगी कि क्या किसी भी मानव खिलाड़ी ने आधिकारिक गेम पर 32768 हासिल किए हैं (यानी कि सेवस्टेट्स या पूर्ववत जैसे टूल का उपयोग किए बिना)। मुझे लगता है कि 65536 टाइल पहुंच के भीतर है!

आप अपने लिए AI की कोशिश कर सकते हैं। कोड https://github.com/nneonneo/2048-ai पर उपलब्ध है ।


12
@RobL: 2 का समय 90% दिखाई देता है; 4 समय के 10% दिखाई देते हैं। क्या है स्रोत कोड : var value = Math.random() < 0.9 ? 2 : 4;
nnonneo

35
वर्तमान में Cuda के लिए पोर्टिंग इसलिए GPU बेहतर गति के लिए भी काम करता है!
निमेसन

25
@nneonneo मैंने आपके कोड को emscripten के साथ जावास्क्रिप्ट में पोर्ट किया, और यह अब ब्राउज़र में काफी अच्छी तरह से काम करता है ! देखने के लिए और सब कुछ संकलित करने की आवश्यकता के बिना कूल ... फ़ायरफ़ॉक्स में, प्रदर्शन काफी अच्छा है ...
रिवर्स_इंजीनियर

6
4x4 ग्रिड में सैद्धांतिक सीमा वास्तव में IS 131072 65536 नहीं है। हालांकि इसके लिए सही समय में 4 प्राप्त करने की आवश्यकता होती है (यानी पूरे बोर्ड में 4 .. 65536 प्रत्येक एक बार - 15 क्षेत्रों पर कब्जा कर लिया जाता है) और उस पर बोर्ड लगाना होगा। पल ताकि आप वास्तव में गठबंधन कर सकें।
बोडो थेइसेन जूल

5
@nneonneo आप हमारे AI की जांच करना चाहते हैं, जो कि और भी बेहतर लगता है, 60% गेम में 32k तक पहुँचना: github.com/aszczepanski/2048
cauchy

1253

मैं एआई कार्यक्रम का लेखक हूं जो दूसरों ने इस धागे में उल्लेख किया है। आप एआई को कार्रवाई में देख सकते हैं या स्रोत पढ़ सकते हैं ।

वर्तमान में, यह कार्यक्रम मेरे लैपटॉप पर ब्राउज़र में जावास्क्रिप्ट में चलने वाली एक 90% जीत दर के बारे में प्राप्त करता है, जो प्रति चाल सोच समय के 100 मिलीसेकंड के बारे में दिया जाता है, इसलिए जब तक कि पूर्ण (अभी तक!) यह बहुत अच्छा प्रदर्शन नहीं करता।

चूंकि खेल एक असतत राज्य स्थान है, सही जानकारी, शतरंज और चेकर्स जैसे बारी-आधारित खेल, मैंने उन्हीं तरीकों का इस्तेमाल किया जो उन खेलों पर काम करने के लिए साबित हुए हैं, अर्थात् अल्फा-बीटा प्रूनिंग के साथ न्यूनतम खोज । चूँकि वहाँ पहले से ही उस एल्गोरिथ्म के बारे में बहुत सारी जानकारी मौजूद है, मैं सिर्फ दो मुख्य उत्तराधिकारियों के बारे में बात करूँगा जिनका मैं स्थैतिक मूल्यांकन समारोह में उपयोग करता हूँ और जो अन्य लोगों द्वारा यहाँ व्यक्त किए गए कई अंतर्ज्ञान को औपचारिक रूप देता है।

दिष्टता

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

यहाँ एक पूरी तरह से मोनोटोनिक ग्रिड का स्क्रीनशॉट है। अन्य एल्गोरिथ्मों की अवहेलना करने के लिए निकाले गए निष्कासन समारोह के साथ एल्गोरिथ्म चलाकर मैंने इसे प्राप्त किया और केवल एकरसता पर विचार किया।

एक पूरी तरह से मोनोटोनिक 2048 बोर्ड

चिकनाई

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

हैकर न्यूज के एक टिप्पणीकार ने ग्राफ सिद्धांत के संदर्भ में इस विचार का एक दिलचस्प औपचारिकरण दिया ।

यहाँ इस बेहतरीन पैरोडी कांटे के सौजन्य से एक बिल्कुल चिकनी ग्रिड का एक स्क्रीनशॉट है ।

एक पूरी तरह से चिकनी 2048 बोर्ड

मुफ्त टाइलें

और अंत में, बहुत कम मुफ्त टाइल होने के लिए एक जुर्माना है, क्योंकि विकल्प जल्दी से बाहर निकल सकते हैं जब गेम बोर्ड बहुत तंग हो जाता है।

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

संपादित करें:

यहाँ इस दृष्टिकोण की शक्ति का प्रदर्शन है। मैंने टाइल मूल्यों को अनप्लग कर दिया (इसलिए यह 2048 तक पहुंचने के बाद भी जारी रहा) और यहां आठ परीक्षणों के बाद सबसे अच्छा परिणाम है।

4096

हां, यह 2048 के साथ 4096 है। =) इसका मतलब है कि इसने एक ही बोर्ड पर तीन बार मायावी 2048 टाइल हासिल की।


89
आप '2' और '4' टाइल रखने वाले कंप्यूटर को 'प्रतिद्वंद्वी' मान सकते हैं।
वी येन

29
@WeiYen ज़रूर है, लेकिन एक माइनमैक्स समस्या के रूप में इसके बारे में गेम लॉजिक के प्रति विश्वासयोग्य नहीं है, क्योंकि कंप्यूटर कुछ संभावनाओं के साथ यादृच्छिक रूप से टाइल्स लगा रहा है, बजाय जानबूझकर स्कोर को कम करने के।
कू

57
भले ही AI बेतरतीब ढंग से टाइलें लगा रहा हो, लेकिन लक्ष्य खोना नहीं है। अशुभ प्राप्त करना एक ही बात है क्योंकि प्रतिद्वंद्वी आपके लिए सबसे खराब चाल का चयन करता है। "मिनट" भाग का मतलब है कि आप रूढ़िवादी रूप से खेलने की कोशिश करते हैं ताकि कोई भयानक कदम न हो जो आपको अशुभ मिल सके।
फ्रायजी

196
मेरे पास 2048 का एक कांटा बनाने का विचार था, जहां 2s और 4s को रखने के बजाय कंप्यूटर बेतरतीब ढंग से आपके AI का उपयोग करके यह निर्धारित करता है कि मूल्यों को कहां रखा जाए। परिणाम: सरासर असभ्यता। : यहाँ से बाहर करने की कोशिश की जा सकती है sztupy.github.io/2048-Hard
SztupY

30
@SztupY वाह, यह बुराई है। मुझे qntm.org/hatetris Hatetris की याद दिलाता है , जो उस टुकड़े को रखने की कोशिश करता है जो आपकी स्थिति को कम से कम सुधार देगा।
पताशु

145

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

एअर इंडिया एल्गोरिथम

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

प्रति चाल केवल 100 रन (यानी मेमोरी गेम्स में) के साथ, AI 2048 टाइल 80% बार और 4096 टाइल 50% बार प्राप्त करता है। 10000 रनों का उपयोग करने पर 2048 टाइल 100%, 4096 टाइल के लिए 70% और 8192 टाइल के लिए लगभग 1% मिलती है।

इसे एक्शन में देखें

सबसे अच्छा प्राप्त स्कोर यहाँ दिखाया गया है:

सर्वश्रेष्ठ अंक

इस एल्गोरिथ्म के बारे में एक दिलचस्प तथ्य यह है कि जब रैंडम-प्ले गेम काफी खराब होते हैं, तो सबसे अच्छा (या कम से कम खराब) कदम चुनने से बहुत अच्छा गेम प्ले होता है: एक विशिष्ट AI गेम 70000 अंकों और अंतिम 3000 चालों तक पहुंच सकता है, फिर भी किसी भी स्थिति से इन-मेमोरी रैंडम प्ले गेम्स मरने से पहले लगभग 40 अतिरिक्त चालों में औसतन 340 अतिरिक्त अंक प्राप्त करते हैं। (आप एआई चलाकर और डिबग कंसोल को खोलकर अपने लिए इसे देख सकते हैं।)

यह ग्राफ इस बिंदु को दिखाता है: नीली रेखा प्रत्येक चाल के बाद बोर्ड स्कोर दिखाती है। लाल रेखा उस स्थिति से एल्गोरिथ्म का सबसे अच्छा यादृच्छिक-रन एंड गेम स्कोर दिखाती है । संक्षेप में, लाल मूल्य नीले मूल्यों को उनकी ओर "खींच" रहे हैं, क्योंकि वे एल्गोरिथम का सबसे अच्छा अनुमान है। यह देखना दिलचस्प है कि लाल रेखा प्रत्येक बिंदु पर नीली रेखा से थोड़ी ऊपर है, फिर भी नीली रेखा अधिक से अधिक बढ़ रही है।

स्कोरिंग ग्राफ

मुझे यह बहुत आश्चर्यजनक लगता है कि एल्गोरिथ्म को वास्तव में अच्छे खेल खेलने की आवश्यकता नहीं है ताकि इसे बनाने वाले चालों को चुना जा सके।

बाद में मैंने पाया कि इस एल्गोरिथ्म को प्योर मोंटे कार्लो ट्री सर्च एल्गोरिदम के रूप में वर्गीकृत किया जा सकता है ।

कार्यान्वयन और लिंक

पहले मैंने एक जावास्क्रिप्ट संस्करण बनाया, जिसे यहां कार्रवाई में देखा जा सकता है । यह संस्करण सभ्य समय में 100 रन चला सकता है। अतिरिक्त जानकारी के लिए कंसोल खोलें। ( स्रोत )

बाद में, कुछ और आसपास खेलने के लिए मैंने @nneonneo को अत्यधिक अनुकूलित बुनियादी ढांचे का उपयोग किया और C ++ में अपना संस्करण लागू किया। यदि आपके पास धैर्य है तो यह संस्करण प्रति चाल 100000 रन और यहां तक ​​कि 1000000 तक की अनुमति देता है। भवन निर्माण के निर्देश दिए। यह कंसोल में चलता है और वेब संस्करण को चलाने के लिए रिमोट-कंट्रोल भी है। ( स्रोत )

परिणाम

हैरानी की बात है, रन की संख्या में वृद्धि से खेल खेलने में काफी सुधार नहीं होता है। 4096 टाइल के साथ लगभग 80000 बिंदुओं पर इस रणनीति की एक सीमा लगती है और सभी छोटे, 8192 टाइल को प्राप्त करने के बहुत करीब हैं। 100 से 100000 के रनों की संख्या बढ़ाने से बढ़ जाती है बाधाओं इस स्कोर सीमित करने के लिए हो रही (5% से 40% तक), लेकिन इसके माध्यम से तोड़ने नहीं की।

महत्वपूर्ण पदों के पास 1000000 की अस्थायी वृद्धि के साथ 10000 रन चलाने से 129892 का अधिकतम स्कोर और 8192 टाइल प्राप्त करने वाले 1% से कम बार इस बाधा को तोड़ने में कामयाब रहे।

सुधार

इस एल्गोरिथ्म को लागू करने के बाद मैंने कई सुधारों की कोशिश की जिसमें न्यूनतम या अधिकतम स्कोर, या न्यूनतम, अधिकतम और एवीजी का संयोजन शामिल है। मैं भी गहराई उपयोग करने की कोशिश: प्रति चाल कश्मीर रन की कोशिश कर के बजाय, मैं इस कदम प्रति कश्मीर चाल की कोशिश की सूची एक दिया लंबाई के ( "ऊपर, ऊपर, बाएँ" उदाहरण के लिए) और सबसे अच्छा स्कोरिंग कदम सूची में सबसे पहला कदम का चयन।

बाद में मैंने एक स्कोरिंग ट्री लागू किया जो एक दी गई सूची के बाद एक चाल चलने में सक्षम होने की सशर्त संभावना को ध्यान में रखता है।

हालांकि, इनमें से किसी भी विचार ने सरल पहले विचार पर कोई वास्तविक लाभ नहीं दिखाया। मैंने C ++ कोड में इन विचारों के लिए कोड छोड़ दिया।

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

मुझे यह सुनने में दिलचस्पी होगी कि क्या किसी के पास अन्य सुधार विचार हैं जो एआई के डोमेन-स्वतंत्रता को बनाए रखते हैं।

2048 वेरिएंट और क्लोन

बस मज़े के लिए, मैंने AI को एक बुकमार्कलेट के रूप में लागू किया है , जो गेम के नियंत्रण में हुक करता है। यह एआई को मूल खेल और इसके कई प्रकारों के साथ काम करने की अनुमति देता है ।

एआई के डोमेन-स्वतंत्र प्रकृति के कारण यह संभव है। कुछ वेरिएंट काफी अलग हैं, जैसे हेक्सागोनल क्लोन।


7
+1। एक AI छात्र के रूप में मुझे यह वास्तव में दिलचस्प लगा। खाली समय में इस पर बेहतर नज़र डालेंगे।
इसहाक

4
ये अद्भुत है! मैं सिर्फ उम्मीद के लिए एक अच्छा हेरास्टिक समारोह के लिए वजन का अनुकूलन घंटे बिताए और मैं इसे 3 मिनट में लागू करता हूं और यह पूरी तरह से इसे नष्ट कर देता है।
ब्रेंडन एनेबल

8
मोंटे कार्लो सिमुलेशन का अच्छा उपयोग।
nnonneo

5
इस नाटक को देखना आत्मज्ञान का आह्वान है। यह सभी अनुमानों की धज्जियाँ उड़ाता है और फिर भी यह काम करता है। बधाई हो !
स्टीफन गौरीचोन

4
अब तक, यहां सबसे दिलचस्प समाधान है।
शबाव

126

EDIT: यह एक भोली एल्गोरिथ्म है, जो मानव जागरूक विचार प्रक्रिया को मॉडलिंग करता है, और AI की तुलना में बहुत कमजोर परिणाम प्राप्त करता है जो सभी संभावनाओं को खोजता है क्योंकि यह केवल एक टाइल से आगे दिखता है। यह प्रतिक्रिया समयरेखा में जल्दी प्रस्तुत किया गया था।

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

खत्म करने के लिए तैयार है

यह वह मॉडल है जिसे मैंने डिफ़ॉल्ट रूप से चुना है।

1024 512 256 128
  8   16  32  64
  4   2   x   x
  x   x   x   x

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

यहाँ एल्गोरिथ्म जाता है। लगभग 80% जीत (ऐसा लगता है कि अधिक "पेशेवर" एआई तकनीकों के साथ जीतना हमेशा संभव है, मुझे इस बारे में निश्चित नहीं है, हालांकि)।

initiateModel();

while(!game_over)
{    
    checkCornerChosen(); // Unimplemented, but it might be an improvement to change the reference point

    for each 3 possible move:
        evaluateResult()
    execute move with best score
    if no move is available, execute forbidden move and undo, recalculateModel()
 }

 evaluateResult() {
     calculatesBestCurrentModel()
     calculates distance to chosen model
     stores result
 }

 calculateBestCurrentModel() {
      (according to the current highest tile acheived and their distribution)
  }

लापता कदम पर कुछ संकेत। यहाँ:मॉडल परिवर्तन

अपेक्षित मॉडल के करीब होने के भाग्य के कारण मॉडल बदल गया है। एआई जिस मॉडल को हासिल करने की कोशिश कर रहा है वह है

 512 256 128  x
  X   X   x   x
  X   X   x   x
  x   x   x   x

और वहां पहुंचने का सिलसिला बन गया है:

 512 256  64  O
  8   16  32  O
  4   x   x   x
  x   x   x   x

Oनिषिद्ध स्थानों का प्रतिनिधित्व करें ...

तो यह दाईं ओर, फिर दाईं ओर, फिर (सही या शीर्ष जहां 4 बनाया गया है) के आधार पर दबाएगा, फिर श्रृंखला को तब तक पूरा करने के लिए आगे बढ़ेगा जब तक कि यह न हो जाए:

चैन पूरा हुआ

तो अब मॉडल और चेन वापस आ गए हैं:

 512 256 128  64
  4   8  16   32
  X   X   x   x
  x   x   x   x

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

यहां छवि विवरण दर्ज करें

यहाँ मॉडल और श्रृंखला है:

  O 1024 512 256
  O   O   O  128
  8  16   32  64
  4   x   x   x

जब यह 128 तक पहुंचने का प्रबंधन करता है तो यह एक पूरी पंक्ति फिर से प्राप्त कर लेता है:

  O 1024 512 256
  x   x  128 128
  x   x   x   x
  x   x   x   x

execute move with best scoreआप संभावित अगले राज्यों में से सर्वश्रेष्ठ स्कोर का मूल्यांकन कैसे कर सकते हैं?
खालिद.के।

हेयुरिस्टिक evaluateResultआप में परिभाषित किया गया है मूल रूप से सबसे अच्छा संभव परिदृश्य के करीब लाने की कोशिश करें।
डैरन

@ डेरेन मैं आपके विस्तृत विवरण की प्रतीक्षा कर रहा हूं
ashu

@ आशू मैं इस पर काम कर रहा हूं, अप्रत्याशित परिस्थितियों ने इसे खत्म करने के लिए मुझे समय के बिना छोड़ दिया है। इस बीच मैंने एल्गोरिथ्म में सुधार किया है और अब यह 75% समय को हल करता है।
डैरन

13
मुझे इस रणनीति के बारे में वास्तव में पसंद है कि मैं इसे मैन्युअल रूप से खेल खेलने के दौरान उपयोग करने में सक्षम हूं, यह मुझे 37k अंक तक मिला।
सिफेलोपॉड

94

मैं यहाँ अपने ब्लॉग पर एक पोस्ट की सामग्री की प्रतिलिपि बनाता हूँ


मेरे द्वारा प्रस्तावित समाधान बहुत सरल और लागू करने में आसान है। हालांकि, यह 131040 के स्कोर तक पहुंच गया है। एल्गोरिथ्म प्रदर्शन के कई बेंचमार्क प्रस्तुत किए जाते हैं।

स्कोर

कलन विधि

हेयोरिस्टिक स्कोरिंग एल्गोरिदम

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

(131072 टाइल तक पहुँचने की संभावना है अगर 4-टाइल बेतरतीब ढंग से 2-टाइल के बजाय उत्पन्न होती है जब आवश्यक हो)

बोर्ड के आयोजन के दो संभावित तरीके निम्नलिखित छवियों में दिखाए गए हैं:

यहां छवि विवरण दर्ज करें

एक मोनोटोनिक घटते क्रम में टाइलों के समन्वय को लागू करने के लिए, स्कोर सी को एक ज्यामितीय अनुक्रम के मूल्यों द्वारा गुणा किए गए बोर्ड पर रैखिक मूल्यों के योग के रूप में सामान्य अनुपात r <1 के साथ गुणा किया जाता है।

रों

रों

कई रैखिक पथ का मूल्यांकन एक बार में किया जा सकता है, अंतिम स्कोर किसी भी पथ का अधिकतम स्कोर होगा।

निर्णय नियम

लागू किया गया निर्णय नियम काफी स्मार्ट नहीं है, पायथन में कोड यहाँ प्रस्तुत किया गया है:

@staticmethod
def nextMove(board,recursion_depth=3):
    m,s = AI.nextMoveRecur(board,recursion_depth,recursion_depth)
    return m

@staticmethod
def nextMoveRecur(board,depth,maxDepth,base=0.9):
    bestScore = -1.
    bestMove = 0
    for m in range(1,5):
        if(board.validMove(m)):
            newBoard = copy.deepcopy(board)
            newBoard.move(m,add_tile=True)

            score = AI.evaluate(newBoard)
            if depth != 0:
                my_m,my_s = AI.nextMoveRecur(newBoard,depth-1,maxDepth)
                score += my_s*pow(base,maxDepth-depth+1)

            if(score > bestScore):
                bestMove = m
                bestScore = score
    return (bestMove,bestScore);

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

बेंचमार्क

  • टी 1 - 121 परीक्षण - 8 विभिन्न पथ - आर = 0.125
  • टी 2 - 122 परीक्षण - 8-विभिन्न पथ - आर = 0.25
  • टी 3 - 132 परीक्षण - 8-विभिन्न पथ - आर = 0.5
  • टी 4 - 211 परीक्षण - 2-अलग-अलग पथ - आर = 0.125
  • टी 5 - 274 परीक्षण - 2-अलग-अलग पथ - आर = 0.25
  • टी 6 - 211 परीक्षण - 2-अलग-अलग पथ - आर = 0.5

यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें

टी 2 के मामले में, दस में चार टेस्ट के एक औसत स्कोर के साथ 4096 टाइल उत्पन्न रों42000

कोड

कोड निम्न लिंक पर GiHub पर पाया जा सकता है: https://github.com/Nicola17/term2048-AI यह शब्द 2048 पर आधारित है और यह पायथन में लिखा गया है। मैं जल्द से जल्द C ++ में अधिक कुशल संस्करण लागू करूंगा।


बुरा नहीं है, अपने चित्रण मुझे एक विचार दिया है मूल्यांकन में मर्ज वैक्टर लेने का,
Khaled.K

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

41

मेरा प्रयास अन्य समाधानों की तरह अपेक्समैक्स का उपयोग करता है, लेकिन बिटबोर्ड के बिना। Nneonneo का समाधान 10 गतियों की चाल की जाँच कर सकता है जो लगभग 4 की गहराई है जिसमें 6 टाइलें बची हैं और 4 चालें संभव हैं (2 * 6 * 4) 4 । मेरे मामले में, इस गहराई का पता लगाने में बहुत लंबा समय लगता है, मैं अपेक्षित टाइल की गहराई को समायोजित की गई मुफ्त टाइलों की संख्या के अनुसार समायोजित करता हूं:

depth = free > 7 ? 1 : (free > 4 ? 2 : 3)

बोर्डों के स्कोर की गणना मुफ्त टाइलों की संख्या के वर्ग के भारित योग और 2 डी के डॉट उत्पाद के साथ की जाती है:

[[10,8,7,6.5],
 [.5,.7,1,3],
 [-.5,-1.5,-1.8,-2],
 [-3.8,-3.7,-3.5,-3]]

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

नीचे या गीथूब पर कोड :

var n = 4,
	M = new MatrixTransform(n);

var ai = {weights: [1, 1], depth: 1}; // depth=1 by default, but we adjust it on every prediction according to the number of free tiles

var snake= [[10,8,7,6.5],
            [.5,.7,1,3],
            [-.5,-1.5,-1.8,-2],
            [-3.8,-3.7,-3.5,-3]]
snake=snake.map(function(a){return a.map(Math.exp)})

initialize(ai)

function run(ai) {
	var p;
	while ((p = predict(ai)) != null) {
		move(p, ai);
	}
	//console.log(ai.grid , maxValue(ai.grid))
	ai.maxValue = maxValue(ai.grid)
	console.log(ai)
}

function initialize(ai) {
	ai.grid = [];
	for (var i = 0; i < n; i++) {
		ai.grid[i] = []
		for (var j = 0; j < n; j++) {
			ai.grid[i][j] = 0;
		}
	}
	rand(ai.grid)
	rand(ai.grid)
	ai.steps = 0;
}

function move(p, ai) { //0:up, 1:right, 2:down, 3:left
	var newgrid = mv(p, ai.grid);
	if (!equal(newgrid, ai.grid)) {
		//console.log(stats(newgrid, ai.grid))
		ai.grid = newgrid;
		try {
			rand(ai.grid)
			ai.steps++;
		} catch (e) {
			console.log('no room', e)
		}
	}
}

function predict(ai) {
	var free = freeCells(ai.grid);
	ai.depth = free > 7 ? 1 : (free > 4 ? 2 : 3);
	var root = {path: [],prob: 1,grid: ai.grid,children: []};
	var x = expandMove(root, ai)
	//console.log("number of leaves", x)
	//console.log("number of leaves2", countLeaves(root))
	if (!root.children.length) return null
	var values = root.children.map(expectimax);
	var mx = max(values);
	return root.children[mx[1]].path[0]

}

function countLeaves(node) {
	var x = 0;
	if (!node.children.length) return 1;
	for (var n of node.children)
		x += countLeaves(n);
	return x;
}

function expectimax(node) {
	if (!node.children.length) {
		return node.score
	} else {
		var values = node.children.map(expectimax);
		if (node.prob) { //we are at a max node
			return Math.max.apply(null, values)
		} else { // we are at a random node
			var avg = 0;
			for (var i = 0; i < values.length; i++)
				avg += node.children[i].prob * values[i]
			return avg / (values.length / 2)
		}
	}
}

function expandRandom(node, ai) {
	var x = 0;
	for (var i = 0; i < node.grid.length; i++)
		for (var j = 0; j < node.grid.length; j++)
			if (!node.grid[i][j]) {
				var grid2 = M.copy(node.grid),
					grid4 = M.copy(node.grid);
				grid2[i][j] = 2;
				grid4[i][j] = 4;
				var child2 = {grid: grid2,prob: .9,path: node.path,children: []};
				var child4 = {grid: grid4,prob: .1,path: node.path,children: []}
				node.children.push(child2)
				node.children.push(child4)
				x += expandMove(child2, ai)
				x += expandMove(child4, ai)
			}
	return x;
}

function expandMove(node, ai) { // node={grid,path,score}
	var isLeaf = true,
		x = 0;
	if (node.path.length < ai.depth) {
		for (var move of[0, 1, 2, 3]) {
			var grid = mv(move, node.grid);
			if (!equal(grid, node.grid)) {
				isLeaf = false;
				var child = {grid: grid,path: node.path.concat([move]),children: []}
				node.children.push(child)
				x += expandRandom(child, ai)
			}
		}
	}
	if (isLeaf) node.score = dot(ai.weights, stats(node.grid))
	return isLeaf ? 1 : x;
}



var cells = []
var table = document.querySelector("table");
for (var i = 0; i < n; i++) {
	var tr = document.createElement("tr");
	cells[i] = [];
	for (var j = 0; j < n; j++) {
		cells[i][j] = document.createElement("td");
		tr.appendChild(cells[i][j])
	}
	table.appendChild(tr);
}

function updateUI(ai) {
	cells.forEach(function(a, i) {
		a.forEach(function(el, j) {
			el.innerHTML = ai.grid[i][j] || ''
		})
	});
}


updateUI(ai);
updateHint(predict(ai));

function runAI() {
	var p = predict(ai);
	if (p != null && ai.running) {
		move(p, ai);
		updateUI(ai);
		updateHint(p);
		requestAnimationFrame(runAI);
	}
}
runai.onclick = function() {
	if (!ai.running) {
		this.innerHTML = 'stop AI';
		ai.running = true;
		runAI();
	} else {
		this.innerHTML = 'run AI';
		ai.running = false;
		updateHint(predict(ai));
	}
}


function updateHint(dir) {
	hintvalue.innerHTML = ['↑', '→', '↓', '←'][dir] || '';
}

document.addEventListener("keydown", function(event) {
	if (!event.target.matches('.r *')) return;
	event.preventDefault(); // avoid scrolling
	if (event.which in map) {
		move(map[event.which], ai)
		console.log(stats(ai.grid))
		updateUI(ai);
		updateHint(predict(ai));
	}
})
var map = {
	38: 0, // Up
	39: 1, // Right
	40: 2, // Down
	37: 3, // Left
};
init.onclick = function() {
	initialize(ai);
	updateUI(ai);
	updateHint(predict(ai));
}


function stats(grid, previousGrid) {

	var free = freeCells(grid);

	var c = dot2(grid, snake);

	return [c, free * free];
}

function dist2(a, b) { //squared 2D distance
	return Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2)
}

function dot(a, b) {
	var r = 0;
	for (var i = 0; i < a.length; i++)
		r += a[i] * b[i];
	return r
}

function dot2(a, b) {
	var r = 0;
	for (var i = 0; i < a.length; i++)
		for (var j = 0; j < a[0].length; j++)
			r += a[i][j] * b[i][j]
	return r;
}

function product(a) {
	return a.reduce(function(v, x) {
		return v * x
	}, 1)
}

function maxValue(grid) {
	return Math.max.apply(null, grid.map(function(a) {
		return Math.max.apply(null, a)
	}));
}

function freeCells(grid) {
	return grid.reduce(function(v, a) {
		return v + a.reduce(function(t, x) {
			return t + (x == 0)
		}, 0)
	}, 0)
}

function max(arr) { // return [value, index] of the max
	var m = [-Infinity, null];
	for (var i = 0; i < arr.length; i++) {
		if (arr[i] > m[0]) m = [arr[i], i];
	}
	return m
}

function min(arr) { // return [value, index] of the min
	var m = [Infinity, null];
	for (var i = 0; i < arr.length; i++) {
		if (arr[i] < m[0]) m = [arr[i], i];
	}
	return m
}

function maxScore(nodes) {
	var min = {
		score: -Infinity,
		path: []
	};
	for (var node of nodes) {
		if (node.score > min.score) min = node;
	}
	return min;
}


function mv(k, grid) {
	var tgrid = M.itransform(k, grid);
	for (var i = 0; i < tgrid.length; i++) {
		var a = tgrid[i];
		for (var j = 0, jj = 0; j < a.length; j++)
			if (a[j]) a[jj++] = (j < a.length - 1 && a[j] == a[j + 1]) ? 2 * a[j++] : a[j]
		for (; jj < a.length; jj++)
			a[jj] = 0;
	}
	return M.transform(k, tgrid);
}

function rand(grid) {
	var r = Math.floor(Math.random() * freeCells(grid)),
		_r = 0;
	for (var i = 0; i < grid.length; i++) {
		for (var j = 0; j < grid.length; j++) {
			if (!grid[i][j]) {
				if (_r == r) {
					grid[i][j] = Math.random() < .9 ? 2 : 4
				}
				_r++;
			}
		}
	}
}

function equal(grid1, grid2) {
	for (var i = 0; i < grid1.length; i++)
		for (var j = 0; j < grid1.length; j++)
			if (grid1[i][j] != grid2[i][j]) return false;
	return true;
}

function conv44valid(a, b) {
	var r = 0;
	for (var i = 0; i < 4; i++)
		for (var j = 0; j < 4; j++)
			r += a[i][j] * b[3 - i][3 - j]
	return r
}

function MatrixTransform(n) {
	var g = [],
		ig = [];
	for (var i = 0; i < n; i++) {
		g[i] = [];
		ig[i] = [];
		for (var j = 0; j < n; j++) {
			g[i][j] = [[j, i],[i, n-1-j],[j, n-1-i],[i, j]]; // transformation matrix in the 4 directions g[i][j] = [up, right, down, left]
			ig[i][j] = [[j, i],[i, n-1-j],[n-1-j, i],[i, j]]; // the inverse tranformations
		}
	}
	this.transform = function(k, grid) {
		return this.transformer(k, grid, g)
	}
	this.itransform = function(k, grid) { // inverse transform
		return this.transformer(k, grid, ig)
	}
	this.transformer = function(k, grid, mat) {
		var newgrid = [];
		for (var i = 0; i < grid.length; i++) {
			newgrid[i] = [];
			for (var j = 0; j < grid.length; j++)
				newgrid[i][j] = grid[mat[i][j][k][0]][mat[i][j][k][1]];
		}
		return newgrid;
	}
	this.copy = function(grid) {
		return this.transform(3, grid)
	}
}
body {
	font-family: Arial;
}
table, th, td {
	border: 1px solid black;
	margin: 0 auto;
	border-collapse: collapse;
}
td {
	width: 35px;
	height: 35px;
	text-align: center;
}
button {
	margin: 2px;
	padding: 3px 15px;
	color: rgba(0,0,0,.9);
}
.r {
	display: flex;
	align-items: center;
	justify-content: center;
	margin: .2em;
	position: relative;
}
#hintvalue {
	font-size: 1.4em;
	padding: 2px 8px;
	display: inline-flex;
	justify-content: center;
	width: 30px;
}
<table title="press arrow keys"></table>
<div class="r">
    <button id=init>init</button>
    <button id=runai>run AI</button>
    <span id="hintvalue" title="Best predicted move to do, use your arrow keys" tabindex="-1"></span>
</div>


3
यकीन नहीं है कि यह अधिक upvotes क्यों नहीं है। यह वास्तव में सरलता के लिए प्रभावी है।
डेविड ग्रीडेनस

धन्यवाद, देर से जवाब और यह वास्तव में अच्छा प्रदर्शन नहीं करता है (लगभग हमेशा [1024, 8192] में), लागत / आँकड़े फ़ंक्शन को और अधिक काम करने की आवश्यकता है
caub

आपने खाली जगहों का वजन कैसे किया?
डेविड ग्रीडेनस

1
यह बस है cost=1x(number of empty tiles)²+1xdotproduct(snakeWeights,grid)और हम इस लागत को अधिकतम करने की कोशिश
caub

धन्यवाद @Rustusto, मुझे किसी दिन कोड में सुधार करना चाहिए, इसे सरल बनाया जा सकता है
caub

38

मैं एक 2048 नियंत्रक का लेखक हूं जो इस धागे में वर्णित किसी भी अन्य कार्यक्रम से बेहतर स्कोर करता है। नियंत्रक का एक कुशल कार्यान्वयन जीथब पर उपलब्ध है । में एक अलग रेपो वहाँ भी नियंत्रक के राज्य मूल्यांकन कार्य के प्रशिक्षण के लिए इस्तेमाल किया कोड है। प्रशिक्षण विधि का वर्णन कागज में किया गया है

नियंत्रक अस्थायी मूल्यांकन सीखने (एक सुदृढीकरण सीखने की तकनीक) के एक संस्करण द्वारा खरोंच (मानव 2048 विशेषज्ञता के बिना) से सीखा राज्य मूल्यांकन समारोह के साथ अपेक्षित खोज का उपयोग करता है । राज्य-मूल्य फ़ंक्शन एक n-tuple नेटवर्क का उपयोग करता है , जो मूल रूप से बोर्ड पर देखे गए पैटर्न का एक भारित रैखिक कार्य है। इसमें कुल मिलाकर 1 बिलियन से अधिक वज़न शामिल थे ।

प्रदर्शन

1 चालें / समय: 609104 (औसत 100 खेल)

10 चालों पर: 589355 (300 गेम औसत)

3-प्लाई (सीए 1500 चाल / सेकंड ): 511759 (1000 गेम औसत)

10 चाल / एस के लिए टाइल आँकड़े निम्नानुसार हैं:

2048: 100%
4096: 100%
8192: 100%
16384: 97%
32768: 64%
32768,16384,8192,4096: 10%

(अंतिम पंक्ति का मतलब बोर्ड पर एक ही समय में दी गई टाइलें हैं)।

3-प्लाई के लिए:

2048: 100%
4096: 100%
8192: 100%
16384: 96%
32768: 54%
32768,16384,8192,4096: 8%

हालाँकि, मैंने इसे 65536 टाइल प्राप्त करने के लिए कभी नहीं देखा।


4
सुंदर प्रभावशाली परिणाम। हालाँकि, आप संभवतः समझाने के उत्तर को अपडेट कर सकते हैं (मोटे तौर पर, सरल शब्दों में ... मुझे यकीन है कि पूरा विवरण यहां पोस्ट करने में बहुत लंबा होगा) आपका कार्यक्रम इसे कैसे प्राप्त करता है? सीखने की एल्गोरिथ्म कैसे काम करता है के एक मोटे विवरण के रूप में?
सेड्रिक मैमो

27

मुझे लगता है कि मुझे एक एल्गोरिथ्म मिला जो काफी अच्छा काम करता है, जैसा कि मैं अक्सर 10000 से अधिक के स्कोर तक पहुंचता हूं, मेरा व्यक्तिगत सर्वश्रेष्ठ लगभग 16000 है। मेरा समाधान एक कोने में सबसे बड़ी संख्या रखने के लिए नहीं है, बल्कि इसे शीर्ष पंक्ति में रखने के लिए है।

कृपया नीचे कोड देखें:

while( !game_over ) {
    move_direction=up;
    if( !move_is_possible(up) ) {
        if( move_is_possible(right) && move_is_possible(left) ){
            if( number_of_empty_cells_after_moves(left,up) > number_of_empty_cells_after_moves(right,up) ) 
                move_direction = left;
            else
                move_direction = right;
        } else if ( move_is_possible(left) ){
            move_direction = left;
        } else if ( move_is_possible(right) ){
            move_direction = right;
        } else {
            move_direction = down;
        }
    }
    do_move(move_direction);
}

5
मैंने 100,000 खेलों का परीक्षण किया, जो कि इस तुच्छ चक्रीय रणनीति का परीक्षण कर रहे हैं "ऊपर, दाएं, ऊपर, बाएं, ..." (और नीचे अगर यह हो)। चक्रीय रणनीति ने "औसत टाइल स्कोर" समाप्त कर दिया 770.6, जबकि यह एक बस मिल गया 396.7। क्या आपके पास अनुमान है कि ऐसा क्यों हो सकता है? मुझे लगता है कि यह बहुत अधिक उतार-चढ़ाव करता है, यहां तक ​​कि जब बाएं या दाएं बहुत अधिक विलय होगा।
थॉमस अहले

1
यदि वे कई दिशाओं में स्थानांतरित नहीं होते हैं, तो टाइल असंगत तरीकों से स्टैक करते हैं। सामान्य तौर पर, चक्रीय रणनीति का उपयोग करने से केंद्र में बड़ी टाइलें होंगी, जो पैंतरेबाज़ी को बहुत अधिक तंग करती हैं।
बीकानेर

25

इस गेम के लिए यहां पहले से ही AI कार्यान्वयन है । README से उद्धरण:

एल्गोरिथ्म पुनरावृत्ति गहन गहराई पहले अल्फा-बीटा खोज है। मूल्यांकन समारोह ग्रिड पर टाइल्स की संख्या को कम करते हुए पंक्तियों और स्तंभों को या तो मोनोटोनिक (या तो सभी घटते या बढ़ते) रखने की कोशिश करता है।

इस एल्गोरिथ्म के बारे में हैकर न्यूज़ पर एक चर्चा भी है जो आपको उपयोगी लग सकती है।


4
यह शीर्ष उत्तर होना चाहिए, लेकिन कार्यान्वयन के बारे में अधिक विवरण जोड़ना अच्छा होगा: जैसे कि गेम बोर्ड को कैसे बनाया गया है (एक ग्राफ के रूप में), ऑप्टिमाइज़ किए गए ऑप्टिमाइज़ेशन (टाइल्स के बीच का अंतर-अधिकतम) आदि
Alceu Costa

1
भविष्य के पाठकों के लिए: यह वही लेखक है जो अपने लेखक (ओवोल्यूड) द्वारा यहां दूसरे टॉप - टॉप उत्तर में समझाया गया है। इस उत्तर और इस चर्चा में ओव्यूलेशन के कार्यक्रम के अन्य उल्लेखों ने, ओवोल्यूड को प्रकट करने और लिखने के लिए प्रेरित किया कि उनके एल्गोरिदम ने कैसे काम किया; उस जवाब में अब 1200 का स्कोर है।
MultiplyByZer0

23

कलन विधि

while(!game_over)
{
    for each possible move:
        evaluate next state

    choose the maximum evaluation
}

मूल्यांकन

Evaluation =
    128 (Constant)
    + (Number of Spaces x 128)
    + Sum of faces adjacent to a space { (1/face) x 4096 }
    + Sum of other faces { log(face) x 4 }
    + (Number of possible next moves x 256)
    + (Number of aligned values x 2)

मूल्यांकन विवरण

128 (Constant)

यह एक स्थिरांक है, जिसका उपयोग आधार-रेखा के रूप में और परीक्षण जैसे अन्य उपयोगों के लिए किया जाता है।

+ (Number of Spaces x 128)

अधिक स्थान राज्य को अधिक लचीला बनाते हैं, हम 128 से गुणा करते हैं (जो कि माध्यिका है) क्योंकि 128 चेहरों से भरा एक ग्रिड एक इष्टतम असंभव राज्य है।

+ Sum of faces adjacent to a space { (1/face) x 4096 }

यहां हम उन चेहरों का मूल्यांकन करते हैं जिनके विलय की संभावना है, उन्हें पीछे से मूल्यांकन करके, टाइल 2 का मूल्य 2048 हो जाता है, जबकि टाइल 2048 का मूल्यांकन 2 होता है।

+ Sum of other faces { log(face) x 4 }

यहां हमें अभी भी स्टैक्ड मानों की जांच करने की आवश्यकता है, लेकिन कुछ हद तक जो लचीले मापदंडों को बाधित नहीं करता है, इसलिए हमारे पास {x44]} में {x का योग है।

+ (Number of possible next moves x 256)

यदि संभव संक्रमणों की अधिक स्वतंत्रता है तो एक राज्य अधिक लचीला है।

+ (Number of aligned values x 2)

यह उस अवस्था के भीतर विलय होने की संभावना का एक सरलीकृत चेक है, जो बिना लुक-फॉरवर्ड किए हुए है।

नोट: स्थिरांक को ट्विस्ट किया जा सकता है।


2
मैं इसे बाद में संपादित करूंगा, @ nishish712
Khaled.K

9
इस एल्गोरिथ्म का जीत% क्या है?
सीगप्रकाश

आपको एक की आवश्यकता क्यों है constant? यदि आप जो भी कर रहे हैं, वह स्कोर की तुलना कर रहा है, तो उन तुलनाओं के परिणाम को कैसे प्रभावित करता है?
बीकानेर

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

12

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

मैंने सिर्फ 3 और 5 में सर्च-ट्री डेप्थ कटऑफ के साथ अल्फा-बीटा प्रूनिंग के साथ अपने न्यूनतम कार्यान्वयन की कोशिश की। मैं 4X ग्रिड के लिए उसी समस्या को हल करने की कोशिश कर रहा था जो एडएक्स कोर्स कोलंबियाएक्स के लिए प्रोजेक्ट असाइनमेंट : CSMM.1019 आर्टिफिशियल इंटेलिजेंस ( ऐ)

मैंने मुख्य रूप से अंतर्ज्ञान से और ऊपर चर्चा की गई लोगों में से कुछ के संयोजन के उत्तल संयोजन (अलग-अलग हेयरिस्टिक वेट्स) को लागू किया।

  1. दिष्टता
  2. नि: शुल्क स्थान उपलब्ध है

मेरे मामले में, कंप्यूटर प्लेयर पूरी तरह से यादृच्छिक है, लेकिन फिर भी मैंने प्रतिकूल सेटिंग्स ग्रहण की और एआई प्लेयर एजेंट को अधिकतम खिलाड़ी के रूप में लागू किया।

मेरे पास गेम खेलने के लिए 4x4 ग्रिड है।

निरीक्षण:

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

मैंने कोने को भी आंकने की कोशिश की, लेकिन किसी कारण से यह परिणाम खराब कर देता है, किसी भी कारण से?

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

मुझे लगता है कि मिनिमैक्स के बजाय एक्सपेक्टिमैक्स का उपयोग करना बेहतर होगा, लेकिन फिर भी मैं केवल मिनिमैक्स के साथ इस समस्या को हल करना चाहता हूं और 2048 या 4096 जैसे उच्च स्कोर प्राप्त करना चाहता हूं। मुझे यकीन नहीं है कि मैं कुछ भी याद कर रहा हूं।

एआई एजेंट द्वारा कंप्यूटर प्लेयर के साथ खेले गए गेम के अंतिम चरणों को नीचे दिखाया गया है:

यहां छवि विवरण दर्ज करें

किसी भी अंतर्दृष्टि वास्तव में बहुत उपयोगी होगी, अग्रिम धन्यवाद। (यह लेख के लिए मेरे ब्लॉग पोस्ट की लिंक है: https://sandipanweb.wordpress.com/2017/03/06/using-minimax-with-alpha-beta-pruning-and-heuristic-evaluation-to-solve -2048-गेम-संग-संग / और यूट्यूब वीडियो: https://www.youtube.com/watch?v=VnVFilfZ04 )

निम्नलिखित एनीमेशन में दिखाया गया है कि खेल के अंतिम चरण में एआई खिलाड़ी एजेंट 2048 अंक प्राप्त कर सकता है, इस बार निरपेक्ष मूल्य को भी जोड़ा जा सकता है:

यहां छवि विवरण दर्ज करें

निम्नलिखित आंकड़े दिखाते हैं कि खेल के पेड़ को एआई एजेंट द्वारा खोजा गया है जो कंप्यूटर को केवल एक कदम के लिए प्रतिकूल मानता है:

यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें


9

मैंने हास्केल में 2048 सॉल्वर लिखा, मुख्यतः क्योंकि मैं अभी इस भाषा को सीख रहा हूं।

खेल का मेरा कार्यान्वयन वास्तविक खेल से थोड़ा अलग है, जिसमें एक नई टाइल हमेशा '2' (90% 2 और 10% 4 के बजाय) होती है। और यह कि नई टाइल यादृच्छिक नहीं है, लेकिन हमेशा ऊपर बाईं ओर से पहली उपलब्ध है। इस वेरिएंट को Det 2048 के नाम से भी जाना जाता है ।

परिणामस्वरूप, यह सॉल्वर नियतात्मक है।

मैंने एक एग्जॉस्ट अल्गोरिदम का इस्तेमाल किया जो खाली टाइल्स का पक्ष लेता है। यह गहराई से 1-4 के लिए बहुत जल्दी प्रदर्शन करता है, लेकिन गहराई 5 पर यह लगभग 1 सेकंड प्रति चाल पर धीमा हो जाता है।

नीचे हल एल्गोरिदम को लागू करने वाला कोड है। ग्रिड को इंटेगर की 16-लंबाई सरणी के रूप में दर्शाया गया है। और स्कोरिंग खाली वर्गों की संख्या की गणना करके किया जाता है।

bestMove :: Int -> [Int] -> Int
bestMove depth grid = maxTuple [ (gridValue depth (takeTurn x grid), x) | x <- [0..3], takeTurn x grid /= [] ]

gridValue :: Int -> [Int] -> Int
gridValue _ [] = -1
gridValue 0 grid = length $ filter (==0) grid  -- <= SCORING
gridValue depth grid = maxInList [ gridValue (depth-1) (takeTurn x grid) | x <- [0..3] ]

मुझे लगता है कि यह अपनी सादगी के लिए काफी सफल है। खाली ग्रिड से शुरू होने पर और गहराई 5 पर हल करने पर यह परिणाम तक पहुँचता है:

Move 4006
[2,64,16,4]
[16,4096,128,512]
[2048,64,1024,16]
[2,4,16,2]

Game Over

स्रोत कोड यहां पाया जा सकता है: https://github.com/popovitsj/2048-haskell


वास्तविक नियमों के साथ इसे विस्तारित करने का प्रयास करें। हास्केल के यादृच्छिक जनरेटर के बारे में सीखने में यह एक अच्छी चुनौती है!
थॉमस अहले

मैं हास्केल के साथ ऐसा करने की कोशिश करके बहुत निराश हो गया, लेकिन मैं शायद इसे दूसरा प्रयास करने वाला हूं! मैंने पाया कि यादृच्छिकरण के बिना खेल काफी आसान हो जाता है।
wvdz

रैंडमाइजेशन के बिना मुझे पूरा यकीन है कि आप हमेशा 16k या 32k पाने का एक तरीका पा सकते हैं। हालांकि हास्केल में यादृच्छिककरण उतना बुरा नहीं है, आपको बस `बीज 'के चारों ओर से गुजरने का एक तरीका चाहिए। या तो यह स्पष्ट रूप से करते हैं, या यादृच्छिक रैंडम के साथ।
थॉमस अहले

एल्गोरिथ्म को परिष्कृत करना ताकि यह हमेशा गैर-यादृच्छिक गेम के लिए 16k / 32k तक पहुंच जाए, एक और दिलचस्प चुनौती हो सकती है ...
wvdz

आप सही हैं, यह जितना मैंने सोचा था उससे कहीं ज्यादा कठिन है। मैं इस क्रम को खोजने में कामयाब रहा: [UP, LEFT, LEFT, UP, LEFT, DOWN, LEFT] जो हमेशा खेल जीतता है, लेकिन यह 2048 से ऊपर नहीं जाता है। (कोई कानूनी कदम नहीं होने की स्थिति में, चक्र एल्गोरिथ्म सिर्फ चुनता है अगले एक घड़ी की दिशा में)
थॉमस अहले

6

यह एल्गोरिथ्म गेम जीतने के लिए इष्टतम नहीं है, लेकिन प्रदर्शन और कोड की मात्रा के मामले में यह काफी इष्टतम है:

  if(can move neither right, up or down)
    direction = left
  else
  {
    do
    {
      direction = random from (right, down, up)
    }
    while(can not move in "direction")
  }

10
यह बेहतर काम करता है यदि आप कहते हैं कि random from (right, right, right, down, down, up) सभी चालें समान संभावना नहीं हैं। :)
डैरन

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

5
हां, यह खेल के साथ मेरे अपने अवलोकन पर आधारित है। जब तक आपको 4 वीं दिशा का उपयोग नहीं करना है तब तक खेल व्यावहारिक रूप से किसी भी प्रकार के अवलोकन के बिना खुद को हल करेगा। यह "एआई" किसी भी ब्लॉक के सटीक मूल्य की जांच के बिना 512/1024 तक पहुंचने में सक्षम होना चाहिए।
एपीआई-बीस्ट

3
एक उचित एआई ऐसे राज्य में जाने से बचने की कोशिश करेगा जहां वह हर कीमत पर केवल एक दिशा में जा सकता है।
एपीआई-बीस्ट

3
केवल 3 दिशाओं का उपयोग करना वास्तव में एक बहुत ही अच्छी रणनीति है! यह सिर्फ मुझे लगभग 2048 में मैन्युअल रूप से गेम खेलने के लिए मिला। यदि आप इसे 3 शेष चालों के बीच निर्णय लेने के लिए अन्य रणनीतियों के साथ जोड़ते हैं तो यह बहुत शक्तिशाली हो सकता है। यह उल्लेख नहीं करने के लिए कि चुनाव 3 को कम करने से प्रदर्शन पर व्यापक प्रभाव पड़ता है।
wvdz

4

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

खेल के अच्छे खिलाड़ियों का उपयोग करने वाली रणनीति का मॉडल तैयार करें।

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

13 14 15 16
12 11 10  9
 5  6  7  8
 4  3  2  1

ऊपर दिखाए गए क्रम में वर्गों को तब तक पढ़ें जब तक कि अगला वर्ग मान वर्तमान से अधिक न हो। यह इस वर्ग में एक ही मूल्य के दूसरे टाइल को मर्ज करने की कोशिश की समस्या को प्रस्तुत करता है।

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


टाइल को पड़ोसी के साथ विलय की आवश्यकता है लेकिन बहुत छोटा है: इस एक के साथ दूसरे पड़ोसी को मिलाएं।

रास्ते में बड़ी टाइल: एक छोटे से आसपास के टाइल के मूल्य में वृद्धि।

आदि...


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


5
आप उत्तराधिकार के साथ एक स्थानीय खोज का वर्णन कर रहे हैं। यह आपको अटक जाएगा, इसलिए आपको अगली चाल के लिए आगे की योजना बनाने की आवश्यकता है। यह बदले में आपको समाधान की खोज और स्कोरिंग की ओर ले जाता है (निर्णय लेने के लिए)। तो यह वास्तव में किसी भी अन्य प्रस्तुत समाधान से अलग नहीं है।
रनडोस्रन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.