Игра 2048 в представлении не нуждается, однако для тех, мимо кого она все же прошла, я кратко опишу правила.
Алгоритм игры не представляет из себя ничего сложного, подобные задачи дают школьникам на уроках программирования. Нет ничего проще, чем по исходному состоянию игрового поля и направлению движения определить следующее состояние и вывести его на форму. Но это некрасиво - не видно перемещения чисел на поле. А значит придется рассчитывать и выводить на экран промежуточные состояния движения, делая между ними паузы. Также хочется чтобы появление новых чисел на поле (ход компьютера) было отделено по времени от сдвига клеток (ход игрока). Несмотря на то, что 1С не предназначена для создания динамичных игр, в данном случае задача вполне решаема.
Рано или поздно стандартная игра надоедает. На этот случай предусмотрено еще 3 варианта игры.
Игра "с помехой".
На поле присутствует серая клетка, которая перемещается аналогично остальным, но не может быть ни с чем объединена. Мешая таким образом достижению цели, она делает игру сложнее и интереснее.
Игра на выживание.
В процессе игры запущен таймер обратного отсчета. По достижению нуля игра останавливается. После объединения клеток значение таймера слегка увеличивается. "Надо бежать со всех ног чтобы оставаться на месте, а чтобы куда-нибудь попасть, надо бежать еще быстрее (с)"
Бесконечная игра.
Во всем совпадает со стандартной, но все числа, начиная от 2048, исчезают. Тем самым освобождается место и, теоретически, игра может никогда не закончиться. Цель - набрать как можно больше очков.
Да, чуть не забыл, управление в игре - с помощью клавиш Num4, Num5, Num6, Num8. К сожалению, не удалось использовать мой любимый метод управления стрелками через табличный документ.
Что внутри
А теперь немного о программных решениях под капотом. Может кому-нибудь эта информация пригодится, или, хотя бы, просто будет интересна.
Самое важное здесь - обеспечение анимации, т.е. как можно более плавного перемещения чисел при сдвиге. Простого способа передвигать элементы формы в платформе не существует, поэтому единственным выходом является поочередная установка текста в заголовках заранее размещенных на форме элементов. Причем делать это нужно с примерно одинаковыми паузами, чтобы игроку движение казалось не моментальным и равномерным. То есть примерная схема такая:
Нажатие клавиши -> сдвиг на 1 позицию -> пауза -> сдвиг на 1 позицию -> пауза -> сдвиг на 1 позицию, уперлись в край поля -> пауза -> ход компьютера.
И все это, разумеется, должно работать на стороне клиента. Вот только функции паузы в платформе для этого нет. ВызватьПаузу() не предлагать, у нее другое предназначение. Если мы хотим обойтись только собственными возможностями платформы, то нам остается только задействовать механизм обработчиков ожидания. ПодключитьОбработчикОжидания() позволяет нам использовать интервал от 0.1 секунды, что для нас вполне подойдет. Правда с таким маленьким интервалом обработчик может быть выполнен только один раз, но ничего, будем подключать его постоянно. В программе предусмотрена процедура ТикТаймера(), в теле которой и обеспечивается выполнение алгоритма игры. В процедуру обработки ожидания нельзя передавать параметры, поэтому в ней используются "глобальные" реквизиты формы и переменные модуля. Совокупность этих реквизитов и переменных исчерпывающим образом определяет состояние игры в любой момент времени. Специалисты сразу же увидят здесь модель цифрового автомата, да, это он и есть. Так как состояние игры однозначно определяется набором свойств, то мы получаем еще один замечательный факт: сохранив эти свойства (например при закрытии формы) и потом восстановив их (например при следующем открытии), мы вернемся ровно в то состояние игры, которое было перед сохранением. Так, закрыв форму во время движения клеток, и открыв форму заново, мы увидим, что клетки продолжают движение.
А что будет происходить при нажатии клавиш игроком? Игнорировать их, пока не закончились движения клеток и ход компьютера? Нехорошо, для игрока это будет выглядеть как неработающие кнопки. Придется все нажатия клавиш сохранять в отдельную очередь FIFO и по одному доставать из очереди и обрабатывать. В программе для этого есть клиентская переменная модуля ОчередьНажатий.
Теперь подумаем как игрок будет управлять игрой. В некоторых аналогах 2048 используются 4 кнопки формы - вверх, вниз, вправо, влево. Не делайте так. Никто не захочет в игре кликать мышью несколько раз в секунду, да еще и в разные кнопки. Единственный вариант - горячие клавиши для клавиатуры. А к чему их привязать? Привязать-то их нужно к командам формы, но они должны обязательно присутствовать на форме, причем желательно незаметно для пользователя. Есть решение - разместим на форме миниатюрную прозрачную декорацию-надпись без заголовка, и в контекстное меню этой надписи добавим нужные команды с горячими клавишами.
Еще одна интересная задача - выбор цветов, так, чтобы цвет клетки плавно менялся при увеличении числа. Казалось бы чего проще - взял, два крайних цвета, разложил их на RGB, и нашел десять промежуточных значений по каждому из каналов, и получил новые цвета. Звучит логично, но на самом деле велика вероятность, что промежуточные цвета будут тусклыми и даже серыми. Например промежуточный цвет между красным RGB(255,0,0) и бирюзовым RGB(0,255,255) будет RGB(128,128,128) - серым. Лучше аналогичным образом использовать цветовые пространства HSV или HSL. Средств для этого в сети достаточно, я использовал свою обработку.
И, наконец, пару слов об интерфейсе. Игра казуальная, она обязана быть простой и минималистичной. На форме не должно быть ничего лишнего, кроме самого необходимого. Относительно редко выполняемые команды (смена типа игры) - спрятаны в подменю. Не надо заставлять пользователя совершать лишние действия - после окончания игры новая игра начинается автоматически. Не надо пугать пользователя дополнительными вопросами "Вы нажали кнопку закрыть, а Вы уверены что хотите закрыть неоконченную игру?", лучше закрыть форму, и, если пользователь закрыл по ошибке, восстановить ее состояние при следующем открытии. Не надо заставлять читать лишние надписи вроде "Начата игра на выживание" или "... стандартная", лучше сделать клетки разного цвета при разных типах игры. Все, что выше сказано о минимализме, особенно актуально для нового воздушного интерфейса 8.5.
Надо сказать, интерфейс 8.5 удивительно хорошо подошел для этой игры, и в светлой, и в темной теме.
В интерфейсе "Такси" она тоже работает, но вид у нее уже совсем не тот.
Игра тестировалась в тонком клиенте 8.5.4.1306 (тестовая, с сайта для разработчиков), интерфейс 8.5 обычный (не компактный).
Работает на любых конфигурациях, не требует БСП.
Как всегда, приветствуются замечания / дополнения / комментарии.
Некоторые из прочих моих публикаций
PS: AIDetector показывает, что текст выше написан человеком. Когда роботы захватят мир, я не смогу себя выдать за ИИ и останусь без работы(.
Проверено на следующих конфигурациях и релизах:
- 1С:Библиотека стандартных подсистем, редакция 3.1, релизы 3.1.12.238
Вступайте в нашу телеграмм-группу Инфостарт