как сделать игру в блокноте windows крестики нолики
Познаем основы Java и создаем крестики-нолики
Java — это не только язык, это целая экосистема, включающая в себя средства разработки, платформу для запуска готовых приложений, огромный свод документации и активное сообщество. Одним из преимуществ Java на начальном этапе была кросс-платформенность (принцип — «написано один раз — запускается везде»).
Дело в том, что программа на Java исполняется не на прямую процессором компьютера, а виртуальной машиной Java (JVM). Это позволяет абстрагироваться от многих нюансов конкретных платформ. Программу, написанную на Java, можно без изменений кода запускать на Windows, Linux, MacOS и других операционных системах (если, конечно, программа не использует специфичные для ОС функции).
Кто застал начало 2000х, наверное помнит огромное количество мобильных телефонов (тогда еще они не были смартфонами), на каждом телефоне была по сути своя маленькая ОС, но при этом почти на каждом можно было запустить Java игру или приложение.
На сегодняшний день Java по-прежнему входит в топ языков для изучения, а Java как платформа — в топ используемых технологий в мире IT и смежных областях.
Сегодня мы начнем изучать Java, причем сразу с примера игры «Крестики-нолики».
Итак, поехали. Надеюсь как установить java SDK ты уже разобрался. Мы будем писать код в IDE IntelliJ IDEA, но если у вас какая-то другая, например Eclipse, то разницы большой не будет.
Итак, создаем новый проект: нажимаем «create new project», выбираем java и щелкаем «next» до окна, где требуется ввести имя проекта, вводим TicTacToe (крестики-нолики). В некоторых случаях на этапе создания потребуется выбрать шаблон проекта, тогда смело выбирай что-либо похожее на JavaConsoleApplication.
После этого нажимаем «Finish». Idea немного подумает и сгенерирует нам проект с классом Main, в котором определена функция main().
Давайте разберемся, что здесь что. Слева открыто окно структуры проекта «Project», как мы видим в папке src в пакете com.company находится единственный java-файл нашей программы с именем Main. Справа показано его содержимое. Тут надо сделать небольшое отступление, дело в том, что в Java почти все представлено классами. В том числе и файлы программы описывают классы, причем имя файла должно совпадать с классом, который описывается в этом файле (например, у нас файл Main.java описывает класс Main). Пусть слово «класс» не смущает на первом этапе. Пока лишь отмечу, что для глубокого изучения Java так или иначе придется познакомиться с объектно-ориентированным подходом. В двух словах, класс можно воспринимать как шаблон, идею, а экземпляры класса — как реализацию этой идеи. Экземпляры класса называются его объектами. Например, вы можете представить идею стола (нечто, на что можно класть предметы), однако конкретных экземпляров такого стола огромное множество (на одной ножке, на четырех, круглые, квадратные, из разных материалов). Примерно так соотносятся классы и объекты в объектно-ориентированном программировании.
Внутри нашего класса Main описана функция main(), в Java с этой функции начинается исполнение программы, это точка входа в наше приложение. Сейчас там написан только автоматический комментарий (комментарии в Java начинаются с двух символов //). Попробуем кое-что добавить в наш код и проверить работоспособность приложения. Внутри функции main() допишем две строки:
Встроенная функция println() просто выводит на экран текстовую информацию. Запустим наше приложение (нажимаем shift-F10 или зеленый треугольник). Внизу, во вкладке run появится вывод нашей программы:
Функция main() отработала и закончилась, вместе с ней закончилась наша программа.
В игре пользователю конечно захочется взаимодействовать с программой более продвинутым способом, поэтому нам понадобится окно. Набираем внутри функции main() следующие строки:
Смысл большинства строк понятен из комментариев к ним, отдельно отмечу строку window.setLayout() — здесь устанавливается менеджер расположения, который будет применяется к компонентам, добавляемым в наше окно. Менеджер BorderLayout может располагать новые компоненты относительно сторон света (North(верх), West(слева), East(справа), South(низ)), Center (центр)). По умолчанию он располагает компоненты по центру. Подробнее с менеджерами расположения можно познакомиться в документации.
Теперь, если запустить нашу программу, мы увидим окно:
Пока в этом окне ничего нет. Создадим свой компонент, который и будет отрисовывать графику игры.
Очевидно, что рисовать в консоли у нас не получится, нужен какой-то компонент для более продвинутого взаимодействия с пользователем. Для этой цели создадим еще один класс, назовем его TicTacToe. Щелкаем правой клавишей мыши на имени пакета приложения (в данном случае это com.company)
И в появившемся меню выбираем пункт «New» → «Java Class». В окне создания класса набираем его имя «TicTacToe» и нажимаем «Enter».
У нас в проекте появился еще один класс. В главное окно можно добавлять только объекты класса JComponent, кроме того, нам нужна область для рисования. Поэтому наследуем наш класс TicTacToe от JComponent. Ой сколько непонятных слов! Сейчас постараюсь пояснить.
Наследование классов — это как создание уточненного шаблона на базе существующего. Например, есть класс Стол, описывающий идею стола вообще. Но нам очень часто приходится создавать столы на четырех ногах с деревянной столешницей, поэтому для удобства мы можем уточнить идею класса Стол и создать шаблон ДеревянныйСтол — он будет иметь все те же основные свойства, что и родительская идея, но зато часть свойств у него уже определены и понятны — это число ног, равное четырем и материал столешницы — дерево.
С JComponent то же самое — данный класс реализует идею некоторого графического компонента пользовательского интерфейса. Такой компонент можно добавить в окно и он умеет как-то себя отрисовывать. Например, класс JButton — наследник класса JComponent, это компонент, который выглядит, как кнопка и умеет показывать анимацию клика мышкой.
Здесь же, наследуя класс JComponent, мы создадим свой компонент, в котором сможем рисовать то, что нам нужно.
Итак дописываем extends JComponent в строку описания класса:
Selenium для игр: автоматизируем крестики-нолики
На тему моего стрима на этой неделе меня вдохновила демонстрация Судхарсана Селвараджа, где он использовал Selenium для игры на виртуальном пианино. Я тоже хотела использовать Selenium, чтобы немного развлечь вас и себя, поэтому составила этот «рецепт», наглядно демонстрирующий, как автоматизировать игру в крестики-нолики (tic-tac-toe) онлайн!
Что особо примечательно в этом рецепте, так это то, что он выходит за рамки привычного использования Selenium для тестирования и способствует развитию навыков проектирования.
Рецепт автоматизации игры в крестики-нолики
Ингредиенты
Инструкции
Создайте конструкцию для представления игровых пространств
Создайте конструкцию для представления игрового поля и игрового поведения
Создайте конструкцию для представления самой игры
Создайте класс для выполнения игрового процесса
Запись стрима:
Ингредиенты
1. Selenium WebDriver
2. Игра крестики-нолики
Мы будем использовать эту онлайн-игру в крестики-нолики — Tic Tac Toe.
Инструкция
1. Создаем конструкцию для представления игровых пространств
Я создала enum (перечисление) для хранения пустых клеток в игре в крестики-нолики. Enum также будет содержать локаторы для каждой из этих клеток. Это позволит нам легко ссылаться на клетки на поле по мере их необходимости.
2. Создаем конструкцию для представления игрового поля и игрового поведения
Теперь нам нужен класс, представляющий игровое поле. Этот класс будет отслеживать текущую игру, сохраняя состояние каждой из клеток поля и позволяя игроку сделать ход.
Поскольку нам нужно взаимодействовать с веб-сайтом, этому классу потребуется ChromeDriver из Selenium.
Затем мне потребуется структура, которая будет представлять состояние каждой из клеток на поле, поэтому давайте создадим Map (ассоциативный массив), которая содержит каждую клетку и логическое значение, указывающее, занята ли она.
Затем нам нужно заполнить map клетками из нашего перечисления Space и установить для всех них значение занятости false, поскольку игра еще не началась и поле пустое.
А теперь самое интересное! Нам нужен метод, который позволит пользователю совершать ходы. В этом методе мы попросим игрока указать нам клетку, на котором он хотел бы поставить свой знак, и нам также необходимо обновить нашу внутреннюю Map.
Кроме того, поскольку мы играем против компьютера, он делает свой ход сразу после нашего, поэтому я добавила некоторое ожидание, чтобы дать компьютеру походить. Не заостряйтесь на этом моменте, это не тестовый код, который будет выполняться в нескольких средах как часть CI конвейера. Здесь можно немножко и подхалтурить.
Метод play отражает наш ход в нашей внутренней Map, но не учитывает ход компьютера. Так давайте же создадим метод для проверки браузера и обновления нашей Map, который будет точно отражать статус игрового поля.
Но сначала нам нужен локатор, чтобы получить все пустые клетки на поле.
Затем мы используем Selenium, чтобы получить все эти пустые клетки, сохранить их в List (список), а затем пройтись по нашей внутренней Map, чтобы обновить все клетки, которые не отображаются в списке Selenium с пустыми клетками, чтобы они были помечены как занятые.
3. Создаем конструкцию, представляющую саму игру
Теперь давайте создадим класс, представляющий саму игру. Первое, что нужно сделать этому классу, — это настроить ChromeDriver и запустить игру. Мы также можем создать инстанс игрового поля.
Мы хотели бы дать пользователю возможность определять, когда игра окончена. Это приложение отображает окно перезапуска игры по завершению партии, поэтому мы можем создать метод, который позволит нам это узнать, и наш собственный метод для перезапуска игры по желанию игрока. При перезапуске нужно не забыть сбросить игровое поле, чтобы все клетки снова были помечены как пустые.
Затем нам нужно определить, выиграл игрок или проиграл. Т.е. я создала три метода. Один для получения результатов с веб-сайта, другой для предоставления пользователю возможности указать выигрышный счет (в случае, если они хотят играть, пока один из игроков не наберет определенное количество очков), и, наконец, третий для вывода результатов.
Наконец, мы добавим в этот класс метод завершения игры, который закрывает браузер и убивает поток.
4. Создаем класс для выполнения игрового процесса
Теперь приступим к игре! Я создала еще один класс для выполнения игры от лица игрока. Первое, что мы здесь сделаем, это создадим инстанс новой игры и получим дескриптор игрового поля.
Затем мы определяем, сколько партий мы хотим сыграть до определения победителя. В этом примере мы указываем, что тот, кто первым наберет 5 очков, является окончательным победителем. Мы хотим продолжать игру, пока не дойдем до этого момента, поэтому мы будем использовать цикл while для представления каждого раунда.
Внутри этого внутреннего цикла мы будем играть на игровом поле. Значит нам нужно получить пустые клетки. Было бы неплохо написать алгоритм со стратегией выбора клетки, однако пока мы просто случайным образом выбираем одну из списка свободных клеток.
Затем после каждого раунда мы должны очищать поле, нажимая кнопку сброса. Это должно быть внутри внешнего цикла, вне области видимости внутреннего.
И наконец, мы заканчиваем игру! Это должно быть за пределами обоих циклов.
Вуаля! Теперь у нас есть решение для автоматизации игры в крестики-нолики.