Як написати свого сапера на java за 15 хвилин

Як написати свого сапера на java за 15 хвилин

Нам знадобляться:

  • 15 хвилин вільного часу;
  • Налагоджена робоче середовище, тобто JDK і IDE (наприклад Eclipse);
  • Бібліотека LWJGL (версії 2.x.x) для роботи з Open GL. Зверніть увагу, що для LWJGL версій вище 3 потрібно написати код, що відрізняється від того, що наведено в статті;
  • Іконки для клітин, тобто цифри, прапор, невірно поставлений прапор, міна, що вибухнула міна і закрите поле. Можна чисто символічно намалювати самому, або завантажити що використовувалися при написанні статті.

Робота з графікою

Для роботи з графікою створимо окремий клас - GUI. Від нього нам буде потрібно зберігання всіх графічних елементів управління (тобто полів клітин), визначення елемента, за яким припав клік і передача йому управління, висновок графічних елементів на екран і управління основними функціями OpenGL.

Благо клас GUI буде взаємодіяти з графічними елементами, нам потрібно створити інтерфейс (писати класи сітки, клітин та іншу механіку поки рано), який визначить, що це таке. Логіка підказує, що у графічного елементу повинні бути:

  • Зовнішній вигляд (текстура);
  • координати;
  • Розміри (ширина і висота);
  • Метод, який за переданими координатам кліка визначить, чи потрапив клік по елементу;
  • Метод, який обробить натискання на елемент.

Таким чином, пишемо:

У GUI повинні зберігатися осередки поля. Створимо для цих цілей двовимірний масив:

Тепер розберемося з основними функціями OpenGL. По-перше, нам потрібна ініціалізація.

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

І, нарешті, нам потрібно це зображення взагалі малювати. Для цього пора закінчити enum Sprite. Його елементи будуть представляти із себе обгортку для текстури з легким для читання іменами.

Тепер ми можемо написати метод для GUI. який буде малювати елементи:

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

Створимо клас Cell. який реалізує інтерфейс GUIElement. У методах getWidth () і getHeight () повернемо константу, для координат доведеться створити поля, які будуть инициализироваться конструктором. Так само конструктором будемо передавати стан клітини: "-1", якщо це міна, "-2", якщо це підірвана міна, число хв поблизу в інших випадках. Для цієї мети можна було б використовувати enum, але число хв зручніше передавати як integer, имхо. Отже, конструктор:

Ще два поля - boolean isMarked і boolean isHidden відповідатимуть за те, чи відзначили клітку прапорцем, і відкрили чи її. За замовчуванням обидва прапора виставлені на false.

Розберемося з методом getSprite ().

У разі, якщо на кнопку натиснули, нам знову необхідно розглянути кілька найпростіших випадків:

Щоб при ураженні клітини можна було розкрити, додамо метод:

Для більш зручної реалізації генератора додайте ще й цей метод:

Обробка відповідей від клітин

Повернемося до методу GUI.receiveClick (). Тепер ми не можемо просто повернути результат назад, тому що якщо результат виконання - одиниця, то нам потрібно відкрити сусідні осередки, а в головний керуючий клас повернути вже нуль, в знак того, що все пройшло коректно.

пишемо генератор

Завдання це не складніше, ніж створити масив випадкових boolean-величин. Ідея наступна - для кожного осередку матриці ми генеруємо випадкове число від 0 до 100. Якщо це число менше 15, то в цьому місці записуємо в матрицю міну (таким чином, шанс зустріти міну - 15%). Записавши міну, ми викликаємо у всіх клітин навколо метод incNearMines (). а для тих осередків, де клітина ще не створена зберігаємо значення в спеціальному масиві.

Головний керуючий клас і введення

Створимо клас Main. в ньому вхідний метод - public static void main (String [] args). Цей метод повинен буде робити лише дві речі: викликати ініціалізацію GUI і циклічно викликати робочі методи (input (). GUI.draw () і GUI.update ()), поки не отримає сигнал закриття.

Тут нам не вистачає методу input (). займемося ім.

Метод GUI.gameover () буде просто викликати метод show () у кожної клітини, показуючи таким чином все поле: