Тактика и стратегия. Где играть в "2048"
Итак, алгоритм простой. Вам нужно собирать максимальное число в левом нижнем углу. При этом нельзя двигать кубики вверх! Иначе есть риск появления там маленьких цифр, которые вы не сможете сложить в большие, и они будут у вас просто занимать место. То есть, у вас будут выстраиваться, например, 1024, 512, 256,128. И, таким образом, вы в течении некоторого времени сложите заветный кубик 2048.Нужно внимательно следить за тем, чтобы в нижнем ряду (особенно в левом углу) не появлялось кубиков 2,4,8 и т. д. Иначе вам будет очень сложно собрать из них большие цифры. Это может помешать вам в достижении победы. Вот скрин: .
Также вы можете использовать такие стратегии:
Стратегии 2048
Для того чтобы выиграть в эту игру за меньшее количество ходов (да и вообще, чтобы просто выиграть ее), подумайте над стратегией. От того, как вы начнете игру, зависит многое и основные действия лучше продумать еще в самом начале.
1)Стратегия «Змейка»
Это самая простая стратегия – нужно просто последовательно жать четыре кнопки управления. Например, «Вверх», «Вправо», «Вниз», «Влево», повторить. Эта стратегия почти не требует усилий, и таким образом можно набрать около 512 очков, но скорее всего, в заполненном поле вы уже не сможете сделать никаких действий. Можно начать с этой стратегии, чтобы познакомиться с игрой и понять механизм действия, но для победы она не особо эффективна.
2)Стратегия 3ех кнопок (стратегия одного столбца)
Эта стратегия сложнее, но и более результативная. При сдвигании плиток нужно пользоваться только тремя кнопками управления. То есть, например, вы пользуетесь только кнопками «Вверх», «Вправо» и «Влево», а кнопку «Вниз» не нажимаете вообще. Таким образом, плитки суммируются с одной стороны поля и их легче «копить», но у этой стратегии есть и недостаток – при достижении определенной планки, приходится использовать 4ую кнопку, и ячейки с большим номиналом неизбежно сдвигаются в сторону. Там, где они раньше находились, появляются новые двойки или четверки, которые сложно объединить с большими числами, которые стоят рядом. Если вам повезет – хорошо, нет – придется начать все заново.
3) Стратегия одного угла
Эта стратегия похожа на предыдущую, но она подразумевает использование двух игровых кнопок – так, чтобы большие цифры копились в углу. Для этого нужно выбрать угол, например, левый нижний и в нем копить ячейки, нажимая преимущественно «Влево» и «Вниз», но, опять же, в определенный момент потребуется сдвинуть ячейки в другую сторону – влево или вверх. Для того чтобы большие цифры не меняли положения, лучше, чтобы ряд, в котором они находятся, был полностью заполнен (и по вертикали и по горизонтали) разными значениями (чтобы они не слились в одно).
4)Стратегия одного столбца с приоритетом
Основа этой стратегии такая же, как и у второй. Вы копите большие значения в одной стороне (например, внизу), и тогда вы вообще не используете кнопку «Вверх». При этом при использовании оставшихся трех кнопок, вы держите в приоритете движения в сторону того самого столбца с большими значениями. Если это нижняя строка, то значит в ситуации, когда есть возможность объединить ячейки в нескольких местах, вы всегда сдвигаете их вниз, а не вправо или влево.
5)Стратегия накопления по нарастающей (как я выше писал)
При использовании этой стратегии важен порядок, в котором находятся ячейки с цифрами. Они должны идти от большего значения к меньшему. В общем читайте все как я написал в начале ответа.
FAQ по опыту предыдущих статей
В: Вы что! Это большой проект, за 15 минут такое нельзя накодить!
О: Разумеется, чтобы придумать всё это и написать, у меня ушёл целый вечер и даже немножко ночи. Но прочитать статью и, скопировав из неё код, запустить работающую игру (при этом понимая, что происходит) вполне реально и за 15 минут.
В: Зачем тянуть ради такого простого проекта LWJGL? Гвозди микроскопом!
О: Вся работа с отображением вынесена в два с половиной метода в 2 интерфейса. Вы можете реализовать их на чём хотите, мне же удобнее на LWJGL.
В: А почему код выкладываете архивом? На гитхаб нужно!
В: У меня не получается подключить твою эту LWJGL! Что делать?
О: В прошлые разы у многих возникли с этим вопросом проблемы, поэтому мне показалось уместным посвятить этому немного времени.
Во-первых, выше я дал ссылку на папку с библиотеками на GitHub, которые использую я, чтобы не было путаницы с версиями и вопросов, где найти что-то. Папку из архива требуется поместить в папку проекта и подключить через вашу IDE.
Во-вторых, у многих пользователей InteliJ IDEA возникли проблемы как раз с их подключением. Я нашёл в сети следующий видеогайд:
После того, как я сделал всё в точности по нему, у меня библиотеки подключились корректно и всё заработало.
В: А почему на Java?
О: На чём бы я не написал, можно было бы спросить «Почему именно на X?». Если в комментариях будет реально много желающих увидеть код на каком-то другом языке, я перепишу игру на нём и выложу (только не Brainfuck, пожалуйста).
С чего начать?
Начать стоит с главного управляющего класса, который в нашем проекте находится выше остальных по уровню абстракции. Вообще отличный совет – в начале работы всегда пишите код вида if(getKeyPressed()) doSomething() , так вы быстро определите фронт работ.
/** * Точка входа. Содержит все необходимые действия для одного игрового цикла. */ public static void main(String args) { initFields(); createInitialCells(); while(!endOfGame){ input(); logic(); graphicsModule.draw(gameField); } graphicsModule.destroy(); }
Это наш main() . Что тут происходит, понять несложно – мы инициализируем поля, потом создаём первые две ячейки и, пока игра не закончится, осуществляем по очереди: ввод пользовательских данных (input()), основные игровые действия (logic()) и вызов метода отрисовки у графического модуля (graphicsModule.draw()), в который передаём текущее игровое поле (gameField).
Так как пока мы не знаем, какие поля инициировать, постараемся написать createInitialCells() . Но так как создавать клетки нам пока просто-напросто не в чем, то создадим класс игрового поля.
Создаём игровое поле
Всё наше поле – матрица чисел и методы, позволяющие их изменять (геттеры и сеттеры). Договоримся только, что пустую ячейку мы будем обозначать числом 0. Выглядеть этот класс будет так:
Public class GameField {
/**
* Состояние всех ячеек поля.
*/
private int theField;
/**
* Инициализирует поле и заполняет его нулями
*/
public GameField(){
theField = new int;
for(int i=0; i Возможно, пока не совсем очевидно, почему нужны именно такие геттеры и сеттеры, это станет ясно в процессе дальнейшей работы (при разработке с нуля следовало бы создать только getState() и setState() , а остальное дописывать потом). Совсем очевидно, что нам нужно просто вызвать два раза метод создания одной ячейки. /**
* Создаёт на поле начальные ячейки
*/
private static void createInitialCells() {
for(int i = 0; i < COUNT_INITITAL_CELLS; i++){
generateNewCell();
}
}
Заметьте, я не пишу вызов одного метода два раза. Для программистов существует одна максима: «Существует только два числа: один и много». Чаще всего, если что-то нужно сделать 2 раза, то со временем может возникнуть задача сделать это и 3, и 4 и куда больше раз. Например, если вы решите сделать поле не 4х4, а 10х10, то разумно будет создавать не 2, а 10 ячеек. Вы могли заметить, что в коде использована константа COUNT_INITIAL_CELLS . Все константы удобно определять в классе с public static final полями. Полный список констант, который нам потребуется в ходе разработки, можно посмотреть в классе Constants на GitHub. Теперь постараемся решить вопрос – как в матрице создать ячейку вместо одного из нулей? Я решил пойти по такому пути: мы выбираем случайные координаты, и если там находится пустая ячейка, то создаём новую плитку там. Если там уже есть плитка с числом, то пытаемся создать в следующей клетке (двигаемся вправо и вниз). Обратите внимание, что после хода не может не быть пустых клеток, т.к. ход считается сделанным, когда клетки либо переместились (т.е. освободили какое-то место), либо соединились (т.е. клеток стало меньше, и место снова высвободилось). Private static void generateNewCell() {
int state = (new Random().nextInt(100) <= Constants.CHANCE_OF_LUCKY_SPAWN)
? LUCKY_INITIAL_CELL_STATE: INITIAL_CELL_STATE;
int randomX, randomY;
randomX = new Random().nextInt(Constants.COUNT_CELLS_X);
int currentX = randomX;
randomY = new Random().nextInt(Constants.COUNT_CELLS_Y);
int currentY = randomY;
boolean placed = false;
while(!placed){
if(gameField.getState(currentX, currentY) == 0) {
gameField.setState(currentX, currentY, state);
placed = true;
}else{
if(currentX+1 < Constants.COUNT_CELLS_X) {
currentX++;
}else{
currentX = 0;
if(currentY+1 < Constants.COUNT_CELLS_Y) {
currentY++;
}else{
currentY = 0;
}
}
if ((currentX == randomX) && (currentY==randomY)) { //No place -> Something went wrong
ErrorCatcher.cellCreationFailure();
}
}
}
score += state;
}
Немного более затратен по времени и памяти другой метод, который тоже имеет право на жизнь. Мы складываем в какую-либо коллекцию (например, ArrayList) координаты всех ячеек с нулевым значением (простым перебором). Затем делаем new Random().nextInt(X) , где X – размер это коллекции, и создаём ячейку по координатам, указанным в члене коллекции с номером, соответствующем результату. Следующим по очереди у нас идёт метод input() . Займёмся им. Private static void input() {
keyboardModule.update();
/* Определяем направление, в котором нужно будет произвести сдвиг */
direction = keyboardModule.lastDirectionKeyPressed();
endOfGame = endOfGame || graphicsModule.isCloseRequested() || keyboardModule.wasEscPressed();
}
Отсюда нам нужно запомнить только, какие интерфейсы (графический и клавиатурный модули) нам нужно создать и какие методы в них определить. Если не запомнили – не волнуйтесь, ворнинги вашей IDE особо забыть не дадут. Так как многим не нравится, что я пишу эти модули на LWJGL, я решил в статье уделить время только интерфейсам этих классов. Каждый может написать их с помощью той GUI-библиотеки, которая ему нравится (или вообще сделать консольный вариант). Я же по старинке реализовал их на LWJGL, код можно посмотреть в папках graphics/lwjglmodule и keyboard/lwjglmodule . Интерфейсы же, после добавления в них всех упомянутых выше методов, будут выглядеть следующим образом: Вполне понятно, что если было определено направление сдвига, то нужно произвести в этом направлении сдвиг – в этом вся суть игры. Также, если сдвиг произвести удалось, необходимо создать новую ячейку. Направление для нового сдвига должно снова стать неопределённым – до следующего пользовательского ввода. Private static void logic() {
if(direction!=Direction.AWAITING){
if(shift(direction)) generateNewCell();
direction=Direction.AWAITING;
}
}
Вы могли заметить, что мы часто используем enum Direction для определения направления. Т.к. его используют различные классы, он вынесен в отдельный файл и выглядит так: Public enum Direction {
AWAITING, UP, DOWN, LEFT, RIGHT
}
Самое ядро нашего кода! Вот самое-самое. К слову, спорный вопрос, куда поместить этот метод – в Main.java или в GameField.java ? Я выбрал первое, но это решение нельзя назвать слишком обдуманным. Жду ваше мнение в комментариях. Очевидно, что должен быть какой-то алгоритм сдвига линии, который должен применяться к каждому столбцу (или строке, зависит от направления) по очереди и менять значения необходимым нам образом. К этому алгоритму мы и будем обращаться из Main.shift() . Так же такой алгоритм (вынесенный в метод) должен определять, изменил он что-то или не изменил, чтобы метод shift() это значение мог вернуть. /**
* Изменяет gameField, сдвигая все ячейки в указанном направлении,
* вызывая shiftRow() для каждой строки/столбца (в зависимости от направления)
*
* @param direction Направление, в котором необходимо совершить сдвиг
* @return Возвращает true, если сдвиг прошёл успешно (поле изменилось)
*/
private static boolean shift(Direction direction) {
boolean ret = false;
switch(direction) {
case UP:
case DOWN:
/*По очереди сдвигаем числа всех столбцов в нужном направлении*/
for(int i = 0; i< Constants.COUNT_CELLS_X; i++){
/*Запрашиваем очередной столбец*/
int arg = gameField.getColumn(i);
/*В зависимости от направления сдвига, меняем или не меняем порядок чисел на противоположный*/
if(direction==Direction.UP){
int tmp = new int;
for(int e = 0; e < tmp.length; e++){
tmp[e] = arg;
}
arg = tmp;
}
/*Пытаемся сдвинуть числа в этом столбце*/
ShiftRowResult result = shiftRow (arg);
/*Возвращаем линию в исходный порядок*/
if(direction==Direction.UP){
int tmp = new int;
for(int e = 0; e < tmp.length; e++){
tmp[e] = result.shiftedRow;
}
result.shiftedRow = tmp;
}
/*Записываем изменённый столбец*/
gameField.setColumn(i, result.shiftedRow);
/*Если хоть одна линия была изменена, значит было изменено всё поле*/
ret = ret || result.didAnythingMove;
}
break;
case LEFT:
case RIGHT:
/*По очереди сдвигаем числа всех строк в нужном направлении*/
for(int i = 0; i< Constants.COUNT_CELLS_Y; i++){
/*Запрашиваем очередную строку*/
int arg = gameField.getLine(i);
/*В зависимости от направления сдвига, меняем или не меняем порядок чисел на противоположный*/
if(direction==Direction.RIGHT){
int tmp = new int;
for(int e = 0; e < tmp.length; e++){
tmp[e] = arg;
}
arg = tmp;
}
/*Пытаемся сдвинуть числа в этом столбце*/
ShiftRowResult result = shiftRow (arg);
/*Возвращаем линию в исходный порядок*/
if(direction==Direction.RIGHT){
int tmp = new int;
for(int e = 0; e < tmp.length; e++){
tmp[e] = result.shiftedRow;
}
result.shiftedRow = tmp;
}
/*Записываем изменённую строку*/
gameField.setLine(i, result.shiftedRow);
/*Если хоть одна линия была изменена, значит было изменено всё поле*/
ret = ret || result.didAnythingMove;
}
break;
default:
ErrorCatcher.shiftFailureWrongParam();
break;
}
return ret;
}
Так как этот магический метод с алгоритмом должен будет по сути вернуть два объекта (новую линию и boolean , который будет говорить о наличии изменений в ней), создадим в начале класса Main для такого результата обёртку: /**
* Результат работы метода сдвига shiftRow().
* Содержит изменённую строку и информацию о том, эквивалентна ли она начальной.
*/
private static class ShiftRowResult{
boolean didAnythingMove;
int shiftedRow;
}
Можно, конечно. просто возвращать линию, а затем сравнивать её (не забываем, что это нужно делать через метод equals() , а не через ==), но на это будет уходит больше времени (из-за сравнение каждого элемента массива), но меньше памяти (на один boolean). Если подумать, то вам предстоит решить задачку - как за наименьшее (линейно зависящее от количества поступающих данных) время произвести с рядом чисел следующие последовательные операции: (1) если в ряде есть нули, их необходимо удалить, (2) если любые два соседних числа равны, то вместо них должно остаться одно число, равное сумме двух равных чисел. И (3) - если число получено через пункт (2), оно не может совмещаться с другими числами. Если представить себе алгоритм таким образом, то придумать линейное решение будет гораздо легче. Вот какой алгоритм должен получиться: При этом нам необходимо хранить место в возвращаемом массиве, на которое необходимо произвести запись. А вот как он выглядит в виде кода: Private static ShiftRowResult shiftRow (int oldRow) {
ShiftRowResult ret = new ShiftRowResult();
int oldRowWithoutZeroes = new int;
{
int q = 0;
for (int i = 0; i < oldRow.length; i++) {
if(oldRow[i] != 0){
if(q != i){
/*
* Это значит, что мы передвинули ячейку
* на место какого-то нуля (пустой плитки)
*/
ret.didAnythingMove = true;
}
oldRowWithoutZeroes[q] = oldRow[i];
q++;
}
}
}
ret.shiftedRow = new int;
{
int q = 0;
{
int i = 0;
while (i < oldRowWithoutZeroes.length) {
if((i+1 < oldRowWithoutZeroes.length) && (oldRowWithoutZeroes[i] == oldRowWithoutZeroes)
&& oldRowWithoutZeroes[i]!=0) { {
ret.didAnythingMove = true;
ret.shiftedRow[q] = oldRowWithoutZeroes[i] * 2;
i++;
} else {
ret.shiftedRow[q] = oldRowWithoutZeroes[i];
}
q++;
i++;
}
}
}
Игра 2048 стала однозначным хитом среди своих конкурентов, когда вышла в свет, она вызвала вокруг себя огромный ажиотаж, множество людей постили в социальных сетях сотни сообщений о своих рекордах в этой игре. Чем же она так затянула всех? Простота геймплея, красивый и приятный глазу дизайн - это игра, в которой приходится значительно подумать для того, чтобы победить, ну а как иначе? Данная игра, как бывает иногда, была создана не с целью обогащения, для автора она носила лишь развлекательный и познавательный характер. Итальянский 19-летний парень однажды вечером решил проверить свои знания и написать игру. Идея не полностью его, он модифицировал очень похожую на эту игру. Затем она стала набирать бешенную популярность, буквально за неделю о ней узнал весь мир, и всё благодаря простоте и затягивающему геймплею. Данная игра имеет открытый исходный код, который может посмотреть любой желающий, в том числе и для обучения. Но нам не нужно обучение чему-либо, кроме данной игры. Ведь мы здесь и хотим побеждать. Так каков секрет 2048, как выиграть в неё? Как выиграть? Для начала необходимо разобраться в самой игре и её правилах. Всё предельно просто. Поле, размером 4 на 4 кубика. В начале игры и при каждом ходе появляются в случайных местах кубики с цифрами 2 или 4 внутри (двойка появляется чаще). В игре существует 4 действия, вверх-вниз-влево-вправо. Каждым из них игрок двигает все кубики на игровом поле в определенную сторону, если им есть куда передвинуться. Если при передвижении между собой встречаются два кубика с одинаковой цифрой - они объединяются, и на их месте появляется в два раза большая ячейка. Например, сдвинув вместе две двойки, мы получим четвёрки, из двух четвёрок получим восьмёрку, а из двух восьмёрок - 16. Знатоки математики сразу заметили, что все эти цифры - степени двоек. И учитывая то, что 2048 - это 2 в 11 степени, придётся знатно потрудиться. Существует множество схем и стратегий для победы в эту игру. Тщательно почитайте и выберите ту, что понравится именно вам. А можете попробовать все и для себя найти самую эффективную и именно ту, что позволит вам узнать ответ на вопрос о том, если есть игра 2048, как выиграть. Можно заметить, что стратегии идут по усложнению, от самой простой к самой сложной и эффективной. Поэтому идите по порядку, и вы обязательно победите. На этом можно закончить данную статью про игру 2048. Как выиграть в неё, вы теперь "2048": как выиграть?
Игра "2048" - это математическая головоломка. Ее смысл состоит в том, чтобы на поле 4 на 4 квадратика соединять квадраты с одинаковыми цифрами до тех пор, пока не появится число 2048. В игре появляются только числа 2 и 4, из них и предлагается собрать победное число. Казалось бы, это очень просто, но на самом деле объединяться могут лишь одинаковые ячейки, а при каждом сдвижении квадратиков в сторону сдвигаются все квадраты на поле. Игра "2048" быстро стала очень популярной, и появились стратегии выигрыша в нее. Поговорим подробнее о том, как выиграть в "2048". Смысл этого способа заключается в том, чтобы при суммировании чисел использовать только три из четырех кнопок. Например "вниз", "вправо" и "влево", а кнопку "вверх" не нажимать. Тогда наибольшие числа находятся в одном углу поля, и их можно легко копить. У этой стратегии есть минус: рано или поздно придется нажать кнопку "вверх", и тогда плитки с крупными числами сдвинутся в сторону и на их место придут двойки или тройки. Если удастся их соединить и нейтрализовать, вам повезло, если же нет - придется начинать сначала. Он очень похож на предыдущий способ, разница в том, что используются не три, а две кнопки. Таким образом все крупные числа собираются в одном углу. Недостаток здесь тот же самый - все равно понадобится задействовать дополнительные кнопки. В этой стратегии можно повысить свои шансы, заблокировав движение крупных чисел. Для этого надо, чтобы ряд, где они копятся, был полностью заполнен плитками с разными крупными числами. Пожалуй, самый результативный и математически сложный способ. Нужно выстраивать числа таким образом, чтобы в самом дальнем углу находилось наибольшее число и они последовательно уменьшались. Тогда при появлении с противоположной стороны цифр 2 или 4 всегда можно будет объединить их с предыдущими, и так далее змейкой, пока в дальнем углу не соберется максимально большое число. Универсального способа выиграть в "2048" не существует. Есть несколько математических закономерностей, зная которые, легче будет продвинуться в игре, а дальше все зависит от ваших способностей и удачи. Огромный бюджет и сверхсовременная графика далеко не всегда являются залогом успешности игры. Напротив, существует немало популярных проектов, созданных в краткие сроки и при отсутствии серьезной финансовой базы. Примером такового может служить приложение-игра 2048, появившееся в 2014 году. Как пройти 2048 следуя простым и ясным правилам далее в статье. История игры 2048 довольно занятна — молодой итальянский программист на имя Габриэле Чирулли решил отвлечь себя от бытовой работы. Упражняясь с языком JavaScript, он потратил два дня на то, что бы создать простое и интересное развлечение. В качестве основы его детища были использованы принципы популярной игры «Threes». Результат произошел сам себя. Прохождение приложения 2048 получило огромную популярность всего лишь за несколько недель, а вопросом «Как пройти 2048?» стали задаваться не только юные игроки, но и те кто только начал своё знакомство с данной головоломкой. Более того — известность проекта достигла уровня своего «прародителя», а возможно и превысила его. Игровое поле состоит из квадрата 4х4. Каждый ход на одной из его клеток возникает новый куб с числом «2» или «4». Геймер может воздействовать с ними, направляя все фигуры в одном из направлений (вверх, вниз, влево или вправо). Играть 2048 онлайн: В случае если две равноценных фигуры сталкиваются друг с другом («2» и «2», «4» и «4», и т.д.) образовывается новый куб с удвоенным числом («4», «8», «16» и т.д.). Цель игры — создать фигуру с числом «2048». Так же, данное приложение 2048 предусматривает возможность проигрыша. Он наступает в той ситуации, когда игрок не может сделать новый ход (при полном заполнении игрового поля). Несмотря на свою кажущуюся простоту прохождения, игра не только затягивает, но и заставляет «напрячь извилины». Как пройти 2048 следуя инструкциям далее согласно секретам. Существует несколько секретов, которые могут в значительной мере упростить прохождение игры 2048.
Наконец — если ошибка все же была допущена (геймер случайно направил фигуры вверх, или образовал «проем в нижнем ряду») изучите сложившуюся ситуацию. В первые 5-7 минут игры подобные промахи можно исправить. Далее в 90 % случаев они превращаются в вердикт, гласящий о вашем поражении. В такой ситуации лучше не тратить время и начать все с нуля. Игра получилась на славу. Простой и понятный интерфейс, отсутствие лишних деталей и ее простота (геймеру достаточно 1-2 минут, что бы разобраться в геймплее) стали главными причинами огромной популярности данного проекта “2048”.Создаём в поле первые две ячейки
Реализуем пользовательский ввод
Интерфейсы для клавиатурного и графического модулей
Графический модуль
public interface GraphicsModule {
/**
* Отрисовывает переданное игровое поле
*
* @param field Игровое поле, которое необходимо отрисовать
*/
void draw(GameField field);
/**
* @return Возвращает true, если в окне нажат "крестик"
*/
boolean isCloseRequested();
/**
* Заключительные действия, на случай, если модулю нужно подчистить за собой.
*/
void destroy();
}
Клавиатурный модуль
public interface KeyboardHandleModule {
/**
* Считывание последних данных из стека событий, если можулю это необходимо
*/
void update();
/**
* @return Возвращает направление последней нажатой "стрелочки",
* либо AWAITING, если не было нажато ни одной
*/
ru.tproger.main.Direction lastDirectionKeyPressed();
/**
* @return Возвращает информацию о том, был ли нажат ESCAPE за последнюю итерацию
*/
boolean wasEscPressed();
}
Метод логики
Давай уже серьёзно. Как нам сдвинуть это чёртово поле?
Самое сердце программы. Метод shiftRow()
История появления игры
Суть игры
Как выиграть в 2048: схема
Список стратегий для победы в 2048
В заключение
знаете, и пора применить знания на практике. Скачивайте данную игру на свой телефон, чтобы она всегда была под рукой. Или же поиграйте в неё прямо сейчас на своем компьютере, ведь когда она получила свою популярность, множество разработчиков переделали её на свой лад. И теперь в неё можно поиграть на сотнях сайтов, с разными вариациями, начиная от кусочков пиццы, которые превращаются в другую еду, заканчивая различными актерами.Способ трех кнопок
Способ одного угла
Накопление по нарастающей
Геймплей
Как проходить 2048
Подбивая итоги