Всем привет, давно уже дописал игру, всё никак не доходили руки до написания статьи, она является логическим продолжение вот этой писулины
Если вы пока еще не пробовали делать что-либо кроме задач JavaRush, то знакомство с игрой будет как раз именно тем, с чего нужно будет начать подготовку к тестовым заданиям реального проекта, в котором я настоятельно рекомендую поучаствовать каждому. Да и вообще пора уже перестать быть сферическим программистом в вакууме и начать изучать что нибудь за пределами java-core.
Для того, чтобы просто посмотреть игру, у вас должен быть установлен MySQL, если вы пока еще таким не пользовались, не стесняйтесь – ставьте, это одна из тех баз данных, которые вы будете использовать в своей работе и личных проектах!
Я не буду приводить описание установки и работы с базой, в интернете навалом туториалов и видео, рекомендую разобраться с этим вопросом самостоятельно, это тоже один из самых важных скилов программиста – разбираться самостоятельно :)
В жизни вам пригодится умение писать запросы в sql, как нативно, так и через JDBC, hibernate, spring, spring data, возможно список можно продолжить, но мои знания на этом оканчиваются.
А теперь отложите чтение этой статьи и разберитесь с MySQL, это на самом деле совсем не сложно, вам нужно поставить сам сервер, из настроек там только логин и пароль. после почитайте про то какие команды используются при работе.
Команды для работы с сервером:
очень много боли в заднем проходе некоторую сложность в написании классов DAO (тоже вики), hibernate немного улучшит ситуацию, с ним у вас будет гораздо меньше повторяющегося (шаблонного) кода.
Для того, чтобы работать hibernate, к проекту необходимо подключить библиотеку, делается это очень просто: Ctrl+Alt+Shift+S(File-Project Structure), заходим во вкладку Libraries, нажимаем "+" и добавляем предварительно скачанную библиотеку (как вариант, отсюда).
Для того, чтобы связать классы
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– тоже для мультиплеера, конкретно во время игры это поле управляет тем чей сейчас ход,
а после ее окончания оно объявляет победителя или ничью
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, почитайте о нем в вики. Но если пользоваться им в написании кода, то это принесет 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")– имя столбца в БД.
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!
Скачать проект можно тут.