- Игры на Android: Крестики-нолики (Custom View)
- Определение касания экрана
- Крестики-нолики
- Вместо предисловия
- Player.java
- Square.java
- Game.java
- Определение победителя
- WinnerCheckerHorizontal.java
- WinnerCheckerVertical.java
- WinnerCheckerDiagonalLeft.java
- WinnerCheckerDiagonalRight.java
- Видео готового приложения
- Дополнительное чтение
- Часть 1. Написание игры «Крестики и нолики» под Android. Подготовка инструментов
- 1. Установка JDK
- 2. Установка Android Studio
- 3. Установка Inkscape
- Заключение
- Крестики-нолики
- Создание проекта
- Верстка экрана
- Соединяем верстку с кодом (Binding)
- Пишем код
- Создаем свою вьюшку и рисуем на ней сетку
- Вычисляем, кто выиграл
- Сбрасывание состояния игры
Игры на Android: Крестики-нолики (Custom View)
Напишем ещё один вариант игры на основе собственного компонента. Наткнулся на руководство из трёх частей (ссылки внизу). Решил частично перевести материал, чтобы посмотреть на ещё одну реализацию игры.
Создадим класс TicTacToeView. Для игрового поля нам понадобятся две вертикальные и две горизонтальные линии, которые должны разделить экран на три равные части по вертикали и горизонтали. Соответственно, чтобы получить нужные координаты для линий, нужно вспомнить немного математики. Для первой вертикальной линии начальную координату X можно вычислить, если ширину доступной области разделить на 3 и умножить на 1. Для второй линии ширину следует разделить на 3 и умножить на 2. По такому же принципу вычисляем координаты для горизонтальных линий.
Разделив линиями экран, мы получили девять прямоугольников. Нам нужно вычислить координаты этих прямоугольников, чтобы иметь возможность определять область нажатия и вывода текста(X или О). Создадим два массива, первый массив для хранения прямоугольников (объекты Rect), второй — для текста, который будет выводиться в центре прямоугольников.
Визуализация прямоугольников, чтобы понимать их расположение. Здесь опять требуется немного математики, чтобы вычислить данные для прямоугольников.
Сразу же пробуем вывести в двух прямоугольниках текст, чтобы посмотреть, как всё это будет выглядеть.
Текст выводится не по центру, что очень некрасиво. Опять понадобятся знания по математике. Нам нужно вычислить размеры текста (отдельные методы для ширины и высоты) и затем найти нужную позицию на основании полученных данных.
Добавим код в метод drawTextInsideRectangle().
Запустите пример и убедитесь сами, что теперь текст выводится по центру.
Определение касания экрана
Метод onTouchEvent() позволяет определить точку касания через параметры event.x и event.y. У Rect есть метод contains() позволяющий узнать, является ли точка частью прямоугольника. Мы можем пройтись по всем прямоугольникам игровой площадки в массиве и вычислить, к какому прямоугольнику относится точка касания. Таким образом мы получим индекс прямоугольника.
Если запустить пример и касаться в разных местах экрана, то получим значения (0, 1), (2, 2) и т.д. На основе этой информации мы можем что-то делать с выбранным прямоугольником, например, подсветить его другим цветом.
Добавим глобальную переменную, чтобы понимать, когда можно отрисовывать прямоугольник и вызовем invalidate() для перерисовки. В методе onDraw() добавим новую функцию.
Настало время вывести X или O на месте выбранного прямоугольника. Два новых метода заполняют массив нужными значениями и вызывают перерисовку.
В третьей части рассказывает об анимации. Все ссылки ниже.
Источник
Крестики-нолики
Вместо предисловия
Однажды я написал статью на Хабре. Один из читателей сказал, что тоже написал одну статью про создание игры «Крестики-нолики», но боится её выкладывать на всеобщее обозрение. Я и несколько других комментаторов сумели убедить его опубликовать свой материал, который вы можете прочитать здесь. В статье речь шла о создании игры в IntelliJ IDEA Community Edition. Если кому-то интересно, то ознакомьтесь с оригиналом статьи, а также почитайте комментарии. Я в свою очередь немного отредактировал статью и сам код игры.
Статья затронет весь цикл разработки приложения. Вместе мы напишем простенькую игру “Крестики-Нолики” с одним экраном.
Для нашего приложения идеально подойдёт макет TableLayout с идентификатором android:id=»@+id/tableLayout».
Программный доступ к TableLayout:
Теперь необходимо реализовать метод buildGameField(). Для этого требуется создать поле в виде матрицы. Этим будет заниматься класс Game. Сначала нужно создать класс Player, объекты которого будут заполнять ячейки игрового поля и класс Square для самих ячеек.
Player.java
Square.java
Game.java
Метод buildGameField() динамически добавляет строки и колонки в таблицу (игровое поле):
В коде создаётся объект, реализующий интерфейс View.OnClickListener. Создадим вложенный класс Listener. Он будет виден только из активности.
Осталось реализовать логику игры. Возвращаемся к Game.java:
Определение победителя
Очевидно, что в крестики-нолики выигрывает тот, кто построит X или O в линию длиной, равной длине поля по вертикали, по горизонтали или по диагонали. Первая мысль, которая приходит в голову — это написать методы для каждого случая. Думаю, в этом случае хорошо подойдёт паттерн Chain of Responsobility. Определим интерфейс:
Так как Game наделён обязанностью выявлять победителя, он реализует этот интерфейс. Настало время создать виртуальных «лайнсменов», каждый из которых будет проверять свою сторону. Все они реализует интерфейс WinnerCheckerInterface.
WinnerCheckerHorizontal.java
WinnerCheckerVertical.java
WinnerCheckerDiagonalLeft.java
WinnerCheckerDiagonalRight.java
Проинициализируем их в конструкторе Game:
Возвращаемся в класс активности. Победителя проверяем после каждого хода. Добавим код в метод onClick() класса Listener
Метод gameOver() реализован в 2-х вариантах.
Метод makeTurn() проверяет очерёдность хода игрока, а метод refresh() обновляет состояние поля:
Весь код активности.
Видео готового приложения
Оригинальные исходники от автора статьи уже недоступны, но по оставленным записям я восстановил работоспособность приложения, хотя, конечно, его можно ещё улучшить.
Дополнительное чтение
SavvaVyatkin/CatDogToe — правильный вариант игры с участием котов. Картинка для статьи взята из этого проекта.
Источник
Часть 1. Написание игры «Крестики и нолики» под Android. Подготовка инструментов
Итак, с сегодняшнего дня начнем цикл статей, которые пошагово разъяснять как написать свою собственную игру на примере классической игры «Крестики и нолики», другое забавное название для данной игры «Tic-Tac-Toe» 🙂 . Плюс ко всему этому попытаемся загрузить, после написания, на Google Play, чтобы игроманы смогли оценить наше детище 🙂 .
В данной части разъясним что нам необходимо для полноценной разработки игры:
- Android Studio — полнофункциональный официальный инструмент разработки для кроссплатформенной разработки приложений для Android, который еще содержит и эмулятор для виртуального тестирования программ;
- JDK — набор инструментов для разработки программ, работающих на Java. Наш инструмент Android Studio работает на основе Java машины, поэтому нам необходимо ее установить на компьютер, прежде чем устанавливать Android Studio;
- Inkscape — векторный редактор для рисования наших ресурсов, таких как кнопки, иконки, фоны и т.д. Это необязательное условие, можете использовать другой, на котором набита рука.
1. Установка JDK
Установка JDK ничем не отличается от установки любой другой программы. Скачиваем отсюда и я не буду вдаваться в дебри установки, потому что нет никаких сложностей. Единственное, если у вас Windows, после установки откройте командную строку и введите команду
Если установка удачная, то должна вернуть версию программы
если это не так, то следует открыть «переменные среды» вашего компьютера
и создать новую пременную JAVA_HOME с параметром пути, где установлена ваша JDK и все — JDK у вас установлена, перейдем к следующему пункту.
2. Установка Android Studio
Скачать Android Studio можно на официальном сайте. Установка Android Studio не должно иметь затруднений, вам лишь необходимо указать место для установки и совершать действия следуя подсказкам установщика. После установки Android Studio нам необходимо настроить программу для дальнейшей разработки — будет во второй части.
3. Установка Inkscape
Считаю, что данная бесплатная программа ничем не хуже платных и нашпигованных и платных Adobe Illustrator, CorelDraw… Не все при деньгах и не все без совести, чтобы пользоваться кряками 🙂 .
Заключение
В данной статье рассмотрели инструменты, которые нам пригодятся для разработки простой игры «Крестики и нолики» под Android. Следуйте в ногу обновлениям и скачивайте последние версии против привычности работы на старых 🙂 . В следующей части рассмотрим Android Studio по подробнее и займемся настройкой и запуском тестовой программы.
Источник
Крестики-нолики
В этой статье, приуроченной к онлайн-курсу Android Developer. Basic, мы напишем свою собственную небольшую игру «Крестики-нолики». Для работы потребуется установить Android Studio. Какая у вас ОС — не имеет значения, т.к. эта IDE работает на Windows, Ubuntu или Mac. Язык программирования будет Kotlin, т.к. сейчас он является официальным языком для программирования на Android. Во время написания статьи использовалась версия Android Studio 4.1.3
Создание проекта
Для начала необходимо создать новый проект. В нашем случае необходимо выбрать Fragment + ViewModel и нажать Next.
Далее в поле Name вводите название приложения, в Package name можете внести свое имя или ник как доменное имя, но с зада на перед. Это нужно для уникальности вашего приложения в маркете и на телефоне. Все остальное можно оставить по умолчанию как на картинке. Далее нажимаем Finish и ждем, когда проект соберется и мы сможем работать.
Нам нужно добавить зависимости которых нам не хватает в build.gradle модуля в раздел dependencies. А так же включить viewBinding для того, чтобы было удобна делать связь верстки с кодом (смотри изображение)
Верстка экрана
Теперь можно преступить к верстанию экрана. Для начала мы добавим только несколько вьюшек. Для того, чтобы не нужно было у каждой вьюшке проставлять отступы от края экрана, воспользуемся специальным виджетом `Guideline`. Он позволяет выставить границы, за которые будут «цепляться» вьюшки. Если у вас экран открылся в режиме `Design`, то я рекомендую перейти в режим `Split`. Так удобнее мне объяснять и можно будет копировать однотипные элементы. Чтобы добавить Guideline можно внутри элемента `ConstraintLayout` написать ` android:id напишем @+id/ плюс название в зависимости от расположения (start, end, top, bottom). В параметре android:orientation поставим vertical/horizontal в зависимости от направления линии. И изменить параметр app:layout_constraintGuide_begin на app:layout_constraintGuide_end для элементов с id=end/bottom .
Теперь добавим отображение того, чей сейчас ход Х или О. Для этого добавим 3 ImageView. Но для начала, давайте создадим сами иконки Х и О, а так же ß для того, чтобы показывать чей ход.
Для этого справа в области project щелкните правой кнопкой мыши (ПКМ) выберите New → Vector Asset.
В появившемся окне щелкнуть по изображению в пункте Clip Art, найти по поиску back стрелку назад и нажать OK. Я выбрал, чтобы концы были скругленными, для этого во втором выпадающем списке выбрать Round. Вы можете посмотреть, как выглядят остальные и выбрать понравившийся. Размер я задал 64 в пункте Size, а цвет в Color: F44336. Вы же в палитре можете выбрать тот цвет, который Вам больше всего понравился. Название в пункте Name я указал ic_arrow, чтоб проще было использовать. Для иконок, принято название начинать с ic_ и в snake case, т.е. с подчеркиванием. И нажимаем Next → Finish. Теперь самостоятельно сделайте крестик и нолик. Для них я выбрал иконку close и panorama fish eye соответственно и выбрал цвет 454FCE, а названия дал ic_cross и ic_circle.
После всех этих действий, в разделе res → drawable появятся новые файлы с нашими иконками. Я рекомендую значение цвета из параметра android:tint перенести в параметр android:fillColor , а сам tint удалить. На некоторых китайских телефонах, отображение ведет себя не корректно и качество иконки ухудшается.
Теперь давайте вернемся к верстке и добавим 3 элемента ImageView. Для этого перейдем в режим Design (это как один из способов верстания экрана), найдем ImageView и перетащим его на макет. В появившемся экране выберем иконку ic_cross. В поле id напишем название cross. Таким же способом перетащим еще 2 элемента для ic_arrow и ic_circle и дадим им имя id direction и circle соответственно. Теперь выделим каждый элемент поочередно и потянув за верхний круг свяжем вьюшку с верхним guideline.
Теперь сделаем из них цепочку, чтоб они были посередине и склеены друг с другом. Для этого выделяем эти 3 элемента вышкой, нажимаем ПКМ → Chains → Create Horizontal Chain.
Затем снова ПКМ → Chains → Horizontal Chain Style → packed. Попробуйте другие стили и посмотрите, чем они отличаются друг от друга.
Теперь они склеились вместе и находятся посередине, как я и хотел.
Добавим еще один элемент Barrier, который служит для того, чтобы следующий элемент расположить после других, не зависимо от того, какого размера будет каждый. Нажмем на кнопку Guidelines → Add Horizontal Barrier.
И установим следующие значения:
У вас должно получиться что-то вроде этого.
Теперь осталось добавить последний элемент верстки это GridLayout. Но его нужно выбрать из подключенной библиотеки и выбрать androidx.gridlayout.widget.GridLayout. Его уже нужно добавить вручную.
Аргументы app:columnCount и app:rowCount отвечают за количество колонок и строк соответственно. Устанавливаем значение 3, т.к. поле у нас 3х3. Аргументы app:layout_constraintDimensionRatio отвечает за соотношение сторон. Для того, что бы у нас был квадрат нужно его выставить в 1:1, вот из-за этого аргументаи пришлось подключать библиотеку, т.к. на версиях Android 5 этот аргумент не работает. И для того, чтобы соотношение работало, необходимо установить android:layout_width и android:layout_height в 0dp. Аргументы app:layout_constraintXXX_toXXX отвечают за привязку нашей вьюшки к другим элементам. Ну и запишем id=»@+id/field» , а во внутрь добавим ImageView. Но так как их понадобиться 9 штук и чтобы у каждой вьюшке не прописывать одни и те же аргументы, можно создать стиль. Для этого щелкаем ПКМ по values → New → Values Resource File.
В появившемся окне, в поле File name указываем styles и нажимаем OK. В созданном файле сделаем следующую запись:
Аргументы layout_columnWeight и layout_rowWeight служат для установки весов вьюшек и чтобы они равными размерами распределялись по ширине и высоте соответственно. Для того, чтобы эти веса заработали, необходимо android:layout_width и android:layout_height установить в 0dp. А в android:background прописываем атрибут, который будет браться из темы и отображать нажатие на вьюшку. Теперь осталось подключить этот стиль к нашей вьюшке. Возвращаемся к нашей верстке и у созданной ImageView меняем на следующее:
style=»@style/CellStyle» – позволяет применить наш стиль для разных вьюшек, а tools:src=»https://otus.ru/journal/krestiki-noliki/@drawable/ic_cross» позволяет отображать картинку на макете, но когда проект будет создан и установлен на телефоне, то картинки не будет. Продублируем этот элемент, чтобы в общем счете их получилось 9. В итоге должно получиться следующее:
Соединяем верстку с кодом (Binding)
Теперь нужно перейти во фрагмент MainFragment и поправить то, что было сгенерировано студией и добавить binding, который связывает верстку с кодом.
А оставшийся метод onActivityCreated полностью удалите. Все элементы, которые студия подчеркнет, нужно импортировать с помощью подсказок.
Пишем код
Теперь давайте перейдем в класс MainViewModel и уберем сгенерированные TODO. Нам необходимо хранить состояния ячеек (пустая, крестик, нолик) и для этого создадим массив этих состояний потому, что в Gridlayout все ячейки хранятся списком. А для расчета того кто победил, будем переводить индекс в массиве в координаты [строка:колонка], но об этом позже.
Создадим enum class для хранения состояния. В нем будет храниться картинка и возможность по ней кликать, ведь когда мы уже поставили символ или игра закончилась, то уже кликать по ячейкам нельзя. Напишем следующее в этом же файле в самом низу за пределами `>`.
Создадим поле с массивом этих состояний, я назову ее matrix для простоты. Так же добавим поле для хранения текущего состояния, т.е. чей сейчас ход и создадим метод initGame для инициализации начального состояния игры при первом запуске приложения (init – вызывается при создании класса MainViewModel ) и при сбросе игры ( onReloadClick ).
Создадим метод обработки кликов по ячейкам и пропишем в нем для начала смену хода и сохранение в массиве состояние ячейки. Так же создадим поле с LiveData, для того, чтобы на экране смогли отображать кто сейчас ходит.
Здесь mCurrentMove является изменяемым и он закрыт для обращения из вне класса, а currentMove является не изменяемым и он доступен снаружи класса.
Давайте подпишемся на изменение хода и будем отображать на экране чей сейчас ход. Для этого перейдем в MainFragment , переопределим метод onViewCreated и добавим в него следующее.
binding.field.forEachIndexed – к каждой вьюшке находящейся в GridLayout устанавливаем слушатель на клик.
binding.direction – это наша стрелочка на экране. Соберите проект и запустите его, посмотрите что происходит когда мы кликаем по ячейкам. Попробуйте убрать комментирование со строки со scaleY, а строку с rotation закомментировать или убрать и посмотреть что получилось.
Добавим отображение иконке в той ячейке, по которой мы кликнули. Чтобы не перерисовывать весь массив ячеек, а менять значение только той, по которой мы кликнули, будем передавать индекс ячейки и ее новое значение. Для этого добавим еще одно поле mCellStateByIndex, в которую будет передаваться индекс и новое состояние ячейки.
SingleLiveEvent – этот класс служит для того, чтобы при смене конфигурации (например, переворота экрана) не вызывалось снова событие на отрисовку вьюшки. Этот класс нужно создать отдельным файлом.
Добавим еще состояние нашей игры (запущена и остановлена), чтобы нельзя было кликать по ячейкам, когда игра завершилась и LiveData, в которой будет храниться состояние игры и список состояний ячеек
Создадим enum GameStatus и напишем его ниже CellState.
Добавим поле mStates и сделаем несколько изменений.
Создаем свою вьюшку и рисуем на ней сетку
Создадим новый файл. Для этого в правой части проекта щелкните ПКМ по ru.otus.tictactoe → New → Kotlin Class/File и введите название FieldView.
И напишите следующее в этот файл:
Обязательно нужно наследоваться от androidx.gridlayout.widget.GridLayout .
Еще нужно добавить в ресурсы в которых будет указан цвет и размер линии. Для этого ПКМ по res → New → Android Resource File.
В появившемся окне, в поле File name: написать values и нажать OK.
Появится новый файл values.xml. откройте его и напишите следующее:
Теперь ошибки должны исчезнуть.
Осталось поменять нашу вьюшку в верстке.
Вычисляем, кто выиграл
Для начала создадим sealed class с возможными вариантами выигрыша (по горизонтали, по вертикали, по диагонали и нет выигрыша).
Создадим методы расчета выигрышного положения.
Сбрасывание состояния игры
Чтобы постоянно не приходилось перезапускать игру, давайте сделаем сброс к начальному состоянию игры. Для этого добавим кнопку в тулбаре.
Добавьте иконку cached и назовите ее ic_reload. Добавьте ресурс, как это делали с цветом и размером, только в открывшемся окне, поменяйте Resource type на Menu и в File name напишите menu_reload. А в ресурсах strings добавьте название кнопки
Теперь осталось только добавить ее и реализовать обработку этой кнопки. Для этого переходим в MainFragment и добавляем следующее.
Источник