Главная » Хабрахабр » Пятничный JS: игра в 0 строк JS и CSS

Пятничный JS: игра в 0 строк JS и CSS

Возможно, многие из старожилов помнят эпидемию статей с заголовками вида "%something% в 30 строк JS". А также последовавший за ней эпичный пост "Игра в 0 строк кода на чистом JS", после которого эпидемия резко сошла на нет. Полностью осознавая, что этот шедевр мне никогда не превзойти, я всё же спустя пять лет решил докинуть свои пять копеек.

Только голый HTML, только хардкор. Дамы и господа, вашему вниманию предлагается игра «Крестики-нолики» в нуль строк JS, а также, в отличие от игры, упомянутой выше, в нуль строк CSS (включая инлайн стили).

→ Ссылка на игру

Под катом я расскажу, почему игра без JS оказалась в рубрике «Пятничный JS», а также другие грязные подробности. Выглядит неказисто, зато будет работать в любом браузере. Игра состоит из почти 6 тысяч страниц статического HTML, ссылающихся друг на друга. Впрочем, Америку я никому не открою, если вы опытный кодер, можете под кат даже не заходить
Собственно, всё устроено очень тупо. Очевидно, писать 6к страниц руками — удовольствие ниже среднего. При тыке на клетку игрового поля происходит переход на страницу, где ход в эту клетку уже сделан. Поэтому (сюрприз!) страницы генерируются JS-скриптами с помощью NodeJS.

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

С одной стороны, вроде как является. Написав предыдущую строчку, я вдруг задумался, не является ли выражение «JS-скрипт» тавтологией, как «CD-диск» или «VIP-персона». Однако пост всё-таки не о филологии, потому лирическое отступление заканчивается и начинается лирическая атака.
С другой, JS — это всё-таки не аббревиатура, а сокращение несколько иной природы.

Сначала мы строим так называемое дерево игры — совокупность всех возможных игровых состояний и переходов между ними. Начальное состояние игры в моём коде представлено следующим образом:

const initialState =
}

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

Дальше мы начинаем, прошу прощения за тавтологию, с начального состояния и делаем следующее:

  1. Проверяем, не является ли состояние терминальным (победа крестиков, победа ноликов, ничья).
  2. Если да, добавляем информацию об этом в объект состояния и заканчиваем.
  3. Если нет, проходимся по всем клеткам поля.
  4. Для каждой пустой клетки поля создаём новое состояние игры, в котором текущий игрок сделал ход в эту клетку, а ход перешёл к следующему игроку.
  5. В поле moves текущего состояния добавляем запись о возможном ходе. Ключом в этой записи служит индекс клетки, а значением — ссылка на новое состояние.
  6. Повторяем этот алгоритм рекурсивно для всех вновь появившихся состояний.

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

Пройдясь по объекту moves, мы заполняем пустые клетки поля ссылками на страницы, соответствующие ходам, сделанным в эти клетки. Затем из каждого объекта игрового состояния мы генерируем HTML-страницу. Добавляем всякие приятные мелочи вроде указания, который игрок ходит, и ссылки на начальную страницу — и вуаля! Затем превращаем одномерный массив поля в двумерную HTML-таблицу.

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

  1. Сначала рекурсивно (на самом деле нет) для каждого игрового состояния вычисляется ожидаемый результат игры — тот, который будет достигнут, если обе стороны будут играть идеально.
  2. Затем дерево игры модифицируется следующим образом: вместо хода игрока мы теперь делаем сразу два хода. Второй ход — ход искусственного интеллекта. При этом из всех возможных ответов на ход игрока выбирается тот, у которого самый лучший ожидаемый результат. Таким образом, тыкнув на пустую клетку, игрок сразу переходит на позицию, где в этой клетке появился крестик (или нолик), а в какой-то другой появился нолик (или крестик).
  3. Все игровые позиции, соответствующие ходам, которые ИИ не делает, безжалостно отбрасываются.
  4. Затем из оставшихся позиций в отдельную папочку генерится HTML — абсолютно аналогично случаю двух игроков.

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

На этом, в общем-то, всё. Кстати о гитхабе: можете посмотреть там код целиком (ссылка присутствует на заглавной странице игры). До новых встреч. До свидания, девочки и мальчики.

S. Замена переносов строки с Windows-style на Unix-style — это очень долго, когда речь идёт о 6 тысячах файлов. P. Я пожалел, что не позаботился об этом на этапе написания кода, но всё-таки мужественно дотерпел до конца git add.


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

KDD 2018, день второй, семинары

Побывал на двух таких тусовках. Сегодня на KDD 2018 день семинаров — вместе с большой конференцией, которая начнется завтра, несколько групп собрали слушателей по некоторым специфичным темам. Анализ временных рядов С утра хотел пойти на семинар по анализу графов, но ...

Zabbix на стероидах: как устроена единая платформа мониторинга Сбертеха

Привет, Хабр! Меня зовут Сергей Прутских, я руковожу направлением мониторинга компании «Сбербанк-Технологии». Основная задача нашей организации — разработка и тестирование программных продуктов для Сбербанка. Для этого в компании сосредоточена крупная ИТ-инфраструктура — 15 тысяч серверов разделены примерно на 1500 тестовых ...