JavaRush /جاوا بلاگ /Random-UR /جاوا رش پر سیکشن "گیمز": مفید نظریہ

جاوا رش پر سیکشن "گیمز": مفید نظریہ

گروپ میں شائع ہوا۔
JavaRush کے "گیمز" سیکشن میں آپ کو مشہور کمپیوٹر گیمز لکھنے کے دلچسپ پروجیکٹس ملیں گے۔ کیا آپ مقبول "2048"، "سیپر"، "سانپ" اور دیگر گیمز کا اپنا ورژن بنانا چاہتے ہیں؟ یہ آسان ہے. ہم نے گیم رائٹنگ کو مرحلہ وار عمل میں تبدیل کر دیا ہے۔ بابایک گیم ڈویلپر کے طور پر اپنے آپ کو آزمانے کے لیے، آپ کو ایک جدید پروگرامر بننے کی ضرورت نہیں ہے، لیکن جاوا کے علم کا ایک مخصوص سیٹ ابھی بھی درکار ہے۔ یہاں آپ کو وہ معلومات ملیں گی جو گیمز لکھتے وقت کارآمد ثابت ہوں گی ۔

1. وراثت

JavaRush گیم انجن کے ساتھ کام کرنے میں وراثت کا استعمال شامل ہے۔ لیکن اگر آپ نہیں جانتے کہ یہ کیا ہے؟ ایک طرف، آپ کو اس موضوع کو سمجھنے کی ضرورت ہے: اس کا مطالعہ سطح 11 پر کیا جاتا ہے ۔ دوسری طرف، انجن کو جان بوجھ کر بہت آسان بنانے کے لیے ڈیزائن کیا گیا تھا، تاکہ آپ وراثت کی سطحی معلومات حاصل کر سکیں۔ تو، وراثت کیا ہے؟ بہت آسان الفاظ میں، وراثت دو طبقات کے درمیان تعلق ہے. ان میں سے ایک والدین بن جاتا ہے، اور دوسرا بچہ (جانشین کلاس) بن جاتا ہے۔ اس صورت میں، والدین طبقے کو یہ بھی معلوم نہیں ہوگا کہ اس میں نسلی طبقے ہیں۔ وہ. وراثت کی کلاسوں کی موجودگی سے اسے کوئی خاص فائدہ نہیں ملتا۔ لیکن وراثت نسلی طبقے کو بہت سے فوائد فراہم کرتی ہے۔ اور سب سے اہم یہ ہے کہ پیرنٹ کلاس کے تمام متغیرات اور طریقے چائلڈ کلاس میں ظاہر ہوتے ہیں، گویا پیرنٹ کلاس کا کوڈ چائلڈ کلاس میں کاپی کیا گیا تھا۔ یہ مکمل طور پر درست نہیں ہے، لیکن وراثت کی ایک آسان فہم کے لیے یہ کام کرے گا۔ وراثت کو بہتر طور پر سمجھنے کے لیے یہاں کچھ مثالیں ہیں۔ مثال 1: سادہ ترین وراثت۔
public class Родитель {

}
چائلڈ کلاس کو ایکسٹینڈس کی ورڈ کا استعمال کرتے ہوئے پیرنٹ کلاس سے وراثت ملتی ہے ۔
public class Потомок extends Родитель {

}
مثال 2: پیرنٹ کلاس متغیرات کا استعمال۔
public class Родитель {

   public int age;
   public String name;
}
چائلڈ کلاس پیرنٹ کلاس کی عمر اور نام کے متغیرات کو اس طرح استعمال کر سکتی ہے جیسے اس میں ان کا اعلان کیا گیا ہو۔
public class Потомок extends Родитель {

   public void printInfo() {

     System.out.println(name+" "+age);
   }
}
مثال 3: پیرنٹ کلاس کے طریقے استعمال کرنا۔
public class Родитель {

   public int age;
   public String name;

   public getName() {
      return name;
   }
}
چائلڈ کلاس پیرنٹ کلاس کے متغیرات اور طریقوں کو اس طرح استعمال کر سکتی ہے جیسے اس میں ان کا اعلان کیا گیا ہو۔ اس مثال میں ہم getName () طریقہ استعمال کر رہے ہیں۔
public class Потомок extends Родитель {

   public void printInfo() {

     System.out.println(getName()+" "+age);
   }
}
مرتب کرنے والے کے نقطہ نظر سے Descendant کلاس ایسا لگتا ہے:
public class Потомок extends Родитель {

   public int age; //  унаследованная переменная
   public String name; //  унаследованная переменная

   public getName() { //  унаследованный метод.
      return name;
  }
   public void printInfo() {

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

2. طریقہ اوور رائڈنگ

بعض اوقات ایسے حالات ہوتے ہیں کہ ہم نے اپنی ڈیسنڈنٹ کلاس کو تمام متغیرات اور طریقوں کے ساتھ کچھ بہت ہی کارآمد پیرنٹ کلاس سے وراثت میں حاصل کیا ہے، لیکن کچھ طریقے بالکل اس طرح کام نہیں کرتے جیسے ہم چاہتے ہیں۔ یا بالکل نہیں جس طرح سے ہم نہیں چاہتے۔ اس صورت حال میں کیا کیا جائے؟ ہم ایک ایسے طریقہ کو اوور رائیڈ کر سکتے ہیں جو ہمیں پسند نہیں ہے۔ یہ بہت آسانی سے کیا جاتا ہے: ہماری Descendant کلاس میں ہم صرف اسی دستخط (ہیڈر) کے ساتھ ایک طریقہ کا اعلان کرتے ہیں جیسا کہ پیرنٹ کلاس طریقہ اور اس میں اپنا کوڈ لکھتے ہیں۔ مثال 1: طریقہ اوور رائیڈنگ۔
public class Родитель {

   public String name;

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

   public getName() {
      return name;
  }
}
printInfo() طریقہ جملہ "Luke, No!!!" پرنٹ کرے گا۔
public class Потомок extends Родитель {

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

   public void printInfo() {

      setName("Luke");
      System.out.println( getName());
   }
}
مرتب کرنے والے کے نقطہ نظر سے Descendant کلاس ایسا لگتا ہے:
public Потомок extends Родитель {

   public String name; //  унаследованная переменная

   public void setName (String nameNew) { //  Переопределенный метод взамен унаследованного

       name = nameNew + ", No!!!";
   }
   public getName() { //  унаследованный метод.

      return name;
   }
   public void printInfo() {

     setName("Luke");
     System.out.println(getName());
   }
}
مثال 2: وراثت کا تھوڑا سا جادو (اور طریقہ اوور رائیڈنگ)۔
public class Родитель {

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

     System.out.println(getName());
   }
}
public class Потомок extends Родитель {

   public getName() {
      return "I'm your father, Luke";
  }
}
اس مثال میں: اگر printInfoڈیسنڈنٹ کلاس میں کوئی طریقہ (پیرنٹ کلاس سے) کو اوور رائڈ نہیں کیا گیا ہے، جب اس طریقہ کو ڈیسنڈنٹ کلاس کی کسی چیز پر بلایا جائے گا، تو اس کا طریقہ کہا جائے گا getName()، نہ کہ getName()پیرنٹ کلاس۔
Родитель parent = new Родитель ();
parent.printnInfo();
یہ کوڈ اسکرین پر لکھا ہوا "Luke" دکھاتا ہے ۔
Потомок child = new Потомок ();
child.printnInfo();
یہ کوڈ یہ تحریر دکھاتا ہے "میں تمہارا باپ ہوں، لیوک؛" .
مرتب کرنے والے کے نقطہ نظر سے Descendant کلاس ایسا لگتا ہے:
public class Потомок extends Родитель {

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

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

3. فہرستیں۔

اگر آپ نے ابھی تک فہرستوں سے ملاقات نہیں کی ہے، تو یہاں ایک فوری پرائمر ہے۔ آپ JavaRush کورس کے لیول 6-7 کے بارے میں مکمل معلومات حاصل کر سکتے ہیں ۔ فہرستوں میں صفوں کے ساتھ بہت کچھ مشترک ہے:
  • ایک خاص قسم کے بہت سے ڈیٹا کو ذخیرہ کر سکتے ہیں؛
  • آپ کو عناصر کو ان کے انڈیکس/نمبر کے ذریعہ بازیافت کرنے کی اجازت دیتا ہے۔
  • عنصر کے اشاریے 0 سے شروع ہوتے ہیں۔
فہرستوں کے فوائد: صفوں کے برعکس، فہرستیں متحرک طور پر سائز تبدیل کر سکتی ہیں۔ تخلیق کے فوراً بعد، فہرست کا سائز 0 ہے۔ جیسے جیسے آپ فہرست میں عناصر شامل کرتے ہیں، اس کا سائز بڑھتا جاتا ہے۔ فہرست بنانے کی مثال:
ArrayList<String> myList = new ArrayList<String>(); // создание нового списка типа 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" کی شکل میں میٹرکس کا حوالہ دینے کا رواج ہے۔ یہ گرانٹ کے لئے لیا جانا چاہئے. اب میٹرکس کو اپنے انجن (class Game) پر پیش کرنے کے بارے میں بات کرتے ہیں۔ جیسا کہ آپ جانتے ہیں، انجن میں بہت سے طریقے ہیں جو دیئے گئے نقاط پر کھیل کے میدان کے خلیات کو تبدیل کرتے ہیں۔ مثال کے طور پر، setCellValue(int x, int y, String value). یہ ایک خاص سیل کوآرڈینیٹ (x، y) کے ساتھ قدر پر سیٹ کرتا ہے value۔ جیسا کہ آپ نے دیکھا، یہ طریقہ پہلے بالکل x لیتا ہے، جیسا کہ کلاسیکی کوآرڈینیٹ سسٹم میں ہوتا ہے۔ انجن کے باقی طریقے اسی طرح کام کرتے ہیں۔ گیمز تیار کرتے وقت، اکثر اسکرین پر میٹرکس کی حالت کو دوبارہ پیش کرنے کی ضرورت ہوگی۔ یہ کیسے کریں؟ سب سے پہلے، ایک لوپ میں آپ کو میٹرکس کے تمام عناصر کے ذریعے اعادہ کرنے کی ضرورت ہے۔ دوسرا، ان میں سے ہر ایک کے لیے، INVERTED کوآرڈینیٹس کے ساتھ ڈسپلے کرنے کے لیے ایک طریقہ کال کریں۔ مثال:
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]));
        }
    }
}
قدرتی طور پر، الٹا دو سمتوں میں کام کرتا ہے۔ setCellValueآپ (i، j) کو طریقہ میں پاس کر سکتے ہیں، لیکن ایک ہی وقت میں میٹرکس سے عنصر [j][i] لے سکتے ہیں۔ الٹا تھوڑا مشکل لگ سکتا ہے، لیکن یہ ذہن میں رکھنے کی چیز ہے۔ اور ہمیشہ، اگر کوئی مسئلہ پیدا ہوتا ہے تو، یہ ایک قلم کے ساتھ کاغذ کا ایک ٹکڑا لینے کے قابل ہے، ایک میٹرکس ڈرائنگ اور اس کے ساتھ کیا عمل ہو رہا ہے دوبارہ پیش کرنا.

5. بے ترتیب نمبر

بے ترتیب نمبر جنریٹر کے ساتھ کیسے کام کریں؟ کلاس Gameایک طریقہ کی وضاحت کرتی ہے getRandomNumber(int)۔ ہڈ کے نیچے، یہ Randomjava.util پیکیج سے ایک کلاس استعمال کرتا ہے، لیکن یہ بے ترتیب نمبر جنریٹر کے ساتھ کام کرنے کے اصول کو تبدیل نہیں کرتا ہے۔ دلیل کے طور پر getRandomNumber(int)ایک عدد کو لیتا ہے ۔ یہ نمبر اوپری حد ہوگی جسے جنریٹر واپس کرسکتا ہے۔ نچلی حد 0 ہے۔ اہم! جنریٹر کبھی بھی اوپری باؤنڈ نمبر واپس نہیں کرے گا۔ مثال کے طور پر، اگر getRandomNumber(3)تصادفی طور پر کہا جائے تو یہ 0، 1، 2 واپس کر سکتا ہے۔ جیسا کہ آپ دیکھ سکتے ہیں، یہ 3 واپس نہیں کر سکتا۔ جنریٹر کا یہ استعمال بہت آسان ہے، لیکن بہت سے معاملات میں بہت موثر ہے۔ آپ کو کچھ حدود کے اندر ایک بے ترتیب نمبر حاصل کرنے کی ضرورت ہے: تصور کریں کہ آپ کو کچھ تین ہندسوں والے نمبر (100..999) کی ضرورت ہے۔ جیسا کہ آپ پہلے ہی جانتے ہیں، کم از کم نمبر 0 ہے، لہذا، آپ کو اس میں 100 کا اضافہ کرنا ہوگا، لیکن اس معاملے میں، آپ کو خیال رکھنا ہوگا کہ اوپری حد سے تجاوز نہ کریں۔ 999 کو زیادہ سے زیادہ رینڈم ویلیو کے طور پر حاصل کرنے کے لیے، آپ کو 1000 کی دلیل کے ساتھ طریقہ کو کال کرنا چاہیے۔ getRandomNumber(int)لیکن ہمیں 100 کے بعد کے اضافے کے بارے میں یاد ہے: اس کا مطلب ہے کہ اوپری باؤنڈ کو 100 سے کم کیا جانا چاہیے۔ یعنی حاصل کرنے کے لیے کوڈ بے ترتیب تین ہندسوں کا نمبر اس طرح نظر آئے گا:
int number = 100 + getRandomNumber(900);
لیکن اس طرح کے طریقہ کار کو آسان بنانے کے لیے، انجن ایک ایسا طریقہ فراہم کرتا ہے getRandomNumber(int, int)جو پہلی دلیل کے طور پر واپس آنے کے لیے کم از کم نمبر لیتا ہے۔ اس طریقہ کو استعمال کرتے ہوئے، پچھلی مثال کو دوبارہ لکھا جا سکتا ہے:
int number = getRandomNumber(100, 1000);
بے ترتیب نمبروں کو بے ترتیب صف عنصر حاصل کرنے کے لیے استعمال کیا جا سکتا ہے:
String [] names = {"Andrey", "Валентин", "Сергей"};
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..4] کے اندر 5 نمبر ہیں، جن میں سے ہر ایک 10% کے امکان کے ساتھ واپس آسکتا ہے، جو کہ مجموعی طور پر 50% ہوگا۔ [5..8] کے اندر 4 نمبر ہیں، اور 9 واحد نمبر ہے جو 10% کے امکان کے ساتھ ظاہر ہوتا ہے۔ کوڈ میں، یہ سارا ہوشیار ڈیزائن اور بھی آسان نظر آتا ہے:
int randomNumber = getRandomNumber(10);
if (randomNumber < 5) {
    System.out.println("Проспал ");
} else if (randomNumber < 9) {
    System.out.println("Встал вовремя ");
} else {
    System.out.println("Встал на час раньше положенного ");
}
عام طور پر، بے ترتیب نمبروں کو استعمال کرنے کے لیے بہت سارے اختیارات ہوسکتے ہیں۔ یہ سب صرف آپ کی تخیل پر منحصر ہے. لیکن اگر آپ کو بار بار کچھ نتیجہ حاصل کرنے کی ضرورت ہو تو وہ سب سے زیادہ مؤثر طریقے سے استعمال ہوتے ہیں۔ پھر یہ نتیجہ پچھلے سے مختلف ہوگا۔ کچھ امکان کے ساتھ، یقینا. بس! اگر آپ گیمز سیکشن کے بارے میں مزید جاننا چاہتے ہیں، تو یہاں کچھ مفید دستاویزات ہیں جو مدد کر سکتی ہیں:
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION