XSLT पर इंटरएक्टिव गेम

छवि

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

जहाँ XML है, वहाँ XSLT है, एक भाषा जो XML दस्तावेज़ों को बदलने के लिए डिज़ाइन की गई है। यह भाषा विशिष्ट है, लेकिन ट्यूरिंग के अनुसार पूर्णता की संपत्ति है। इसलिए, भाषा "असामान्य" उपयोग के लिए उपयुक्त है। यहाँ, उदाहरण के लिए, 8 रानियों की समस्या का समाधान है । तो, आप एक खेल लिख सकते हैं।

अधीर के लिए: JSFiddle पर एक काम कर रहे कार्यक्रम, GitHub पर स्रोत।

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

छवि

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

XSLT प्रोग्राम को रनटाइम की आवश्यकता होती है। XSLT निष्पादित करने में सक्षम सबसे आम रनटाइम किसी भी आधुनिक ब्राउज़र है । हम XSLT संस्करण 1.0 का उपयोग करेंगे, क्योंकि यह बॉक्स से ब्राउज़र द्वारा समर्थित है।

XSLT और XPath के बारे में थोड़ा


XSLT एक XML दस्तावेज़ परिवर्तन भाषा है; एक्सपीथ का उपयोग एक्सएमएल दस्तावेज़ के कुछ हिस्सों तक पहुंचने के लिए किया जाता है। इन भाषाओं के लिए विनिर्देश w3.org: XSLT संस्करण 1.0 और XPath संस्करण 1.0 पर प्रकाशित होते हैं।

XSLT और XPath की मूल बातें और उपयोग के उदाहरण आसानी से नेट पर खोजे जाते हैं। यहाँ मैं उन विशेषताओं की ओर ध्यान आकर्षित करता हूँ जिन पर विचार करने की आवश्यकता है जब XSLT को "सामान्य" सामान्य-उद्देश्य वाली उच्च-स्तरीय प्रोग्रामिंग भाषा के रूप में उपयोग करने की कोशिश की जा रही है।

एक्सएसएलटी ने कार्यों को नाम दिया है। उन्हें एक तत्व घोषित किया जाता है।

<xsl:template name="function_name"/> 

और इस तरह कहा जाता है:

 <xsl:call-template name="function_name"/> 

कार्यों में पैरामीटर हो सकते हैं।

घोषणा:

 <xsl:template name="add"> <xsl:param name="x"/> <xsl:param name="y"/> <xsl:value-of select="$x + $y"/> </xsl:template> 

मापदंडों के साथ फंक्शन कॉल:

 <xsl:call-template name="add"> <xsl:with-param name="x" select="1"/> <xsl:with-param name="y" select="2"/> </xsl:call-template> 

पैरामीटर में डिफ़ॉल्ट मान हो सकते हैं।

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

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

XPath चार बुनियादी डेटा प्रकारों को परिभाषित करता है: स्ट्रिंग, संख्या, बूलियन और नोड-सेट। XSLT एक पांचवें प्रकार को जोड़ता है - एक परिणाम वृक्ष का टुकड़ा। यह खंड नोड-सेट की तरह दिखता है, लेकिन इसके साथ आप सीमित संचालन कर सकते हैं। इसे पूरी तरह से XML आउटपुट डॉक्यूमेंट में कॉपी किया जा सकता है, लेकिन आप चाइल्ड नोड्स तक नहीं पहुंच सकते।

 <xsl:variable name="board"> <cell>1</cell> <cell>2</cell> <cell>3</cell> <cell>4</cell> </xsl:variable> 

बोर्ड चर में XML दस्तावेज़ का एक टुकड़ा होता है। लेकिन बच्चे के नोड्स तक नहीं पहुंचा जा सकता है। यह कोड मान्य नहीं है:

 <xsl:for-each select="$board/cell"/> 

आपको जो सबसे अच्छा मिल सकता है, वह टुकड़े के पाठ नोड्स तक पहुंच सकता है और उनके साथ स्ट्रिंग के रूप में काम कर सकता है:

 <xsl:value-of select="substring(string($board), 2, 1)"/> 

"2" लौटाएगा।

इस वजह से, हमारे खेल में, बोर्ड (या खेल का मैदान) को एक स्ट्रिंग के रूप में प्रस्तुत किया जाएगा ताकि इसे मनमाने ढंग से हेरफेर किया जा सके।

XSLT आपको xsl का उपयोग करके नोड-सेट को पुनरावृत्त करने की अनुमति देता है: प्रत्येक निर्माण के लिए। लेकिन भाषा में छोरों के लिए या सामान्य नहीं है। इसके बजाय, आप एक पुनरावर्ती फ़ंक्शन कॉल (पुनरावृत्ति और पुनरावृत्ति isomorphic हैं) का उपयोग कर सकते हैं। A..b में x के लिए फॉर्म का एक लूप इस तरह व्यवस्थित किया जाएगा:

 <xsl:call-template name="for_loop"> <xsl:with-param name="x" select="$a"/> <xsl:with-param name="to" select="$b"/> </xsl:call-template> <xsl:template name="for_loop"> <xsl:param name="x"/> <xsl:param name="to"/> <xsl:if test="$x < $to"> <!--  -  --> <xsl:call-template name="for_loop"> <xsl:with-param name="x" select="$x + 1"/> <xsl:with-param name="to" select="$to"/> </xsl:call-template> </xsl:if> </xsl:template> 

