CodeGym /Java Blog /अनियमित /CodeGym पर गेम अनुभाग: उपयोगी सिद्धांत
John Squirrels
स्तर 41
San Francisco

CodeGym पर गेम अनुभाग: उपयोगी सिद्धांत

अनियमित ग्रुप में प्रकाशित
CodeGym पर "गेम्स" सेक्शन में , आपको रोमांचक प्रोजेक्ट मिलेंगे जिनमें लोकप्रिय कंप्यूटर गेम लिखना शामिल है। लोकप्रिय गेम्स 2048, माइनस्वीपर, स्नेक और अन्य गेम्स का अपना संस्करण बनाना चाहते हैं? यह आसान है। हमने गेम राइटिंग को स्टेप-बाय-स्टेप प्रोसेस में बदल दिया है। CodeGym पर "गेम्स" खंड: उपयोगी सिद्धांत - 1गेम डेवलपर के रूप में अपनी क्षमताओं का परीक्षण करने के लिए, आपको उन्नत प्रोग्रामर होने की आवश्यकता नहीं है, लेकिन जावा ज्ञान का एक विशिष्ट सेट आवश्यक है। यहां आपको वह जानकारी मिलेगी जो गेम राइटिंग में उपयोगी होगी

1. विरासत

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

public class Parent {

}
चाइल्ड क्लास एक्सटेंडेड कीवर्ड का उपयोग करके पैरेंट क्लास को इनहेरिट करता है।

public class Child extends Parent {

}
उदाहरण 2: पैरेंट क्लास के वेरिएबल्स का उपयोग करना।

public class Parent {

   public int age;
   public String name;
}
बाल वर्ग अभिभावक वर्ग की आयु और नाम चर का उपयोग कर सकता है जैसे कि उन्हें मूल वर्ग में घोषित किया गया हो ।

public class Child extends Parent {

   public void printInfo() {

     System.out.println(name+" "+age);
   }
}
उदाहरण 3: मूल वर्ग के तरीकों का उपयोग करना।

public class Parent {

   public int age;
   public String name;

   public getName() {
      return name;
  }
}
चाइल्ड क्लास पेरेंट क्लास के वेरिएबल्स और मेथड्स का इस्तेमाल कर सकती है जैसे कि उन्हें चाइल्ड क्लास में घोषित किया गया हो इस उदाहरण में, हम getName () विधि का उपयोग करते हैं।

public class Child extends Parent {

   public void printInfo() {

     System.out.println(getName()+" "+age);
   }
}
कंपाइलर को चाइल्ड क्लास ऐसा दिखता है :

public class Child extends Parent{

   public int age;  // Inherited variable
   public String name;  // Inherited variable

   public getName() {  // Inherited method.
      return name;
  }
   public void printInfo() {

     System.out.println(getName()+" "+age);
   }
}

2. ओवरराइडिंग तरीके

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

public class Parent {

   public String name;

   public void setName(String nameNew) {
       name = nameNew;
  }

   public getName() {
      return name;
  }
}
PrintInfo () विधि "ल्यूक, नहीं !!!" प्रदर्शित करेगी।

public class Child extends Parent{

   public void setName(String nameNew) {
       name = nameNew + ", No!!!";
  }

   public void printInfo() {
      setName("Luke");
      System.out.println(getName());
   }
}
कंपाइलर को चाइल्ड क्लास ऐसा दिखता है :

public Child extends Parent {

   public String name;  // Inherited variable

   public void setName(String nameNew)  // Overridden method instead of the inherited method {

       name = nameNew + ", No!!!";
   }
   public getName() {  // Inherited method.

      return name;
   }
   public void printInfo() {

     setName("Luke");
     System.out.println( getName());
   }
}
उदाहरण 2: कुछ इनहेरिटेंस मैजिक (और मेथड ओवरराइडिंग)।

public class Parent {

   public getName() {
      return "Luke";
  }
   public void printInfo() {

     System.out.println(getName());
   }
}

public class Child extends Parent {

