JavaRush /Java блог /Random UA /Розрахована на багато користувачів консольна гра на java
timurnav
21 рівень

Розрахована на багато користувачів консольна гра на java

Стаття з групи Random UA
Всім привіт, давно вже дописав гру, все ніяк не доходабо руки до написання статті, вона є логічним продовженням цієї писуліни Якщо ви поки що не пробували робити щось крім завдань JavaRush, то знайомство з грою буде саме тим, з чого потрібно буде почати підготовку до тестових завдань реального проекту, в якому я рекомендую взяти участь кожному. Та й взагалі час вже перестати бути сферичним програмістом у вакуумі і почати вивчати щось за межами java-core. Для того, щоб просто подивитися гру, у вас має бути встановлений MySQL, якщо ви поки що таким не користувалися, не соромтеся – ставте, це одна з тих баз даних, які ви будете використовувати у своїй роботі та особистих проектах! Я не наводитиму опис установки та роботи з базою, в інтернеті навалом туторіалів та відео, рекомендую розібратися з цим питанням самостійно, це теж один з найважливіших скілів програміста – розбиратися самостійно.hibernate , spring, spring data, можливо, список можна продовжити, але мої знання на цьому закінчуються. А тепер відкладіть читання цієї статті та розберіться з MySQL, це насправді зовсім не складно, вам потрібно поставити сам сервер, з налаштувань там лише логін та пароль. потім почитайте про те які команди застосовуються при роботі. Команди для роботи із сервером: create , show, use, та інші, команда help– дасть повний перелік команд. Запити до роботи з конкретною таблицею: select , insert,deleteта інші. особливо сильно не заглиблюйтесь, є ймовірність, що від простого читання команд запам'ятається лише мала частина. ви все вивчите з часом. Можете пограти в терміналі MySQL, створіть базу даних, створіть таблички, заповніть їх, зробіть запит на виведення даних, додайте критерії запитів. Швидше за все, у вас на цій піде не більше 2-3 годин, якщо довше - не засмучуйтеся, з досвідом ви освоюватимете новий матеріал швидше. Якщо з базами у вас проблем немає, то можна приступати до розробки гри, за основу взято гру, про яку я вже писав хрестики-нуліки. Я дуже довго не міг розібратися з тим, як реалізувати мультиплеєр, вихід я знайшов у використанні БД. Процес гри передбачає, що гравці ходять по черзі, всі зміни в грі фіксуються в базі даних. вже виходячи з цього ми розуміємо, що у нас є гравець і є ігрове поле, яке містить посилання на гравців, саме в ігровому полі має бути зав'язана логіка, в якій один гравець перебуває в очікуванні ходу другого гравця і після чого їх ролі змінюються і вже перший гравець робить хід, а другий чекає. Оскільки всі зміни повинні дублюватися в БД, то після кожного ходу нам потрібно зберігати поле. Отже ми дійшли першого висновку, в Базі даних має бути ігрове поле і якщо ми говоримо про мультиплеєрі, то потрібно туди додати і гравців. Створимо таблиці в MySQL, я зробив це нативно, через вікно терміналу mysql. Гравці у нас мають:
  • id- Порядковий номер, ми його робимо первинним ключем;
  • name- Звичайне ім'я, рядок;
  • wins– кількість перемог;
  • loses– кількість поразок;
  • games- Загальна кількість проведених ігор.
Таблиця з іграми:
  • id- Порядковий номер, ми його робимо первинним ключем;
  • x– id гравця граючого х– вторинний ключ;
  • o– id гравця граючого o– вторинний ключ;
  • field- саме поле, про його формат буде написано нижче;
  • status- Це потрібно для коректної роботи мультиплеєра, статус характеризує стан гри:
    створена, граємо, гра закінчена

  • current- теж для мультиплеєра, саме під час гри це поле управляє тим чий зараз хід,
    а після її закінчення воно оголошує переможця або нічию

З таблицями розібралися, тепер потрібно створити Java-класи з відповідними полями – Gameта User.
public class Game {
    private Integer id;
    private Integer x;
    private Integer y;
    private Integer field;
    private String status;
    private String current;
}
public class User {
    private Integer id;
    private String name;
    private Integer wins;
    private Integer loses;
    private Integer games;
    private Boolean busy;
}
Додамо порожній конструктор без параметрів – для роботи з БД та ще один конструктор, яким ми створюватимемо об'єкти. додамо сеттери та гетери для всіх полів. Тепер розберемося з hibernate :) час від часу не легше. Тут трохи складніше, ніж з MySQL, я швидко пройдуся за загальною структурою. Знову ж таки не все так складно, основи можна засвоїти через будь-який туторіал за пару-трійку годин, а поглиблено вже краще вивчати в процесі написання своїх проектиків. Робота з БД з JAVA має на увазі використання JDBC, почитайте про нього у вікі . Але якщо користуватися ним у написанні коду, то це принесе дуже багато болю в задньому проході деяку складність у написанні класів DAO ( теж вікі), hibernate трохи покращить ситуацію, з ним у вас буде набагато менше повторюваного (шаблонного) коду. Для того, щоб працювати hibernate, до проекту необхідно підключити бібліотеку, робиться це дуже просто: Ctrl+Alt+Shift+S(File-Project Structure), заходимо у вкладку Libraries, натискаємо "+" і додаємо попередньо завантажену бібліотеку (як варіант , звідси ). Для того, щоб зв'язати класи Userі Gameвам потрібно використовувати інструкції – вони дуже прості у використанні, з ними код виглядає так:
@Entity
@Table(name="games")
public class Game {
    private Integer id;
    private Integer x;

