...

понедельник, 19 мая 2014 г.

[Перевод] Игра 2048 в Wolfram Mathematica

Перевод поста 2048, Wolfram Style, написанного для официального блога компании Wolfram Research Дэном Фортунато, младшим программистом Wolfram|Alpha Parser Content.

Перевод сделал Сергей Шевчук (opckSheff на Хабрахабре)

Архив с файлом Wolfram Mathematica, в котором содержится код, вы можете скачать здесь.


2048-Game-In-Wolfram-Mathematica_43.gif


Если в течение последних нескольких недель вы выходили в интернет, то вы вряд ли могли не встретиться с игрой под названием 2048, разработанной Габриэлем Чирулли. Будучи основанной на похожих играх, 1024! от Veewo Studio и THREES от Ашера Воллмера, эта игра имеет простую механику, которая затянет вас надолго — перемещайте по полю фишки, на которых написаны степени числа 2 и соединяйте их попарно, чтобы получить ещё более высокие степени. Главная цель игры — получить фишку 2048. Достаточно сложно объяснить, насколько в действительности интересна и увлекательна эта игра, поэтому я рекомендую вам самим сыграть в нее.


Чтобы отдать должное этой простой игре (и в честь всех математических игр!), я решил продемонстрировать всю мощь Языка Wolfram, используя его, чтобы разработать нашу собственную версию 2048. Начнём!



Основной структурой для игрового поля послужит матрица 4х4, заполненная пустыми элементами (строками нулевой длины):


In[1]:=


2048-Game-In-Wolfram-Mathematica_1.gif


Out[2]=


2048-Game-In-Wolfram-Mathematica_2.png


После начала новой игры я случайным образом расположу на поле две фишки со значениями 2 или 4. Больший приоритет я отдам фишке 2, таким образом, она будет появляться на поле чаще.


In[3]:=


2048-Game-In-Wolfram-Mathematica_3.png


In[4]:=


2048-Game-In-Wolfram-Mathematica_4.png


Out[4]=


2048-Game-In-Wolfram-Mathematica_5.png


Настало время сделать наше игровое поле немного красивее. Я могу полностью повторить стиль оригинальной игры, импортировав её CSS-стиль (CSS — Cascading Style Sheets, каскадные таблицы стилей). Как вы можете видеть, в CSS я смог найти цвета для фона и текста всех фишек.


In[5]:=


2048-Game-In-Wolfram-Mathematica_6.gif


Out[8]=


2048-Game-In-Wolfram-Mathematica_7.png


Теперь у меня есть список, содержащий каждый номер фишки и соответствующие ему цвета! Далее я могу обработать его, создав функцию для поиска цвета и перевода её из HEX (шестнадцатиричной записи цвета, используемой в CSS) в RGB (цветовую модель, основанную на сочетании красного, зелёного и синего цветов). Также я определяю цвета для остального игрового поля и, на всякий случай, для некоторых цветов по-умолчанию.


In[9]:=


2048-Game-In-Wolfram-Mathematica_8.png


In[10]:=


2048-Game-In-Wolfram-Mathematica_9.gif


In[13]:=


2048-Game-In-Wolfram-Mathematica_10.gif


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


In[15]:=


2048-Game-In-Wolfram-Mathematica_11.png


In[16]:=


2048-Game-In-Wolfram-Mathematica_12.png


In[17]:=


2048-Game-In-Wolfram-Mathematica_13.png


Я определил функцию drawTile таким образом, чтобы впоследствии её можно было легко изменить…


In[18]:=


2048-Game-In-Wolfram-Mathematica_14.png


Out[18]=


2048-Game-In-Wolfram-Mathematica_15.gif


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


In[19]:=


2048-Game-In-Wolfram-Mathematica_16.png


In[20]:=


2048-Game-In-Wolfram-Mathematica_17.png


Out[20]=


2048-Game-In-Wolfram-Mathematica_18.gif


Выглядит красиво! Теперь нам нужно научиться управлять игрой.


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


In[21]:=


2048-Game-In-Wolfram-Mathematica_19.png


In[22]:=


2048-Game-In-Wolfram-Mathematica_20.png


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


In[23]:=


2048-Game-In-Wolfram-Mathematica_21.png


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


In[24]:=


2048-Game-In-Wolfram-Mathematica_22.png


Сдвиг вправо осуществляется так же, с одним незначительным изменением — я хочу, чтобы сочетания одинаковых фишек справа объединялись до сочетаний, находящихся левее. Рассмотрим в качестве примера строку {$empty, 2, 2, 2}. Используя функцию combineLeft и нажав стрелку влево, я получу строку {$empty, $empty, 4, 2}, но на самом деле я хочу, чтобы сначала объединилась правая пара двоек. Переворот строки, сдвиг ячеек влево и обратный переворот легко решают проблему.


In[25]:=


2048-Game-In-Wolfram-Mathematica_23.png


In[26]:=


2048-Game-In-Wolfram-Mathematica_24.png


Теперь, когда у нас есть две этих функции, реализовать сдвиг вверх и вниз очень просто! Сдвиг вверх — это то же самое, что сдвиг влево на транспонированном игровом поле, за которым следует обратное транспонирование. Таким же отношением связаны и операции сдвига вправо и вниз.


In[27]:=


2048-Game-In-Wolfram-Mathematica_25.gif


Если клавиша нажата, новые фишки на поле должны добавляться только в том случае, если состояние поля изменилось, то есть если некоторые фишки переместились или объединились. Для этого необходимо отслеживать предыдущее состояние игрового поля.


Теперь научимся вести подсчёт очков в течение игры. Каждый раз, когда объединяются две фишки, я собираю их сумму функцией Sow, а потом использую на всех суммах функцию Reap, когда все возможные объединения совершены. Также я вывожу значение наибольшей полученной на данный момент фишки.


In[29]:=


2048-Game-In-Wolfram-Mathematica_26.png


Наконец, давайте добавим проверку на выигрыш и проигрыш. Игра считается выигранной, если наибольшая фишка на поле имеет значение 2048 или выше. Я проиграл, если доска заполнена и у меня больше нет возможных ходов. В данном случае я снова могу использовать язык шаблонных выражений, чтобы определить, остались ли на доске возможные сочетания фишек.


In[30]:=


2048-Game-In-Wolfram-Mathematica_27.png


In[31]:=


2048-Game-In-Wolfram-Mathematica_28.png


Используя функцию Dynamic, я могу поддерживать отображаемое игровое поле в полном соответствии с внесёнными изменениями. Кроме того, я могу окружить всё это функцией DynamicModule и использовать Initialization, чтобы настроить обработку нажатий клавиш и игровое поле. Поместив DynamicModule внутрь CreateDialog мы можем открывать игру в отдельном окне.


Наконец, игра полностью готова.


In[32]:=


2048-Game-In-Wolfram-Mathematica_31.png


2048-Game-In-Wolfram-Mathematica_32.gif


Сейчас всё выглядит вполне симпатично, но у нас в компании Wolfram Research мы любим что-нибудь более… заостренное. Такое, как Spikey — логотипы различных версий системы Mathematica и Wolfram|Alpha. Давайте немного изменим цвета фишек и их форму.


In[33]:=


2048-Game-In-Wolfram-Mathematica_33.gif


In[34]:=


2048-Game-In-Wolfram-Mathematica_34.png


Out[34]=


2048-Game-In-Wolfram-Mathematica_35.gif


In[35]:=


2048-Game-In-Wolfram-Mathematica_36.png


In[36]:=


2048-Game-In-Wolfram-Mathematica_37.png


In[37]:=


2048-Game-In-Wolfram-Mathematica_38.gif


In[39]:=


2048-Game-In-Wolfram-Mathematica_39.png


Теперь мы можем переключаться между двумя стилями при помощи кнопок.


In[40]:=


2048-Game-In-Wolfram-Mathematica_40.png


Out[40]=


2048-Game-In-Wolfram-Mathematica_41.png


In[41]:=


2048-Game-In-Wolfram-Mathematica_42.png


2048-Game-In-Wolfram-Mathematica_43.gif


Удачной вам игры!


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

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