крестики нолики пустое поле

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 для представления каждого раунда.

Внутри этого внутреннего цикла мы будем играть на игровом поле. Значит нам нужно получить пустые клетки. Было бы неплохо написать алгоритм со стратегией выбора клетки, однако пока мы просто случайным образом выбираем одну из списка свободных клеток.

Затем после каждого раунда мы должны очищать поле, нажимая кнопку сброса. Это должно быть внутри внешнего цикла, вне области видимости внутреннего.

И наконец, мы заканчиваем игру! Это должно быть за пределами обоих циклов.

Вуаля! Теперь у нас есть решение для автоматизации игры в крестики-нолики.

Источник

Банальные Крестики-нолики

Это конечно не самый удобный способ но мы в рабочем чате ватсапа играем так временами

Дубликаты не найдены

Сразу скажу плохо помню правила но сыграть попытаюсь

да чтоб я хорошо помнил

шашка телепортировалась или я туплю?

Чуть поправил тебе поле.

Копипасть на здоровье.
Идея неплохая 👍

Граждане-залётчики минусят, думаю, это временно. Знал бы как играть, сыграл бы, серьёзно, как-то мимо меня всё время проходила эта игра.

Но у тебя был шанс ))

Смысла в этой игре не очень много. Если ты умеешь играть, то в принципе всегда победишь если ходишь первый или выйдешь на ничью.

Шах и мат в два хода 🙂

Да вы, батенька, нонконформист.

Коричневый триллер

В догонку про профдеформацию

Семейные истории

Предложение

Единороги

Зарисовки с работы #5

*работаю в сети стройматериалов

Люблю работать с «девочками». Наверное мужики во всяких » Лэтуалях», выглядят также нелепо, как и «девочки» в строймагазинах.
Студентка подбирает линолеум в общагу. Наворачивает уже тридцать шестой круг по залу, все перетрогала, перещупала, перенюхала, только на зуб не попробовала.
— Задайте вектор, в какую сторону вам помогать? Светлый, темный, подешевле, подороже, что вы хотите?
Девочка горько вздохнула, надула губки:
— Я хочу. Я хочу замуж поскорее, чтобы у мужа голова болела, а не вот это вот все.

Читайте также:  леруа краска для фасадов

Вот так бывает.

Живёшь ты, живёшь. а на тебя совершают нападение. Сегодня. Средь бела дня.

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

Нажала на свой этаж и о чудо, ему туда же. Здесь конечно мои чувства обострилась взяла ключи в руку, зажав железку между пальцами, стою жду.
Лифт остановился на моем этаже, со спокойной душой мне выхожу, мне остается буквально 3 шага до моей двери квартиры и меня начинают душить хваткой сзади.

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

В итоге сил моих не хватает, отпускаю его. Вызываю полицию. Несколько часов сборов информации и есть его фото.

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

Источник

Логические игры на бумаге

Вообще-то это в копилку занятий с детьми на карантине, но во все эти игры можно и взрослым людям играть, было бы желание.

Великая китайская стена

Подготовка. Нарисуйте прямоугольник 8*12 клеток, можно сделать и больше.

Игра. Участники по очереди рисуют белые и чёрные (закрашенные) «камни» − кружочки. При этом соблюдается следующее важное условие: камень не может «висеть в воздухе», он всегда ставится или на нижней границе прямоугольника, или на одном из уже поставленных камней. Выигрывает тот, кто первым составил последовательность из четырёх камней по вертикали, горизонтали или диагонали. Другой вариант: игра продолжается до тех пор, пока поле не окажется заполнено целиком, и победителем признаётся тот, кто выстроил больше последовательностей из четырёх и более камней. В этом случае каждая законченная последовательность перечёркивается, чтобы те же камни не могли использоваться для выстраивания нового ряда.

Построим китайскую стену! Не впустим к себе злобный коронавирус!

Крестики-нолики на бесконечном поле.

Обычная игра в «крестики-нолики» быстро надоедает, когда играющие обнаруживают, что при соблюдении единственной выигрышной стратегии результат всегда предрешён. Снова сделать сражение увлекательным поможет переход на «бесконечное» поле.

Подготовка. Возьмите один или несколько листов в клетку и карандаш либо ручку.

Игра. Участники по очереди ставят в клетках крестики и нолики; выигрывает тот, кто первым выстроит пять знаков в ряд.

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

Для игры рисуется квадратное поле размером не менее 5*5 клеток.

Игроки по очереди ставят вертикальные или горизонтальные чёрточки длиной в одну клетку. Тот, кто смог составить из четырёх чёрточек квадрат, рисует в нём свой знак (крестик или нолик). Участнику, сделавшему квадрат, даётся ещё один ход. Игра продолжается до тех пор, пока поле не будет заполнено; выигрывает тот, кто составил больше квадратов.

Для этой игры понадобятся ручки или карандаши двух цветов. Поле подготавливается следующим образом: рисуются четыре «берега» в виде прямых линий, причём берега, расположенные напротив, изображаются одним цветом, чтобы обозначить их принадлежность: например, красный напротив красного и синий напротив синего. Пространство между берегами заполняется точками двух цветов, расположенных на одинаковом расстоянии друг от друга в шахматном порядке.

Эта игра похожа на одноименную компьютерную игру, но предназначена минимум для двух игроков.

Для начала нарисуйте квадратное или прямоугольное поле на листе бумаги в клетку. Игроки по очереди рисуют своих «змеек»: начинают из разных точек в узлах клеточной сетки в произвольно выбранных местах ; за один ход можно нарисовать одну чёрточку длиной в одну клетку по вертикали или горизонтали. Нельзя касаться уже нарисованных линий, а также краёв поля. Проигрывает тот, кто зашёл в тупик и не может больше сделать ни одного хода.

Можно усложнить игру, сделав поле необычной формы или добавив разные препятствия.

Поле представляет из себя прямоугольник со сторонами, состоящими из чётного количества клеток. На узких сторонах по центру изображаются одинаковые по ширине «ворота».

Выигрывает тот, кто первым уничтожил все корабли противника.

Для двух и более игроков. В этой игре каждый будет создавать и развивать свою колонию вирусов, стремясь уничтожить противников. Вирусы обозначаются любыми знаками, обычно крестиками и ноликами. Игра ведётся по следующим правилам:

— Ход каждого игрока состоит из трёх маленьких «ходиков», за один «ходик» можно поставить одного своего вируса или съесть одного вражеского.

— Ставить вирусов можно только на соседние клетки со своими живыми (несъеденными) вирусами.

— Если рядом оказался вирус противника, его можно съесть, поставив поверх свой знак (или перекрасив в свой цвет).

— Съеденные вирусы называются «крепостями», съесть их повторно уже нельзя.

— Пока рядом с крепостью остаётся хотя бы один свой живой вирус, рядом с ней можно ставить новых вирусов и съедать оказавшихся на соседних клетках врагов.

Самое то во время эпидемии.

Игра по принципу «Вирусов», но с более сложными правилами.

Любой объект противника, оказавшийся в зоне поражения, может быть атакован, закрашен своим цветом и тем самым превращён в свою крепость, которую уже нельзя атаковать.

Войско должно сохранять постоянную связь с генералом; если объект не соединён с генералом через свои войска и крепости, то от него нельзя ставить новые «подразделения».

Игрок, потерявший генерала, проигрывает и выбывает из игры.

— за один ход можно провести один прямой отрезок с концами в узловых точках клеток;

Читайте также:  Shaft в обуви что это

— если «машина» стояла, то отрезок будет длиной в одну клетку;

— в каждый следующий ход можно «разогнаться», «затормозить» или «повернуть», при этом нельзя отклоняться от прежней траектории более, чем на одну клетку.

Источник

Крестики нолики «Без границ»

Крестики-нолики… в них играли все, я уверен. Игра притягательна своей простотой, особенно когда ты тянешь часы где-нибудь на уроке, паре, а под рукой нет ничего, кроме тетрадного листа и простого карандаша. Уж не знаю, кто первым когда-то догадался рисовать кресты и кружки в 9 квадратах, но с тех пор игра нисколько не потеряла в востребованности, тем более, что народ придумал огромное множество её вариаций.

Эта статья про процесс разработки ИИ на javascript для игры в одну из таких вариаций крестиков-ноликов: получилось довольно много материала, но я разбавил его анимацией и картинками. В любом случае, хотя бы стоит попробовать поиграть в это.
Отличия этого варианта игры от оригинала в следующем:

Перед тем, как начнем

Вынужден извиниться заранее за объем статьи и местами не совсем доходчивое изложение мысли, однако у меня не получилось сжать стаю без потери в содержании и качестве.
Рекомендую сначала ознакомиться с результатом. Код

Горячие клавиши и команды:

Начнем

Начать нужно с реализации самой игры, т.е. написать приложение для двух игроков, пока без бота. Для своих целей я решил использовать javascript + jquery + bootstrap4, хотя он там практически не используется, но его лучше оставить – или таблица поплывет. Тут рассказывать особо нечего, материала по js, jquery и bootstrap на хабре полно. Скажу лишь, что использовал MVC. Да и вообще, объяснять абсолютно весь код я не буду – материала и без того получилось много.

Итак, игровое поле было готово. Можно устанавливать фигуры в клетки. Но победа кого-либо из игроков никак не фиксировалась.

Сканирование «конца игры»

Игра заканчивается, когда один из игроков поставит 5 фигур в ряд. «Все просто!» — подумал я. И начал сканировать абсолютно все клетки поля: сначала все горизонтали, потом вертикали и, наконец, диагонали.

Это тупой способ, но он работал. Однако, его можно было значительно улучшить, что я и сделал: Большая часть клеток будет оставаться пустой на протяжении всей игры – игровое поле слишком большое, чтоб его можно было заполнить целиком. Поскольку сканировать его нужно было каждый ход, а за один ход ставится только одна фигура — то можно сосредоточиться только на этой фигуре (клетке): просканировать только одну горизонталь, вертикаль и две диагонали клетки, которым принадлежит та самая клетка.

Плюс ко всему, не нужно сканировать все клетки линий. Поскольку конец игры – это 5 фигур в ряд, то фигуры, удаленные друг от друга на 6 клеток нас не интересуют. Достаточно сканировать по пять клеток в каждую из сторон. Не понятно? Смотри анимацию ниже.

Приступим к самому боту

Итак, мы уже написали страницу с крестиками-ноликами. Переходим к основной задаче – ИИ.
Нельзя просто так взять и написать код, если ты не знаешь как: нужно продумать логику бота.

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

Терминология

Крестики и нолики – это фигуры.
Атакой будем называть несколько одинаковых фигур, стоящих рядом, на одной линии. По сути, это множество. Количество фигур в атаке – её мощность. Одна отдельная фигура – тоже атака (мощностью 1).

На соседних клетках атаки (на концах) могут быть пустые клетки или фигуры противника. Логично думать, что атаку с двумя пустыми клетками на «концах», мы можем развивать в двух направлениях, что делает ее более перспективной. Количество пустых клеток на «концах» атаки будем называть её потенциалом. Потенциал может принимать значения 0, 1 или 2.
Атаки обозначаем так: [ мощность атаки, потенциал ]. Например, атака [4:1].


Рис 1. Атака [4:1]

В ходе анализа мы будем оценивать все клетки, которые входят в определенную область. У каждой клетки будет просчитываться её вес. Он вычисляется на основе весов всех атак, на которые влияет данная клетка.

Суть анализа

Представим, что на игровом поле уже есть несколько атак одного и второго игрока. Кто-то из игроков делает ход (пускай крестики). Естественно ход он делает в пустую клетку – и тем самым он может:

Суть анализа в следующем:

По сути, таким алгоритмом мы проверяем, что будет, если мы пойдем так… а что будет если так пойдет оппонент. Мы смотрим на один ход вперед и выбираем наиболее подходящую клетку – с наибольшим весом.

Если какая-то клетка имеет больший вес, нежели другая, значит она приводит к созданию более опасных атак, либо к блокировке сильных атак противника. Все логично… мне кажется.
Если зайти на страницу и написать в консоли SHOW_WEIGHTS = true, можно визуально прочувствовать работу алгоритма (Будут показаны веса клеток).

Веса атак

Пораскинул я мозгами и привел такое соответствие атак и весов:

Подобрано эмпирически – возможно это не оптимальный вариант.

Я добавил в массив атаки мощностью 5 с запредельно большим весом. Объяснить это можно тем, что бот анализирует игру, смотря на шаг вперед (подставляя фигуру в клетку). Пропуск такой атаки есть ни что иное, как поражение. Ну или победа… смотря для кого.

Атаки с большим потенциалом ценятся выше.

Атака [4:2] в большинстве случаев решает исход игры. Если игроку удалось создать такую атаку, то оппонент уже не сможет ее заблокировать. Однако это еще не победа. Противник может быстрее завершить игру, даже при наличие у нас на поле атаки [4:2], поэтому ее вес ниже, чем у атак мощностью 5. Смотри пример ниже.


Рис 2. Атака [4:2]

«Рваные» атаки

В этом абзаце код не представлен. Здесь мы вводим понятие делителя атаки и объясняем суть «рваных атак».

Рассмотрим такую ситуацию: при подстановке фигуры на удалении нескольких пустых клеток, но не более 5-и, расположена еще одна.

И вроде бы, две одинаковые фигуры, на одной линии… визуально это похоже на атаку, а по факту нет. Не порядок, так как такие «рваные» атаки также несут в себе потенциальную угрозу.

Читайте также:  как менять замки на дверях квартиры

Специально для таких случаев, для каждой атаки будем просчитывать делитель. Изначально его значение равно 1.

Таким образом, «рваные» атаки так же будут учитываться ИИ. На самом деле, это будут обычные атаки, но чем они дальше находятся от сканируемой клетки, тем меньшее влияние на нее оказывают и, соответственно, имеют меньший вес (благодаря делителю).

Алгоритм поиска атак

Во-первых, создадим класс атаки. У атаки будет 3 атрибута, о которых я писал ранее:

И один метод, который будет возвращать вес данной атаки:

Далее. Поиск всех атак для одной клетки мы разделим на:

Однако, нам не нужно проверять всю линию целиком. Максимальная мощность атаки, которая нас интересует – 5. Безусловно, создать атаку мощностью, скажем, 6 – возможно. Но для ИИ, который анализирует игровую ситуацию следующего хода, все равно, что 6, что 5. Перспектива получить одну из этих атак говорит о конце игры на следующем ходу. Соответственно, вес анализируемой клетки будет в обоих случаях будет одинаковым.

Здесь надо остановиться, так как может возникнуть вопрос: зачем проверять 6-ую клетку, если максимальная мощность атаки – 5. Ответ – это нужно для определения потенциала удаленной от центра атаки.

Вот пример: атака мощностью 1 на картинке находится на границе сканируемой области. Чтобы узнать потенциал этой атаки нужно «заглянуть за границу».


Рис. 3. Сканирование 6-ых клеток. Если не просканировать 6-ую клетку, можно неправильно определить потенциал атаки.

Для завершения некоторых атак может просто не хватать места. Посчитав attackplace мы заранее можем понять, какие из атак бесперспективны.


Рис. 4. Место для атаки

1) Начнем с центральной клетки. Она должна быть пустой (мы ведь собираемся сделать в нее ход, не так ли? Однако мы не забываем, что наш ИИ должен подставлять фигуры в данную клетку для анализа следующего хода. Фигура, которую мы подставляем – this.subfig – по умолчанию крестик. Поскольку центральная клетка изначально будет содержать в себе какую-либо фигуру после подстановки, то она будет принадлежать какой-то атаке this.curAttack:

Все эти пункты мы отобразили в значениях конструктора по умолчанию – смотри код выше.

2) Далее, уменьшая итератор, перебираем 5 клеток с одной стороны от сканируемой. За это отвечает функция getAttacks( cellX, cellY, subFig, dx, dy ), где:

cellX, cellY – координаты проверяемой клетки
subFig – фигура, которую мы подставляем в проверяемую клетку
dx, dy – изменения координат x и y в циклах – так мы задаем направление поиска:

Обратите внимание, что если checkCell() что-то вернет, то выполнение цикла прекращается.

3) Проверяем фигуры данных клеток.
За это отвечает функция checkCell( x, y ):

Для начала запишем фигуру в переменную fig:
Model.Field – наше игровое поле.

fig может быть ‘x’, ‘o’, ‘b’ (граница), 0 (пустая клетка).

4) Если на 5-ой клетке фигура совпадает с центральной клеткой, значит атака «уперлась» в границу и для определения потенциала атаки придется «проверить границу» ( this.checkEdge = true).

Функция checkCell – готова. Однако продолжаем работать над классом checkLine.

5) После выполнения первого цикла, надо «развернуться». Переводим итератор в центр и центральную атаку, с индексом 0, убираем из массива атак и устанавливаем как текущую.

6) Далее идем в другую сторону от текущей клетки, увеличивая итератор.
Абсолютно такая же проверка фигур. (Код уже написан – функция getAttacks)

7) Все, мы собрали все атаки, что были на линии в один массив.
На этом с классом checkLine всё… закончили.

Ну а дальше все просто – создаем объект checkLine для каждой из линий (2 диагонали, горизонталь и вертикаль) и вызываем функцию getAttacks. То есть, для каждой линии — свой объект checkLine и, соответственно, свой набор атак.

Пусть за все это отвечает функция getAllAttacks() – уже отдельно от описанных выше классов;

На выходе имеем объект со всеми атаками для проверяемой клетки

Однако вы, возможно, заметили некую функцию-фильтр. Ее задача – отсеивать «бесперспективные» атаки:

Да соберем, наконец, все воедино

Итак, основной ад позади — описан выше. Пора слепить из него что-то рабочее. Функция countWeight( x, y ) — принимает на вход координаты клетки, а возвращает ее вес. Что же у нее под капотом?

Во-первых, получим массив всех атак, которым клетка принадлежит. ( getAllAttacks( x, y ) ). Перебирая все линии, мы считаем количество брейкпоинтов. Если 2 брейкпоинта – вспоминаем, что такая ситуация может решить исход игры, и увеличиваем вес клетки на 100.
Однако все брейкпоинты должны принадлежать одному игроку, поэтому пришлось реализовать проверку в 2 шага: сначала крестики, потом нолики.

Поскольку в массиве весов атак ( ATTACK_WEIGHTS[] ) я не предусмотрел атаки мощностью 6 и больше, мне пришлось заменить их на атаки мощностью 5. Разницы никакой – все они приводят к концу игры.

Ну и суммируем веса атак – к этому все и шло.

Еще небольшой момент: чтобы бот в конце игры не тупил, когда он уже построил атаку мощностью 4 и думает над текущем ходом, необходимо значительно увеличить вес клетки для завершения такой атаки. Без этого, ИИ, просто на просто, может начать защищаться от «опасных» атак оппонента, хотя игра, казалось бы выиграна. Последний ход важен.

Теперь при вызове этой функции для конкретной клетки мы получим ее вес. Проводим эту операцию для всех клеток и выбираем наилучшую (с наибольшим весом). Туда и ходим)

Остальной код вы сможете найти на github. Материала уже предостаточно, и его изложение, как я не пытался, оставляет желать лучшего. Но если ты смог дочитать до этого момента, дорогой читатель, то я тебе благодарен.

Мое мнение о полученном результате

Сойдет! Да, его можно обыграть, однако сделать это немножко проблематично лично для меня. Возможно я просто недостаточно внимателен. Попробуйте и вы свои силы.

Знаю, что можно проще, но не знаю как. Хотелось бы выслушать людей знающих или посмотреть на иные реализации такого бота.

Знаю, что можно лучше. Да… можно воспользоваться известными алгоритмами, вроде минимакса, но для этого нужно обладать некоторой базой знаний в области теории игр, чем похвастать увы не могу.

В будущем планирую добавить анализ брейкпоитов на несколько шагов вперед, что сделает бота еще более серьезным соперником. Однако сейчас не имею четкого представления о реализации сего; лишь имею предстоящую сессию и недописанный диплом – что меня огорчает.

Источник

Развивающий портал