   public getName() {
      return "Luke, I am your father";
  }
}
इस उदाहरण में, यदि printInfoचाइल्ड क्लास में मेथड (पैरेंट क्लास से) को ओवरराइड नहीं किया जाता है, तो जब इस मेथड को चाइल्ड ऑब्जेक्ट पर कॉल किया जाता है, तो पेरेंट क्लास के मेथड getName()के बजाय इसकी मेथड को कॉल किया जाएगा।getName()

Parent parent = new Parent ();
parent.printnInfo();
यह कोड स्क्रीन पर "ल्यूक" प्रदर्शित करता है।

Child child = new Child ();
child.printnInfo();
यह कोड स्क्रीन पर "ल्यूक, आई एम योर फादर" प्रदर्शित करता है।
कंपाइलर को चाइल्ड क्लास ऐसा दिखता है :

public class Child extends Parent {

   public getName() {
      return "Luke, I am your father";
   }
   public void printInfo() {

     System.out.println(getName());
   }
}

3. सूचियाँ

यदि आप अभी तक सूचियों (सूची) से नहीं मिले हैं, तो यहां एक संक्षिप्त अवलोकन है। आप CodeGym पाठ्यक्रम के स्तर 6-7 में पूरी जानकारी प्राप्त कर सकते हैं । सरणियों के साथ सूचियों में बहुत समानता है:
  • आप एक विशिष्ट प्रकार का बहुत सारा डेटा स्टोर कर सकते हैं;
  • वे आपको उनके सूचकांक द्वारा आइटम प्राप्त करने देते हैं;
  • तत्व सूचकांक 0 से शुरू होते हैं।
सूचियों के लाभ: सरणियों के विपरीत, सूचियाँ गतिशील रूप से आकार बदल सकती हैं। जब कोई सूची बनाई जाती है, तो उसका आकार 0 होता है। जैसे ही आप किसी सूची में आइटम जोड़ते हैं, उसका आकार बढ़ जाता है। यहां सूची बनाने का एक उदाहरण दिया गया है:

ArrayList<String> myList = new ArrayList<String>(); // Create a new ArrayList
कोण कोष्ठक में मान उस डेटा प्रकार को इंगित करता है जिसे सूची संग्रहीत कर सकती है। सूची के साथ काम करने के कुछ तरीके यहां दिए गए हैं:
कोड कोड क्या करता है इसका संक्षिप्त विवरण
ArrayList<String> list = new ArrayList<String>(); तार की नई सूची बनाएँ
list.add("name"); सूची के अंत में एक तत्व जोड़ें
list.add(0, "name"); सूची की शुरुआत में एक तत्व जोड़ें
String name = list.get(5); इसके सूचकांक द्वारा एक तत्व प्राप्त करें
list.set(5, "new name"); किसी तत्व को उसके सूचकांक से बदलें
int count = list.size(); सूची में तत्वों की संख्या प्राप्त करें
list.remove(4); सूची से एक तत्व हटाएं
आप निम्न आलेखों से सूचियों के बारे में अधिक जान सकते हैं:
  1. ऐरेलिस्ट वर्ग
  2. चित्रों में ArrayList
  3. एक ArrayList से एक तत्व हटाना

4. सरणियाँ

एक मैट्रिक्स क्या है? एक मैट्रिक्स एक आयताकार तालिका से ज्यादा कुछ नहीं है जिसे डेटा से भरा जा सकता है। दूसरे शब्दों में, यह द्वि-आयामी सरणी है। जैसा कि आप शायद जानते हैं, जावा में सरणियाँ वस्तुएँ हैं। एक मानक एक आयामी intसरणी इस तरह दिखती है:

int [] array = {12, 32, 43, 54, 15, 36, 67, 28};
हम इसकी कल्पना इस प्रकार कर सकते हैं:
0 1 2 3 4 5 6 7
12 32 43 54 15 36 67 28
शीर्ष पंक्ति कोशिकाओं के पतों को इंगित करती है। दूसरे शब्दों में, संख्या 67 प्राप्त करने के लिए, आपको अनुक्रमणिका 6 के साथ सरणी तत्व तक पहुँचने की आवश्यकता है:

int number = array[6];
यह सब बहुत आसान है। एक द्वि-आयामी सरणी एक-आयामी सरणी की एक सरणी है। यदि आप इसके बारे में पहली बार सुन रहे हैं, तो रुकें और अपने दिमाग में इसकी कल्पना करें। द्वि-आयामी सरणी इस तरह दिखती है:
0 एक आयामी सरणी एक आयामी सरणी
1 एक आयामी सरणी
2 एक आयामी सरणी
3 एक आयामी सरणी
4 एक आयामी सरणी
5 एक आयामी सरणी
6 एक आयामी सरणी
7 एक आयामी सरणी
कोड में:

int [][] matrix = {
{65, 99, 87, 90, 156, 75, 98, 78}, {76, 15, 76, 91, 66, 90, 15, 77}, {65, 96, 17, 25, 36, 75, 54, 78}, {59, 45, 68, 14, 57, 1, 9, 63}, {81, 74, 47, 52, 42, 785, 56, 96}, {66, 74, 58, 16, 98, 140, 55, 77}, {120, 99, 13, 90, 78, 98, 14, 78}, {20, 18, 74, 91, 96, 104, 105, 77} }
0 0 1 2 3 4 5 6 7
65 99 87 90 156 75 98 78
1 0 1 2 3 4 5 6 7
76 15 76 91 66 90 15 77
2 0 1 2 3 4 5 6 7
65 96 17 25 36 75 54 78
3 0 1 2 3 4 5 6 7
59 45 68 14 57 1 9 63
4 0 1 2 3 4 5 6 7
81 74 47 52 42 785 56 96
5 0 1 2 3 4 5 6 7
66 74 58 16 98 140 55 77
6 0 1 2 3 4 5 6 7
120 99 13 90 78 98 14 78
7 0 1 2 3 4 5 6 7
20 18 74 91 96 104 105 77
मान 47 प्राप्त करने के लिए, आपको [4] [2] पर मैट्रिक्स तत्व को संदर्भित करने की आवश्यकता है।

int number = matrix[4][2];
आपने देखा होगा कि मैट्रिक्स निर्देशांक शास्त्रीय आयताकार समन्वय प्रणाली (कार्टेशियन समन्वय प्रणाली) से भिन्न होते हैं। जब आप मैट्रिक्स तक पहुँचते हैं, तो आप पहले y निर्देशांक और फिर x निर्देशांक निर्दिष्ट करते हैं। गणित में, पहले x निर्देशांक निर्दिष्ट करने की प्रथा है, अर्थात (x, y)। आप सोच रहे होंगे: "ठीक है, मैट्रिक्स के अपने प्रतिनिधित्व को क्यों न घुमाएं और फिर (x, y) का उपयोग करके तत्वों को सामान्य तरीके से एक्सेस करें? ऐसा करने से मैट्रिक्स की सामग्री नहीं बदलेगी"। हां, कुछ नहीं बदलेगा। लेकिन प्रोग्रामिंग की दुनिया में, स्वीकृत अभ्यास "पहले y, फिर x द्वारा" मैट्रिसेस तक पहुंचना है। आपको इसे उचित तरीके के रूप में स्वीकार करना चाहिए। अब बात करते हैं मैट्रिक्स को अपने इंजन में प्रोजेक्ट करने की (Gameकक्षा)। जैसा कि आप जानते हैं, इंजन में कई तरीके हैं जो विशिष्ट निर्देशांक पर खेल के मैदान की कोशिकाओं को बदलते हैं। उदाहरण के लिए, setCellValue(int x, int y, String value)विधि। यह मान पैरामीटर के बराबर निर्देशांक (x, y) के साथ एक विशिष्ट सेल सेट करता है। आपने देखा होगा कि क्लासिकल कोऑर्डिनेट सिस्टम की तरह ही इस मेथड में पहले x लगता है। इंजन के अन्य तरीके इसी तरह काम करते हैं। खेल विकसित करते समय, स्क्रीन पर मैट्रिक्स की स्थिति को पुन: पेश करना अक्सर आवश्यक होता है। हम इसे कैसे करते हैं? सबसे पहले, आपको लूप में सभी मैट्रिक्स तत्वों के माध्यम से पुनरावृति करने की आवश्यकता है। दूसरा, रिवर्सड निर्देशांक का उपयोग करके उनमें से प्रत्येक के लिए प्रदर्शन विधि को कॉल करें। उदाहरण के लिए:

