- PVSM.RU - https://www.pvsm.ru -
Здравствуйте.
Этот пост посвящен краткому разбору того, как на FBD написать простейшую игрушку «2048».
Сразу помещу картинку с результатом:
Если интересно, как это сделано, добро пожаловать под кат.
Игра «2048». Правила.
1. В каждом раунде появляется плитка номинала «2» (с вероятностью 90 %) или «4» (с вероятностью 10 %).
2. Нажатием стрелки игрок может скинуть все плитки игрового поля в одну из 4 сторон. Если при сбрасывании две плитки одного номинала «налетают» одна на другую, то они слипаются в одну, номинал которой равен сумме соединившихся плиток. После каждого хода на свободной секции поля появляется новая плитка номиналом «2» или «4». Если при нажатии кнопки местоположение плиток или их номинал не изменится, то ход не совершается.
3. Игра заканчивается поражением, если после очередного хода невозможно совершить действие.
Как мы видим, правила предельно простые. Начинаем реализацию алгоритма.
Для решения данной задачи делаем макрос «Случайное». Т.к. чистого «random» в контроллере нет, идем старым и проверенным путем:
Делаем макрос, на выходах которого будут формироваться случайные координаты клетки (строка и столбец) а так же признак того, что в данную клетку должна быть помещена четверка.
Итак, чуть выше мы получили случайные координаты ячейки, в которую должны поместить новое значение (2 или 4). Преобразуем это значение в шестнадцать логических признаков с помощью макроса «Установка».
Как понятно из названия, это основной макрос, который будет отображать нам состояние ячейки. Всего таких макросов 16 штук. Но в этом то и весь смысл, что они все абсолютно одинаковые (этого удалось добиться с помощью выноса алгоритмов установки значений а также отдельной обработки команд от пользователя). Таким образом программа быстро и легко переделывается т.к. при изменении логики достаточно поменять только один алгоритм макроса, и все остальное поменяется автоматом.
Входы:
Выходы:
Начинка макроса:
Основу макроса составляет алгоритм «Память», в котором хранится текущее значение ячейки. Значение, записываемое в данный алгоритм, выбирается посредством четырех последовательных алгоритмов «Выбор». Первым алгоритмом «Выбор» мы проверяем, какое значение должны записать в ячейку — «двойку» или «четверку». Второйf алгоритм «Выбор» проверяет — пустая ли это ячейка. Если ячейка пустая, то мы пишем туда выбранную двойку или четверку. Третий алгоритм «Выбор» проверяет начало это игры или нет. Если это начало игры, то без всяких проверок пишется выбранное ранее значение. Четвертый алгоритм «Выбор» самый приоритетный. Проверяем, пришел ли признак «Очистить», и если пришел, то принудительно записываем в память ноль очищая ячейку. Алгоритм «Сравнение» формирует признак, пустая это ячейка или нет. Далее с помощью двух алгоритмов «И» и «ИЛИ» мы проверяем, что если нам пришла команда установить в ячейку новое случайное значение и эта ячейка пустая, или это вообще начало игры, то выставляем признак того, что ячейка обработана и ход завершен.
Этот макрос и есть основа всей логики, реализованной в игре.
Макрос имеет два входа и три выхода. Вход «Команда» это логический признак того, что макросу нужно обработать 4 входных элемента и выдать выходные значения. Макрос универсальный и используется для обработки всех четырех команд. Он сделан под команду «вправо», но для обработки команды «влево» достаточно подать на вход элементы строки в обратном порядке и в таком же обратном порядке забрать их с выхода. Для обработки команд «вверх» и «вниз» на вход подаются соответствующие значения из разных строк, формирующие столбец.
Это и есть самое слабое место алгоритма. Для обработки строки приходится прогонять программу три раза (в пределе). Из-за того, что проверка может выполнится при первом проходе программы, а может только при третьем, а все 16 ячеек должны отработать одновременно, приходится ставить большое количество элементов памяти и триггеров в программе. Но пока простого и красивого способа реализовать сортировку в один проход я не придумал. Но еще не вечер. Когда будет время, займусь этим плотнее и возможно вся программа упростится раза в два.
Когда наконец-то проверка выполнена, и все элементы у нас расположены по порядку без пропусков, формируется импульс, по которому запускается попарное сравнение элементов, начиная с нижнего. Сравниваем между собой четвертый и третий элементы. Если они равны, то в четвертую ячейку записываем их сумму, а все остальные элементы сдвигаем на одну ячейку вниз. Далее сравниваем между собой второй и первый элементы и поступаем аналогично. Если четвертый и третий элементы между собой не сравнились, то сравниваем третий и второй элементы, и т.д. Тут алгоритм простой благодаря тому, что мы уже отсортировали все ненулевые ячейки и точно знаем, что между заполненными ячейками у нас нет пустых ячеек. Вот эта сортировка выполняется в один проход. В конце получившиеся значения элементов записываются на выход и формируется выходной сигнал «Готово».
Одновременно нам нужно проверять, что при подаче команды хотя бы один набор элементов изменился. В противном случае данная команда не является ходом и делать при ее подаче ничего не надо. Для этой проверки служат элементы внизу макроса, которые у исходной последовательности проверяют, что нужна хотя бы одна перестановка и хотя бы одна пара клеток «схлопнулась». В этом случае формируется выходной сигнал «сработало».
Вот, собственно, и все. Основные элементы программы у нас готовы. Осталось их только связать между собой. Пара слов об остальных вспомогательных элементах.
Мы рассмотрели все элементы программы. Теперь достаточно их объединить и все будет работать.
Ну тут все просто и делается за 5 минут.
Рисуем один квадратик. Задаем ему значение равное значению соответствующей ячейки. Меняем цвет фона в зависимости от значения ячейки. Далее копируем квадратик пятнадцать раз и получаем готовое поле. Делаем несколько подписей, добавляем кнопки «старт» и «Сброс» и большую надпись поверх поля «Game over».
Вид окна в режиме «рисование».
Вот и все готово. Запускаем и можно играть.
Пока пил кофе в обед, подумал: «какого хрена?» и решил переделать макрос обработки. Помните, я говорил, что обработка строки проходит в несколько циклов и это самое слабое место всей программы. Решил от этого избавится и выставить все проверки в одну последовательность. С одной стороны мы получаем лишние проверки если даже на старте у нас условие выполнилось. Но с другой стороны это решение (пусть и громоздко и некрасиво выглядящее) позволяет нам избавится от порнографии с кучей триггеров, кучей ячеек памяти и необходимости все это дело синхронизировать. Далее под катом новый макрос обработки и общий вид программы. Можно обратить внимание на то, как упростился макрос обработки (нет ни одной обратной связи) и стали лишними навесные костыли из элементов для синхронизации признаков, возникающих в разных циклах выполнения программы.
В очередной раз мы сделали пусть и бесполезную, но весьма интересную с точки зрения реализации алгоритмов игрушку. Более того, я специально не стал переписывать пост и заменять старые макросы новыми чтобы показать, как можно быстро кардинально переделать программу, при этом не затрагивая остальную часть. Что касается простоты написания программ на языке FBD, то думаю самым красноречивым здесь будет тот факт, что на написание этого поста я потратил времени раза в 2-3 больше, чем на написание программы.
То, что осталось нереализованным.
1. Подсчет очков. Я не спец в этой игре. Более того играл в нее только во время написания данного поста в своей программе и дальше рекорда в 256 дойти пока не получилось. Так вот, сделать подсчет очков несложно. Просто в макросе «Обработка» нужно при суммировании значений клеток с одинаковым номиналом дополнительно выдавать эту сумму на выход макроса, а снаружи подсчитывать общую сумму этих значений. Но я не вижу в этом никакого смысла, т.к. цель игры «получить плитку с максимальным номиналом».
2. «Умный» алгоритм выбора случайного значения, для установки двойки или четверки в пустую клетку. Я написал чуть выше как это можно сделать. Но т.к. там ничего интересного нет, то оставим это всем желающим.
На этом все. Надеюсь было интересно.
Автор: OPCSenator
Источник [4]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/nenormal-noe-programmirovanie/112329
Ссылки в тексте:
[1] хостинг: https://www.reg.ru/?rlink=reflink-717
[2] Image: http://radikal.ru/fp/8cb37e7131d9417b9bb9559d12fa765e
[3] Image: http://radikal.ru/fp/8ef8169e072046109612361a747079ef
[4] Источник: https://habrahabr.ru/post/277203/
Нажмите здесь для печати.