1. Успадкування

Робота з ігровим рушієм JavaRush передбачає використання успадкування. А що робити, якщо ви не знаєте, що це таке? З одного боку, у цій темі слід розібратися й вивчити її. З іншого боку, рушій спеціально створено дуже простим, щоб можна було обійтися лише поверхневим знанням успадкування.

Отже, що таке успадкування? Простими словами, успадкування — це зв'язок між двома класами. Один із них є батьком, а другий — нащадком (класом-спадкоємцем). Причому батьківський клас може навіть не знати, що в нього є класи-нащадки. Тобто особливої вигоди від наявності класів-спадкоємців він не отримує.

А от клас-нащадок отримує від успадкування чимало переваг. Головна перевага в тому, що всі змінні й методи батьківського класу з'являються в класі-нащадку, ніби код батьківського класу туди скопіювали. Це не зовсім так, але достатньо для базового розуміння успадкування.

От кілька прикладів для кращого розуміння.

Приклад 1 — найпростіший приклад з успадкуванням

public class Батько
{
}
Клас Нащадок успадковано від класу Батько за допомогою ключового слова extends.
public class Нащадок extends Батько
{
}

Приклад 2 — використання змінних батьківського класу

public class Батько
{
  public int age;
  public String name;
}
Клас Нащадок може використовувати змінні age і 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);
   }
}

Якщо не деталізувати, то можна сказати, що з погляду Java-компілятора ми просто скопіювали код батьківського класу в код класу-нащадка:

public class Нащадок extends Батько
{
   public int age;        // успадкована змінна
   public String name;    // успадкована змінна
   public getName() {     // успадкований метод
      return name;
   }

   public void printInfo()
   {
      System.out.println(getName() + " " + age);
   }
}
клас Нащадок з погляду компілятора


2. Перевизначення методів

Часом виникають такі ситуації: ми успадкували наш клас Нащадок від якогось дуже корисного нам класу Батько разом з усіма його змінними й методами, але деякі з цих методів працюють трохи не так, як нам хочеться, або так, як нам зовсім не хочеться.

Що робити в цій ситуації? Ми можемо перевизначити метод, який нам не сподобався. Зробити це дуже просто: у нашому класі Нащадок ми просто оголошуємо метод із такою самою сигнатурою (заголовком), як у методу класу Батько, і пишемо в ньому свій код.

Приклад 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());
   }
}

У загальних рисах, під час успадкування код батьківського класу копіюється в клас-нащадок. Але якщо в класі-нащадку вже є такий самий метод, як у батьківському класі, то цей метод із батьківського класу не копіюватиметься. У такому разі кажуть, що метод класу-нащадка перекриває (перевизначає) метод батьківського класу. Наведений нижче приклад допоможе вам краще все це зрозуміти.

Отакий вигляд має клас Нащадок із погляду компілятора:
public class Нащадок 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() класу Батько.

А якщо метод printInfo() викликати для об'єкта класу Нащадок, він своєю чергою викличе метод getName() класу Нащадок.

Тобто незважаючи на те, що метод printInfo() оголошено тільки в класі Батько, він викликатиме метод getName() класу Нащадок, якщо цей метод printInfo() викликати для об'єкта типу Нащадок.

Приклад:

Батько parent = new Батько();
parent.printnInfo();
Цей код виведе на екран напис:
Luke
Нащадок child = new Нащадок();
child.printnInfo();
Цей код виведе на екран напис:
I'm your father, Luke

Простими словами, це відбувається тому, що з погляду компілятора код класу Нащадок має такий вигляд:

public class Нащадок extends Батько
{
   public getName() {
      return "I'm your father, Luke";
   }

   public void printInfo()
   {
      System.out.println(getName());
   }
}
клас Нащадок з погляду компілятора


3. Списки

Коротко нагадаємо властивості списків (List). Списки мають чимало спільного з масивами:

  • Можуть зберігати багато даних певного типу.
  • Дають змогу отримувати елементи за їхнім індексом або номером.
  • Індекси елементів нумеруються з 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);
Вилучити елемент зі списку

Докладні відомості про списки наведено в цих статтях:



4. Випадкові числа

Ігровий рушій JavaRush має два методи, які можна використовувати для отримання випадкових чисел. Це такі методи:

int getRandomNumber(int max)
int getRandomNumber(int min, int max)

Перший метод — getRandomNumber(int max): повертає випадкове ціле число в діапазоні 0, 1, 2, …, max-1. Цей метод використовує клас Random із пакету java.util, але принцип роботи з генератором випадкових чисел від цього не змінюється.

Як аргумент методу getRandomNumber(int) потрібно передати ціле число. Це число є верхньою межею чисел, які може повернути генератор. Нижньою межею є 0. Увага! Генератор НІКОЛИ не поверне верхнє граничне число. Наприклад, якщо викликати getRandomNumber(3), він випадковим чином може повернути 0, 1, 2. Як бачите, число 3 він повернути не може. Таке використання генератора є досить простим, але дуже ефективним у багатьох випадках.

Другий метод — getRandomNumber(int min, int max): повертає випадкове ціле число в діапазоні [min, max-1]. Він ніколи не поверне число, менше за min, і ніколи не поверне число, більше за max-1.

Тож як ці методи використовувати на практиці?

1. Гральні кубики

Припустимо, ви хочете імітувати кидок гральних кубиків і отримати випадкове число в діапазоні 1–6. Як це зробити? Це можна зробити за допомогою такого коду:

int dice = getRandomNumber(1, 7);

Такий метод поверне випадкове ціле число в діапазоні 1–6.

2. Стрільба по мішені

Припустімо, вам потрібно імітувати постріл по мішені, і ваш постріл має випадкове відхилення в діапазоні від -10 до +10 включно. Це можна зробити за допомогою такого коду:

int dx = getRandomNumber(-10, 11);

Такий метод поверне випадково ціле число в діапазоні від -10 до +10.

Варіантів застосування випадкових чисел в іграх може бути дуже багато. Все залежить лише від вашої фантазії. Пишіть свої ігри, налаштовуйте їх на свій смак і отримуйте задоволення від процесу.

Грати в ігри можуть всі, а створювати їх — лише програмісти.