    @Id
    @GeneratedValue
    @Column(name = "id")
    public Integer getId() {
        return id;
    }

    @Column(name = "x")
    public Integer getX() {
        return x;
    }
}
Тут все просто,
  • @Entity- Каже, про те що клас є "сутністю", простими словами, вона прив'язана до таблиці в БД.
  • @Table(name="games")– говорить від того до якої саме таблиці, games– назва таблиці у БД
  • @Id, @GeneratedValue, @Column(name = "id")– цими трьома анотаціями позначаємо, що це поле є ідентифікаційним, що генерується автоматично, а стовпець у БД називається id.
  • @Column(name = "x")- Ім'я стовпця в БД.
Далі необхідно побудувати рівні – рівень DAO та рівень обслуговування. Якщо спростити все до умов вакууму, то робота з даними йде через сервісний рівень, це один із рівнів абстракції, він дозволяє зробити роботу програми більш незалежною, щоб розробник логіки гри не вдавався в подробиці налаштування доступу до БД, або наприклад, якщо раптом ми замість простого hibernate вирішабо використати spring, зміни не підуть далі сервісного шару, без якого довелося б переписувати половину програми! це є одним із патернів проектування. Починаємо писати рівень DAO.
public class UserDAO {

    public void addUser(User user) throws SQLException {
        Session session = null;
        try{
            session = HibernateUtil.getSessionFactory().openSession();
            session.beginTransaction();
            session.save(user);
            session.getTransaction().commit();
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            if (session != null && session.isOpen()) {
                session.close();
            }
        }
    }
}
Так виглядає операція додавання нового користувача в бд, зверніть увагу, що метод передається тільки об'єкт класу-сутності, ніякої додаткової інформації тут не потрібно. це забезпечується тим, що ми отримуємо вже готову сесію зв'язку з БД із класу HibernateUtil. Розглянемо його.
public class HibernateUtil {
    private static SessionFactory sessionFactory = null;

    static {
        try {

            sessionFactory = new Configuration().configure().buildSessionFactory();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}
Як ви бачите тут теж все дуже просто, SessionFactoryце інтерфейс з бібліотеки hibernate, яку ми підключабо до нашого проекту. Для коректної роботи залишається лише заповнити конфігураційний файл hibernate.cfg.xml
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/tictactoe</property>
        <property name="connection.username">root</property>
        <property name="connection.password">root</property>
        <property name="connection.pool_size">100</property>
        <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        <property name="show_sql">false</property>
        <property name="hbm2ddl.auto">update</property>
        <property name="hibernate.connection.autocommit">false</property>
        <property name="current_session_context_class">thread</property>
        <property name="hibernate.enable_lazy_load_no_trans">true</property>
        <mapping class="entity.User" />
        <mapping class="entity.Game" />
    </session-factory>
</hibernate-configuration>
Якщо пробігти очима по тегах, стає ясно, що і як ми тут налаштовуємо. Ще одна особливість hibernate, якщо ми раптом вирішимо змінити ДБ з MySQL, на якусь іншу, нам потрібно буде лише змінити драйвер усередині тега property name="connection.driver_class" Шар DAO готовий, робимо сервісний шар. щоб не створювати об'єктів DAO в сервісному шарі застосуємо патерн фабрика.
public class Factory {
    private static UserDAO userDAO = null;
    private static Factory instance = null;
    private Factory() {
    }

    public static synchronized Factory getInstance() {
        if (instance == null) {
            instance = new Factory();
        }
        return instance;
    }

    public UserDAO getUserDAO() {
        if (userDAO == null) {
            userDAO = new UserDAO();
        }
        return userDAO;
    }
}
А ось один із методів сервісного рівня
public class UserService {
    static void setUserBusy(User user){
        user.setBusy(true); //делаем его занятым
        //и обновляем его в БД
        Factory.getInstance().getUserDAO().updateUser(user);
    }

}
Код для роботи з БД завершено, переписуємо ігрову логіку з урахуванням змін. спочатку виділимо метод, що запускає маїн в окремий клас Main, він буде тільки керуючим класом - ігровим меню в якому можна буде запустити гру або подивитися статистику. Створимо клас GameLogic, в ньому буде описана вся логіка гри та перевірки ігрового поля. Збереження всіх змін на ігровому полі та статистики гравців після гри він віддаватиме на відкуп сервісному шару. Є цікава особливість, ігрове поле у ​​нас міститься у вигляді масивів, в базу даних їх можна зберігати, але я вирішив на цьому етапі винайти велосипед і в базі даних поле у ​​мене міститься як int, а саме 9-тизначне число, парсинг якого проводиться двома методами класуGameLogic, Так робити не рекомендую, в наступних релізах гри я виправлятимуся :) Всім удачі у вивченні JAVA! Завантажити проект можна тут .
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