private void drawScene() {
    for (int i = 0; i < matrix.length; i++) {
        for (int j = 0; j < matrix[i].length; j++) {
            setCellValue(j, i, String.valueOf(matrix[i][j]));
        }
    }
}
स्वाभाविक रूप से, उलटा दोनों दिशाओं में काम करता है। आप विधि में (i, j) पास कर सकते हैं setCellValueऔर साथ ही मैट्रिक्स से तत्व [j] [i] ले सकते हैं। निर्देशांकों को उलटना थोड़ा कठिन लग सकता है, लेकिन आपको इसे याद रखने की आवश्यकता है। और हमेशा, अगर आपको कोई समस्या आती है, तो आपको कागज का एक टुकड़ा और एक पेन लेना चाहिए, मैट्रिक्स खींचना चाहिए, और मैट्रिक्स से जुड़ी प्रक्रियाओं को पुन: पेश करना चाहिए।

5. यादृच्छिक संख्या

आप एक यादृच्छिक संख्या जनरेटर के साथ कैसे काम करते हैं? वर्ग विधि को Gameपरिभाषित करता है getRandomNumber(int)। हुड के तहत, यह Randomjava.util पैकेज से कक्षा का उपयोग करता है, लेकिन जिस तरह से आप यादृच्छिक संख्या जेनरेटर के साथ काम करते हैं वह नहीं बदलता है। getRandomNumber(int)एक पूर्णांक को एक तर्क के रूप में लेता है। यह संख्या जेनरेटर द्वारा लौटाई जा सकने वाली राशि की ऊपरी सीमा होगी। निचली सीमा 0 है। महत्वपूर्ण! जनरेटर कभी भी ऊपरी सीमा संख्या नहीं लौटाएगा। उदाहरण के लिए, यदि आप कॉल करते हैं getRandomNumber(3), तो यह बेतरतीब ढंग से 0, 1, या 2 लौटाएगा। जैसा कि आप देख सकते हैं, यह 3 वापस नहीं आ सकता है। इस तरह जनरेटर का उपयोग करना काफी सरल है, लेकिन कई मामलों में अत्यधिक प्रभावी है। मान लीजिए कि आपको किसी श्रेणी में एक यादृच्छिक संख्या प्राप्त करने की आवश्यकता है: कल्पना करें कि आपको [100..999] श्रेणी में तीन अंकों की संख्या की आवश्यकता है। जैसा कि आप पहले से ही जानते हैं, लौटाई गई न्यूनतम संख्या 0 है। इसलिए आपको 100 जोड़ने की आवश्यकता होगी। लेकिन इस मामले में, आपको ध्यान रखना होगा कि ऊपरी सीमा से अधिक न हो। अधिकतम यादृच्छिक मान के रूप में 999 प्राप्त करने के लिए, कॉल करेंgetRandomNumber(int)तर्क 1000 के साथ विधि। लेकिन अब हमें याद है कि हम परिणाम में 100 जोड़ रहे हैं: इसका मतलब है कि ऊपरी सीमा को 100 से कम किया जाना चाहिए। दूसरे शब्दों में, हमारे यादृच्छिक तीन अंकों की संख्या प्राप्त करने के लिए कोड इस तरह दिखेगा :

