हल करने के लिए एक और समस्या के साथ आपका स्वागत है! यदि आप शतरंज और कोडिंग खेलना पसंद करते हैं: तो यह आपके लिए है! आज हम राजा को युद्ध के मैदान में एक और दिन जीवित रहने में मदद करेंगे, साथ ही कोड का एक बड़ा समूह भी लिखेंगे।
आपको शतरंज बोर्ड पर टुकड़ों की स्थिति का प्रतिनिधित्व करने वाले
8
से8
मैट्रिक्स के साथ प्रस्तुत किया जाता है। बोर्ड पर केवल काले राजा और विभिन्न सफेद टुकड़े हैं। इस मैट्रिक्स को देखते हुए, निर्धारित करें कि राजा चेक में है या नहीं।
प्रत्येक टुकड़ा कैसे चलता है, इसके विवरण के लिए देखें
उदाहरण के लिए, निम्नलिखित मैट्रिक्स दिया गया है:
...K.... ........ .B...... ......P. .......R ..N..... ........ .....Q..
आपको True
वापस करना चाहिए , क्योंकि बिशप तिरछे राजा पर हमला कर रहा है।
प्रत्येक टुकड़े की शुरुआती स्थिति और उसकी चाल-सेट को देखते हुए, हम "आसानी से" हर टुकड़े की हर संभव अगली चाल की गणना कर सकते हैं।
और चूंकि वे सभी राजा को जल्द से जल्द पकड़ने में रुचि रखते हैं, इसलिए हम यह मान सकते हैं कि उनका अगला कदम काले राजा को पकड़ने वाला होगा । इसलिए, चूंकि हम काले राजा की स्थिति को भी जानते हैं, हमें केवल यह जांचने की आवश्यकता है कि क्या काले राजा की स्थिति अन्य मोहरों की संभावित अगली चालों में से एक है। यदि ऐसा है, तो अगले सफेद मोड़ के दौरान सफेद टुकड़ा काले राजा को पकड़ने के लिए वहां जाएगा।
चूँकि हम 8x8 ग्राफ़ पर हैं (स्पष्ट होने के लिए, कोई भी अन्य आयाम उसी तरह काम करेगा) और हमारे पास प्रत्येक टुकड़े के शुरुआती निर्देशांक हैं, हम निर्देशांक x, y की श्रृंखला बना सकते हैं जो हमारे टुकड़े अगली चाल होंगे। ऐसा करने के लिए, हम पहले प्रत्येक टुकड़े के लिए एक वर्ग को परिभाषित करते हैं, उसके निर्देशांक को परिभाषित करते हैं और फिर वहाँ से हर संभव चाल की गणना करने के लिए नियमों को परिभाषित करते हैं।
आइए प्यादा के साथ सरल शुरुआत करें। वैसे, मैं इसे पायथन में बना रहा हूं, क्योंकि यह इस समय सबसे लोकप्रिय भाषाओं में से एक है और यकीनन किसी के द्वारा सबसे अधिक पठनीय है। फिर भी, आपको यह जानने की आवश्यकता होगी कि अब से किस वर्ग का पालन किया जा सकता है ।
आइए संक्षेप में समझाते हैं: हम पहले class Pawn
वर्ग और __init__
इसके निर्देशांक x,y
को परिभाषित करते हैं। उसके बाद, हम वहां से प्यादा संभावित चालों की गणना करने के लिए possibleMoves
विधि को परिभाषित करते हैं। प्यादा चालें अपेक्षाकृत आसान होती हैं, इसलिए हम उन्हें केवल चर moves
में जोड़ते हैं, यह जाँचने के बाद कि यह हमारे ग्रिड से बाहर नहीं जाती है, और moves
सरणी वापस कर देता है। यहाँ ध्यान देने योग्य दो बातें, विशेष रूप से प्यादा के लिए:
हम जानबूझकर सामान्य गति को छोड़ देते हैं , क्योंकि हम काले राजा को पकड़ने में रुचि रखते हैं: चूंकि प्यादा केवल तिरछे तरीके से कब्जा कर सकता है और हम टुकड़ों को अन्य दिशाओं में ले जाने की परवाह नहीं करते हैं, हम इसकी सामान्य गति को छोड़ सकते हैं।
अब हम बस मोहरे की चालों को उसके निर्देशांक देकर और possibleMoves
विधि को कॉल करके देख सकते हैं, जैसे: print(Pawn(7,2).possibleMoves())
और हमें [(6,3),(8,3)]
जैसा कुछ प्राप्त करना चाहिए [(6,3),(8,3)]
.
इसके अलावा, आप शीर्ष पर देख सकते हैं कि हमने अपने ग्रिड आयामों को चर के रूप में परिभाषित किया है , इसलिए हम संभवतः उन्हें अन्य आयामों के बोर्डों पर एल्गोरिथम चलाने के लिए बदल सकते हैं।
अब चलो टावर पर चलते हैं।
दोबारा, हम टावर क्लास को इसके निर्देशांक के साथ शुरू करते हैं और possibleMoves
फ़ंक्शन को परिभाषित करते हैं। यहां सभी संभावित चालों को इकट्ठा करने के लिए हम टॉवर दो अक्षों पर सभी बिंदुओं को श्रेणीबद्ध करते हैं और प्रत्येक एकल निर्देशांक को चर moves
में जोड़ते हैं, जो सभी लूपों के बाद वापस आ जाएगा। पहले की तरह, टावर चालों की जांच करने के लिए हम केवल print(Tower(5,3).possibleMoves())
सकते हैं और हमें कुछ इस तरह मिलना चाहिए: [(1,3), (2,3), (3,3), ..., (5,8)]
.
टॉवर की तुलना में बिशप की चालें अधिक जटिल हैं, इसलिए हम यहां क्या हो रहा है, इसकी थोड़ी व्याख्या कर सकते हैं। मूल रूप से हमें इसकी शुरुआती स्थिति से शुरू होने वाले दो विकर्ण अक्षों पर अंक एकत्र करने की आवश्यकता है । क्लास और इनिट मेथड घोषित करने के बाद, हम दो वेरिएबल बनाते हैं: moves
, पहले की तरह, और currentPos
, जिसका उपयोग हम अपने अक्षों के साथ चलते हुए एकत्रित किए गए बिंदुओं पर नज़र रखने के लिए करेंगे। अब while
लूप का उपयोग करते हुए, और यह जाँचते हुए कि हम अपने ग्रिड के बाहर नहीं जा रहे हैं, हम x
और y
उसी के अनुसार बढ़ाते और घटाते हैं जहाँ हम जाना चाहते हैं । उदाहरण के लिए, यदि हम इसकी शुरुआती स्थिति से ऊपर-बाएँ जाना चाहते हैं, तो हमें y
मान को बढ़ाते हुए x
मान को कम करना होगा। यदि हम दाईं ओर नीचे जाना चाहते हैं, तो हमें y
मान को घटाते हुए x
मान को बढ़ाना होगा और इसी तरह आगे भी। अंत में, हम बस एक बार फिर moves
लौटाते हैं।
ठीक है, यहाँ क्या हो रहा है? ठीक है, अगर हम इसके बारे में सोचते हैं, तो रानी के पास बिशप और टावर संयुक्त की समान चालें हैं । वह एक रानी की तुलना में टॉवर के आकार के बिशप मेचा-बॉट की तरह अधिक है। इस कारण से, उसकी चालों को कोडिंग करना वास्तव में सरल है। उसकी कक्षा घोषित करने के बाद हम बस उसकी possibleMoves
बिशप और टावर की संभावित चालों के परिणामस्वरूप चालों के संघ सरणी के रूप में परिभाषित करते हैं।
ध्यान दें कि possibleMoves
फ़ंक्शन में Bishop
और Tower
उदाहरणों को कॉल करते समय उनके पैरामीटर x
और y
self.x, self.y
के रूप में दिया जाता है, इसलिए वे वास्तव में रानी निर्देशांक हैं।
नाइट मेरे लिए सबसे खास है। उसका मूव-सेट अजीब है, जैसे "L" आकार का, इसलिए मुझे इसे कोड करने के लिए विशेष रूप से चतुर या तेज़ तरीका नहीं मिला और मैंने इसकी चालों को हार्ड कोडिंग करना समाप्त कर दिया, बस उसकी शुरुआती स्थिति से उसके द्वारा की जाने वाली 8 संभावित चालों की गणना की।
राजा के बारे में कुछ संक्षिप्त अवधारणाएँ। चूँकि हमें राजा को स्थानांतरित करने की आवश्यकता नहीं है, केवल यह बता देना कि उसने जाँच की है या नहीं, हमें वास्तव में उसके चाल-सेट को लागू करने की आवश्यकता नहीं है । हालाँकि, हम लेख के अंत में एक संक्षिप्त कार्यान्वयन भी देखेंगे। इसके अलावा, इसे कोडिंग करना उतना आसान नहीं है जितना कि रानी की चाल-सेट को कम करना, जैसा कि हम बाद में देखेंगे। तो अभी के लिए, उसकी हरकतों को छोड़ दें और समाधान देखें।
अब हम केवल कुछ निर्देशांक के रूप में एक वेरिएबल blackKing
बनाते हैं। फिर प्रत्येक टुकड़े के लिए हम इसकी कक्षा का एक उदाहरण बनाते हैं जिसे हमने अभी बनाया है और चाल के पूर्ण सेट की गणना करने के लिए possibleMoves
विधि को कॉल करता है। एक बार हमारे पास होने के बाद, हम जांचते हैं कि blackKing
निर्देशांक उन चाल-सेटों में मौजूद हैं या नहीं : यदि वे हैं, तो हम यह प्रिंट करते हैं कि राजा को उस विशेष टुकड़े द्वारा चेक किया गया है। यहाँ परिणाम कुछ इस प्रकार है:
Pawn moves: [(8, 3), (6, 3)] Tower moves: [(1, 3), (2, 3), (3, 3), (4, 3), (6, 3), (7, 3), (8, 3), (5, 1), (5, 2), (5, 4), (5, 5), (5, 6), (5, 7), (5, 8)] Check by the tower! Bishop moves: [(3, 8), (1, 6), (1, 8), (3, 6), (4, 5), (5, 4), (6, 3), (7, 2), (8, 1)] Queen moves: [(4, 3), (5, 4), (6, 5), (7, 6), (8, 7), (2, 1), (2, 3), (1, 4), (4, 1), (1, 2), (2, 2), (4, 2), (5, 2), (6, 2), (7, 2), (8, 2), (3, 1), (3, 3), (3, 4), (3, 5), (3, 6), (3, 7), (3, 8)] Knight moves: [(4, 7), (4, 5), (8, 7), (8, 5), (5, 4), (7, 4), (7, 8), (5, 8)] Check by the knight!
क्या होगा अगर हम यह भी गणना करना चाहते हैं कि क्या राजा के पास अभी भी जीवित रहने की कुछ संभावना है या यह वास्तव में चेक मेट है? इस उद्देश्य के लिए, हमें राजा की चालों के सेट की गणना करने की आवश्यकता है।
आइए इसका थोड़ा वर्णन करें। सबसे पहले, हम अपनी कक्षा को परिभाषित करते हैं और पहले की तरह समन्वय करते हैं। उसके बाद हम possibleMoves
विधि बनाते हैं और राजा की संभावित चालों को कोड करते हैं (फिर से, मुझे पूरा यकीन है कि एक तेज़ तरीका है, लेकिन केवल 8 संभावित चालें हैं इसलिए ...)। उसके बाद, हम जाँचते हैं कि कौन सी चालें अवैध हैं (बोर्ड के बाहर जाएँ) और केवल validMoves
लौटाएँ।
तो अब, यह जाँचने के लिए कि क्या राजा के पास अभी भी जीवित रहने का एक मौका है, हमें यह जाँचने की आवश्यकता है कि क्या उसकी कोई भी संभावित चाल चालों के दूसरे टुकड़े में नहीं है। ऐसा करने के लिए हम केवल बादशाह की चालों और दूसरी चालों पर लूप करते हैं।
इसलिए अभी भी हमारे राजा के बचने की उम्मीद है! उसके लिए भाग्यशाली मुझे लगता है …
सबसे पहले, चूंकि प्रत्येक टुकड़ा एक वर्ग का एक उदाहरण है, हमें उस उदाहरण को आरंभ करने के समय पर विचार करना चाहिए।
रानी को टॉवर और बिशप के संयुक्त कदमों के सेट की जरूरत है। चूंकि समय जटिलता का मूल्यांकन करते समय हमें सबसे खराब परिदृश्य पर ध्यान देना चाहिए , बिशप का टीसी टावर के टीसी पर प्रबल होता है। इस प्रकार, हमें रानी के लिए O(n) के एक टीसी पर भी विचार करना चाहिए।
अंत में, राजा के पास चालों का एक कठिन कोडित सेट होता है, लेकिन एक सत्यापन प्रक्रिया भी शामिल होती है जो लूप के लिए उपयोग करती है । इसलिए तकनीकी रूप से, भले ही राजा की चालें किसी भी मामले में अपेक्षाकृत छोटी हों, हमें उसके tc को O(n) मानना चाहिए, वह भी बोर्ड पर उसकी स्थिति पर निर्भर करता है।
इस बिंदु पर, हम ब्लैक किंग की चेक स्थिति को सत्यापित करने और प्रिंट करने के लिए प्रत्येक टुकड़े के लिए लूप का उपयोग करते हैं। इससे हमें कोई समस्या नहीं होती है जहां टीसी स्थिर है (टॉवर लें, उदाहरण के लिए: हम इसकी 14 चालों की गणना करते हैं और फिर उन पर 14 बार लूप करते हैं, इसलिए हम इसे निश्चित समय भी मान सकते हैं)। फिर भी, जहां tc O(n) या उससे ऊपर है, वहां हमें परेशानी होने वाली है, क्योंकि हम एक लूप जोड़ रहे हैं जो चालों की संख्या बढ़ने पर भी बढ़ेगा।
अंत में, हम चेक मेट को सत्यापित करने के लिए लूप के लिए एक डबल (आंतरिक) का उपयोग करते हैं , जो निश्चित रूप से राजा की चालों की संख्या और अन्य टुकड़ों की चालों के आधार पर O(n²) का एक टीसी होने वाला है।