CodeGym /جاوا بلاگ /Random-UR /CodeGym پر گیمز سیکشن: مفید تھیوری
John Squirrels
سطح
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() طریقہ ظاہر کرے گا "Luke, No!!!"
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. ArrayList کلاس
  2. تصویروں میں اری لسٹ
  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 ہے، تو ہمارے پاس "ایک گھنٹہ جلدی جاگ" ایونٹ ہے۔ یہ سب بہت آسان ہے۔ رینج میں 5 نمبر ہیں [0 ..4]، جن میں سے ہر ایک کو کل 50% کے لیے 10% کے امکان کے ساتھ واپس کیا جا سکتا ہے؛ رینج میں 4 نمبر ہیں [5..8]، ٹھیک ہے، اور 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