एक रनटाइम लिखना


कार्यक्रम की आवश्यकता है: 3 XSLT, स्रोत XML, उपयोगकर्ता इनपुट (पैरामीटर), आंतरिक स्थिति XML और आउटपुट XML।

हम HTML फाइल में पहचानकर्ता के साथ टेक्स्ट फ़ील्ड रखते हैं: "प्रीप्रोसेसर-xslt", "प्रोसेसर-xslt", "पोस्टप्रोसेसर-xslt", "इनपुट-xml", "पैरामीटर", "आउटपुट-xml", "पोस्टप्रोसेसर-xml"। हम परिणाम को पृष्ठ में (विज़ुअलाइज़ेशन के लिए) एम्बेड करने के लिए भी जगह देते हैं।

दो बटन जोड़ें: प्रोसेसर का प्रारंभ और कॉल (चरण)।

कुछ जावास्क्रिप्ट कोड लिखते हैं।

एक प्रमुख विशेषता XSLT परिवर्तन का उपयोग है।
 function transform(xslt, xml, params) { var processor = new XSLTProcessor(); var parser = new DOMParser(); var xsltDom = parser.parseFromString(xslt, "application/xml"); // TODO: check errors .documentElement.nodeName == "parsererror" var xmlDom = parser.parseFromString(xml, "application/xml"); processor.importStylesheet(xsltDom); if (typeof params !== 'undefined') { params.forEach(function(value, key) { processor.setParameter("", key, value); }); } var result = processor.transformToDocument(xmlDom); var serializer = new XMLSerializer(); return serializer.serializeToString(result); } 


प्रीप्रोसेसर, प्रोसेसर और पोस्टप्रोसेसर के कार्य:
 function doPreprocessing() { var xslt = document.getElementById("preprocessor-xslt").value; var xml = document.getElementById("input-xml").value; var result = transform(xslt, xml); document.getElementById("output-xml").value = result; } function doProcessing() { var params = parseParams(document.getElementById("parameters").value); var xslt = document.getElementById("processor-xslt").value; var xml = document.getElementById("output-xml").value; var result = transform(xslt, xml, params); document.getElementById("output-xml").value = result; } function doPostprocessing() { var xslt = document.getElementById("postprocessor-xslt").value; var xml = document.getElementById("output-xml").value; var result = transform(xslt, xml); document.getElementById("postprocessed-xml").value = result; document.getElementById("output").innerHTML = result; } 


सहायक फ़ंक्शन parseParams () उपयोगकर्ता इनपुट को कुंजी = मान जोड़े में देता है।

इनिशियलाइज़ेशन बटन कॉल करता है
 function onInit() { doPreprocessing(); doPostprocessing(); } 


प्रोसेसर प्रारंभ बटन
 function onStep() { doProcessing(); doPostprocessing(); } 


बेसिक रनटाइम तैयार है।

इसका उपयोग कैसे करें। उपयुक्त क्षेत्रों में तीन XSLT दस्तावेज़ डालें। XML इनपुट दस्तावेज़ डालें। "Init" बटन दबाएं। यदि आवश्यक हो, तो पैरामीटर फ़ील्ड में आवश्यक मान दर्ज करें। स्टेप बटन पर क्लिक करें।

एक खेल लेखन


यदि किसी और ने अनुमान नहीं लगाया है, तो शीर्षक से इंटरएक्टिव गेम क्लासिक 3 बाय 3 टिक-टैक-टो है।

खेल का मैदान एक 3 से 3 तालिका है, जिनमें से कोशिकाओं को 1 से 9 तक गिना जाता है।
मानव खिलाड़ी हमेशा पार करता है (प्रतीक "X"), कंप्यूटर - शून्य ("O")। यदि सेल को क्रॉस या शून्य पर कब्जा कर लिया जाता है, तो संबंधित अंक को "X" या "O" चिन्ह से बदल दिया जाता है।

खेल की स्थिति इस फॉर्म के XML दस्तावेज़ में समाहित है:

 <game> <board>123456789</board> <state></state> <beginner></beginner> <message></message> </game> 

<बोर्ड /> तत्व में खेल का मैदान होता है; <राज्य /> - खेल की स्थिति (खिलाड़ियों में से एक या ड्रॉ या गलती से जीतना); <शुरुआती /> तत्व का उपयोग यह निर्धारित करने के लिए किया जाता है कि किसने वर्तमान गेम शुरू किया (ताकि कोई अन्य खिलाड़ी अगला गेम शुरू करे); <संदेश /> - खिलाड़ी के लिए संदेश।

प्रीप्रोसेसर मध्यस्थ के XML दस्तावेज़ से एक प्रारंभिक स्थिति (खाली फ़ील्ड) बनाता है।

प्रोसेसर उपयोगकर्ता इनपुट को मान्य करता है, इसकी चाल को लागू करता है, खेल की स्थिति की गणना करता है, कंप्यूटर की चाल की गणना करता है और लागू करता है।

छद्म कोड पर, यह कुछ इस तरह दिखता है
 fn do_move() { let board_after_human_move = apply_move(board, "X", param) let state_after_human_move = get_board_state(board_after_human_move) if state_after_human_move = "" { let board_after_computer_move = make_computer_move(board_after_human_move) let state_after_computer_move = get_board_state(board_after_computer_move) return (board_after_computer_move, state_after_computer_move) } else { return (board_after_human_move, state_after_human_move) } } fn apply_move(board, player, index) { //     board    index   player     } fn get_board_state(board) { //   "X",   , "O",   , "tie"          } fn make_computer_move(board) { let position = get_the_best_move(board) return apply_move(board, "O", position) } fn get_the_best_move(board) { return get_the_best_move_loop(board, 1, 1, -1000) } fn get_the_best_move_loop(board, index, position, score) { if index > 9 { return position } else if cell_is_free(board, index) { let new_board = apply_move(board, "O", index) let new_score = minimax(new_board, "X", 0) if score < new_score { return get_the_best_move_loop(board, index + 1, index, new_score) } else { return get_the_best_move_loop(board, index + 1, position, score) } } else { return get_the_best_move_loop(board, index + 1, position, score) } } fn cell_is_free(board, index) { //   true,    board   index   ( ) } fn minimax(board, player, depth) { let state = get_board_state(board) if state = "X" { //   return -10 + depth } else if state = "O" { //   return 10 - depth } else if state = "tie" { //  return 0 } else { let score = if player = "X" { 1000 } else { -1000 } return minimax_loop(board, player, depth, 1, score) } } fn minimax_loop(board, player, depth, index, score) { if index > 9 { return score } else if cell_is_free(board, index) { //   ,    let new_board = apply_move(board, player, index) let new_score = minimax(new_board, switch_player(player), depth + 1) let the_best_score = if player = "X" { //    if new_score < score { new_score } else { score } } else { //    if new_score > score { new_score } else { score } } return minimax_loop(board, player, depth, index + 1, the_best_score) } else { //      return minimax_loop(board, player, depth, index + 1, score) } } fn switch_player(player) { //   ; X -> O, O -> X } 


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

यह एल्गोरिदम बड़ी संख्या में पुनरावर्ती कॉल का उपयोग करता है और कंप्यूटर के पहले कदम की गणना मेरी मशीन पर 2-3 सेकंड तक की जाती है। हमें किसी तरह तेज करना चाहिए। आप सभी संभव स्वीकार्य जुआ क्षेत्र की स्थितियों के लिए कंप्यूटर के सर्वश्रेष्ठ चाल को सरल रूप से ले और पूर्व-गणना कर सकते हैं। ऐसे राज्य 886 निकले। क्षेत्र की सड़ांध और प्रतिबिंबों के कारण इस संख्या को कम करना संभव है, लेकिन यह आवश्यक नहीं है। नया संस्करण तेज है।

यह खेल मैदान को खूबसूरती से प्रदर्शित करने का समय है। अगर यह कुछ है तो क्या उपयोग करना चाहिए? ग्राफिक्स आकर्षित करना चाहिए (यार्ड में 21 वीं सदी, ग्राफिक्स के बिना किस तरह का खेल?) और बी) एक्सएमएल प्रारूप होना वांछनीय है? बेशक एसवीजी!

पोस्टप्रोसेसर एक चेकर क्षेत्र को खींचता है और इसमें हरे क्रॉस, नीले जीरो और छोटे काले कपड़े की व्यवस्था करता है । यह खेल के अंत के बारे में संदेश भी दिखाता है।

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

हम रनटाइम और पोस्टप्रोसेसर को अंतिम रूप दे रहे हैं।

रनटाइम में, एसवीजी तत्व पर क्लिक करने की प्रतिक्रिया समारोह जोड़ें:

 function onSvgClick(arg) { document.getElementById("parameters").value = arg; onStep(); } 

पोस्टप्रोसेसर में हम प्रत्येक सेल के ऊपर एक वर्ग जोड़ते हैं (पारदर्शिता rect.btn शैली द्वारा निर्दिष्ट होती है) वर्ग, जब क्लिक किया जाता है, तो सेल नंबर के साथ एक फ़ंक्शन कहा जाता है:

 <rect class="btn" x="-23" y="-23" width="45" height="45" onclick="onSvgClick({$index})"/> 

बैच पूरा होने के बाद, किसी भी सेल पर क्लिक करने से एक नई शुरुआत होती है। "Init" बटन को केवल शुरुआत में एक बार दबाया जाना चाहिए।

अब आप खेल समाप्त होने पर विचार कर सकते हैं। बात छोटी है: इनसाइट्स को छिपाएं, इसे एक इलेक्ट्रॉन एप्लिकेशन में पैक करें, इसे स्टीम पर रखें,,, अमीर और प्रसिद्ध को जागृत करें।

निष्कर्ष


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

Source: https://habr.com/ru/post/hi441478/


All Articles