Программирование крестики нолики алгоритм

Познаем основы 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 в строку описания класса:

Источник

Простой алгоритм проверки победы в крести-нолики на не стандартном поле

Столкнулся с такой проблемой, что молодым программистам, которые только начинают изучение языков, алгоритмы вызывают больше трудностей, чем синтаксис языка. Если сам синтаксис и концепцию объяснит преподаватель по конкретному языку, то алгоритмы вам придется придумывать самим. Исключением из правил могут быть только специализированные технические специальности в ВУЗах, где преподают именно алгоритмы.

При том, что алгоритм решения может быт очень простым многие не знают как подойти к решению задачи. Я рассмотрю пример проверки победы в игре крестики-нолики, но на поле 6х6 и блоком подряд заполненных значений равному 4-м.

На самом деле, здесь представлен универсальный алгоритм, только вместо переменных я использовал константы. И это практически не зависит от языка, котором эта проверка осуществляется. Я предлагаю начинающим программистам сначала решить задачу графически, а затем уже перевести ее на тот или иной язык. Для создания этого алгоритма подойдет листок в клетку и ручка.

image

Блок последовательно заполненных элементов, который достаточен, чтобы выиграть, равен 4-м.

image

Думаю, что теперь (всего лишь поле двух рисунков) стало намного понятнее, как решить эту задачу.

Фактически мы должны решить 2 независимые задачи:

  1. Найти все заполненные последовательности в блоке 4х4.
  2. Найти все квадраты 4х4 в квадрате 6х6.

1. Найти все заполненные последовательности в блоке 4х4

Почему проверяем блок 4х4? Все просто в нем возможно только 2 диагонали такой размерности, которая нам нужна.

Используя двоичную логику (1&1=1 и 1&0=0) мы можем легко сделать проверку циклами. Для этого нам нужна 1 переменная для каждой диагонали. Пусть toright – логическая переменная в которую пишем результат проверки диагонали сверху слева вниз направо. И toleft для проверки диагонали сверху справа вниз налево.

Первоначально выставим значение true для этих переменных. Дальше мы сравниваем каждую клетку в диагонали с символом «Х» или «О». Конечно, мы делаем это 2-мя вызовами либо все сравниваем с «Х», либо все с «О».

Каждую клеточку диагонали мы сравниваем с нашим символом и получаем результат (true) или (false). Затем делам логическую операцию (&) между полученным результатом и нашей toright. Результат этой операции пишем опять в toright. Если на каком-то этапе мы получим результат (false), то все дальнейшие toright всегда будут равны (false). Это следует из правила логических операций (1&0=0).

boolean checkDiagonal(char symb) < boolean toright = true; // установили логическое значение 1 for (int i=0; i// Дальше мы вернули (true), если во всех клетках нам встретились символы symb if (toright) return true; // или вернули (false), если встретился хоть один символ, отличный от symb return false; >

Собственно вот в этой строчке

toright = toright & (map[i][i] == symb))

Краткая запись выглядит так:

Получаются только 2 результата работы условия:

toright = toright & 0 или toright = toright & 1

Для 2-х диагоналей, полный код функции будет выглядеть так:

/** Проверяем диагонали */ boolean checkDiagonal(char symb) < boolean toright, toleft; toright = true; toleft = true; for (int i=0; iif (toright || toleft) return true; return false; >

Полный аналог делается для проверки вертикалей и горизонталей, только циклы меняются.

/** Проверяем горизонтальные и вертикальные линии */ boolean checkLanes(char symb) < boolean cols, rows; for (int col=0; col// Это условие после каждой проверки колонки и столбца // позволяет остановить дальнейшее выполнение, без проверки // всех остальных столбцов и строк. if (cols || rows) return true; > return false; >

Собственно это и есть решение для блока 4х4. Как видно из кода, для другого блока нужно только поменять 4 в цикле на другое число, или написать вместо числа имя переменной. Причем эту переменную вы можете сделать как глобальной видимости, так и передать в функцию, например так:

boolean checkLanes(char symb, int block)…..

2. Найти все квадраты 4х4 в квадрате 6х6

Собственно, их не так много. Начиная с позиции [0,0], [1,0] и [2,0] для первой строки квадрата, [0,1], [1,1] и [2,1] для второй, [0,2], [1,2] и [2,2] для третьей. Дальше квадрат 4х4 выйдет за границы квадрата 6х6.

Такой перебор координат вполне можем сделать циклами:

boolean checkWin(char symb) < for (int col=0; col> // Все подквадраты в квадрате проверены. 4-х последовательностей // подряд не выявлено. Значит еще не победа. return false; >

Тут нам придется немного модифицировать методы checkDiagonal и checkLanes, поскольку мы должны проверять квадрат 4х4 с соответствующим смещением.

int size = 6; // размер квадратного поля int block = 4; // размер блока boolean checkLanes(char symb, int offsetX, int offsetY) < boolean cols, rows; for (int col=offsetX; colif (cols || rows) return true; > return false; >

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

И еще один совет. В настоящий момент имеется огромное количество реализаций различных алгоритмов в сети на разных языках. Если вы хотите научиться думать, то смотрите именно принципы решений (алгоритмы), не привязанные к языкам. Готовые решения не позволят вам быстро научиться выбирать наиболее оптимальный вариант решения. Очень часто, переписать готовое решение с одного языка на другой, можно не понимая принципа решения задачи. Где-то это вам поможет, а где-то может сделать дальнейшее развитие программы невозможным без изменения ее логики.

Сначала я рекомендую попробовать написать проверку самостоятельно. Шаблон игры можно забрать здесь. Там уже есть заголовки функций, которые я описал в статье. Осталось скопировать в шаблон часть моего кода и чуть-чуть его модифицировать. А вот здесь можно скачать полный рабочий код на Java. Рекомендую смотреть его уже после того, как вы написали свои функции на основе этой статьи.

Источник

Оцените статью