int number = 100 + getRandomNumber(900);
लेकिन इस प्रक्रिया को सरल बनाने के लिए, इंजन वह getRandomNumber(int, int)तरीका प्रदान करता है जिसका पहला पैरामीटर वापसी के लिए न्यूनतम संख्या है। इस पद्धति का उपयोग करके, पिछले उदाहरण को निम्नानुसार फिर से लिखा जा सकता है:

int number = getRandomNumber(100, 1000);
यादृच्छिक सरणी तत्व प्राप्त करने के लिए यादृच्छिक संख्या का उपयोग किया जा सकता है:

String [] names = {"Sarah", "Val", "Sergey"};
String randomName = names[getRandomNumber(names.length)]
कुछ घटनाओं को कुछ संभावना के साथ उत्पन्न करना। मनुष्यों के लिए, सुबह की शुरुआत कुछ संभावित परिदृश्यों के साथ होती है: अधिक सोना - 50% संभावना; समय पर उठा - 40% संभावना; एक घंटा जल्दी उठा - 10% संभावना। कल्पना कीजिए कि आप सुबह का परिणाम जनरेटर लिख रहे हैं। आपको एक निश्चित संभावना के साथ ईवेंट उत्पन्न करने की आवश्यकता है। ऐसा करने के लिए, आपको फिर से एक यादृच्छिक संख्या जनरेटर का उपयोग करने की आवश्यकता है। विभिन्न कार्यान्वयन संभव हैं, लेकिन सबसे सरल निम्नलिखित एल्गोरिथम पर आधारित होना चाहिए:
  1. संख्या उत्पन्न करने के लिए उपयोग की जाने वाली सीमा निर्धारित करें;
  2. एक यादृच्छिक संख्या उत्पन्न करें;
  3. प्राप्त संख्या को संसाधित करें।
इस स्थिति में, अधिकतम 10 होगी। कॉल करेंgetRandomNumber(10)विधि और विश्लेषण करें कि हम इसे वापस कर सकते हैं। यह 10 नंबर (0 से 9 तक) वापस कर सकता है, प्रत्येक समान संभावना के साथ - 10%। अब हमें सभी संभावित परिणामों को संयोजित करने और उन्हें हमारे संभावित ईवेंट में मैप करने की आवश्यकता है। आपकी कल्पना कई संभावित संयोजनों के बारे में सोच सकती है, लेकिन यहां सबसे स्पष्ट है: "यदि यादृच्छिक संख्या [0..4] की सीमा में है, तो हमारे पास "ओवरस्लेप्ट" घटना है; यदि संख्या [5 की सीमा में है ..8], हमारे पास "समय पर जाग गया" घटना है; और यदि संख्या 9 है, तो हमारे पास "एक घंटे पहले उठो" घटना है। यह सब बहुत आसान है। [0] श्रेणी में 5 संख्याएँ हैं ..4], जिनमें से प्रत्येक को कुल 50% के लिए 10% की संभावना के साथ लौटाया जा सकता है; श्रेणी [5..8] में 4 संख्याएँ हैं, और 9 केवल एक संख्या है जो इसके साथ दिखाई देती है 10% की संभावना।

int randomNumber = getRandomNumber(10);
if (randomNumber < 5) {
    System.out.println("Overslept");
} else if (randomNumber < 9) {
    System.out.println("Woke up on time");
} else {
    System.out.println("Woke up an hour early");
}
सामान्य तौर पर, यादृच्छिक संख्याओं का उपयोग करने के कई तरीके हैं। आप केवल अपनी कल्पना से ही सीमित हैं। लेकिन अगर आपको बार-बार कुछ परिणाम प्राप्त करने की आवश्यकता है तो वे सबसे प्रभावी ढंग से उपयोग किए जाते हैं। तब नया परिणाम पिछले वाले से भिन्न होगा। कुछ संभावना के साथ, बिल्कुल। अभी के लिए इतना ही! यदि आप "गेम्स" अनुभाग के बारे में अधिक जानना चाहते हैं, तो यहां कुछ उपयोगी दस्तावेज दिए गए हैं जो मदद कर सकते हैं:
टिप्पणियां
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION