CodeGym /Java Blog /এলোমেলো /কোডজিমের গেমস বিভাগ: দরকারী তত্ত্ব
John Squirrels
লেভেল 41
San Francisco

কোডজিমের গেমস বিভাগ: দরকারী তত্ত্ব

এলোমেলো দলে প্রকাশিত
কোডজিমের "গেমস" বিভাগে , আপনি জনপ্রিয় কম্পিউটার গেম লেখার সাথে জড়িত এমন উত্তেজনাপূর্ণ প্রকল্পগুলি খুঁজে পাবেন। জনপ্রিয় গেম 2048, মাইনসুইপার, স্নেক এবং অন্যান্য গেমগুলির নিজস্ব সংস্করণ তৈরি করতে চান? ইহা সহজ. আমরা গেম লেখাকে ধাপে ধাপে প্রক্রিয়ায় পরিণত করেছি। কোডজিমের "গেমস" বিভাগ: দরকারী তত্ত্ব - 1একটি গেম ডেভেলপার হিসাবে আপনার ক্ষমতা পরীক্ষা করার জন্য, আপনাকে একটি উন্নত প্রোগ্রামার হতে হবে না, তবে জাভা জ্ঞানের একটি নির্দিষ্ট সেট প্রয়োজন। এখানে আপনি এমন তথ্য পাবেন যা গেম রাইটিংয়ে কাজে লাগবে

1. উত্তরাধিকার

কোডজিম গেম ইঞ্জিনের সাথে কাজ করা উত্তরাধিকার ব্যবহার করে। কিন্তু যদি আপনি না জানেন যে কি? একদিকে, আপনাকে এই বিষয়টি বুঝতে হবে: এটি লেভেল 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. অ্যারেলিস্ট ক্লাস
  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. প্রাপ্ত নম্বর প্রক্রিয়া করুন।
এক্ষেত্রে সর্বোচ্চ ১০টি হবে। কল করুনgetRandomNumber(10)পদ্ধতি এবং বিশ্লেষণ যে আমরা এটি ফিরে করতে পারেন. এটি 10টি সংখ্যা ফেরত দিতে পারে (0 থেকে 9 পর্যন্ত), প্রতিটি একই সম্ভাবনার সাথে - 10%। এখন আমাদের সমস্ত সম্ভাব্য ফলাফল একত্রিত করতে হবে এবং সেগুলিকে আমাদের সম্ভাব্য ইভেন্টগুলিতে ম্যাপ করতে হবে। আপনার কল্পনা অনেক সম্ভাব্য সংমিশ্রণ নিয়ে ভাবতে পারে, কিন্তু এখানে সবচেয়ে সুস্পষ্ট: "যদি র্যান্ডম সংখ্যাটি পরিসরে থাকে [0..4], তাহলে আমাদের কাছে "ওভারস্লিপ্ট" ইভেন্ট আছে; যদি সংখ্যাটি পরিসরে থাকে [5 ..8], আমাদের কাছে "সময়ে ঘুম থেকে উঠার" ইভেন্ট আছে; এবং যদি সংখ্যাটি 9 হয়, তাহলে আমাদের কাছে "এক ঘণ্টা আগে ঘুম থেকে উঠে" ইভেন্ট রয়েছে। এটি সবই খুব সহজ। পরিসরে 5টি সংখ্যা রয়েছে [0 ..4], যার প্রতিটি 10% সম্ভাব্যতার সাথে ফেরত দেওয়া যেতে পারে, মোট 50% এর জন্য; পরিসরে 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