Реализуем пользовательский ввод. Тактика и стратегия

Попробуйте воспользоваться простейшей стратегией. Есть простой способ – двигайте плитки поочередно вверх и вправо до тех пор, пока у вас не будет выбора, кроме как сдвинуть их влево (то есть когда плитки не реагируют на ваши действия). Затем сдвиньте их влево и продолжайте следовать той же тактике вверх/вправо. Это не гарантирует вам победу – в действительности вообще маловероятно, что так вы сможете победить. Однако таким образом вы сможете заработать много очков. С этой тактики можете и начать.

  • Сосредоточьтесь на угле. Есть одна распространенная техника среди игроков – формирование плитки с наибольшим номером в каком-то определенном угле. Неважно, какой угол вы предпочтете, но как только угол выбран, необходимо его придерживаться.

    • После того как вы выбрали угол, убедитесь, что последний ряд (сверху или снизу, зависит от того, какой угол вы выбрали) всегда заполнен. Сдвигайте плитки вверх или вниз, соответственно, чтобы сформировать большее число.
    • Сдвигайте плитки по направлению к углу, чтобы получить большее число.
  • Используйте технику "Мансини" (довольно распространенная техника, но в одной статье она была названа этим именем). Она заключается в формировании цепей плиток, для того чтобы достичь большего числа в верхнем углу поля.

    • Начните с движения из стороны в сторону, перемещая плитки то влево, то вправо, пока у вас не закончатся варианты. В результате ваше поле будет состоять из двоек, четверок и восьмерок.
    • Когда поле будет заполнено, начните сталкивать числа по направлению к верхней части поля. Когда появится возможность – соедините плитки, чтобы получить большее число.
    • Когда вы больше не сможете двигать клетки вверх, снова перемещайте их влево и вправо. Продолжайте в том же духе, сфокусируйтесь на верхнем угле, в котором вы сформируете большее число.
    • Старайтесь формировать цепочки, чтобы получить большее число. Это тактика в особенности подходит для первого и второго ряда: старайтесь построить такую последовательность, чтобы в результате, используя движения влево/вправо и вверх, вы получили большее число.
    • Лучше соединять малые числа так, чтобы сформировать цепочку, чем стараться работать над увеличением числа на какой-то одной плитке. Тактика формирования цепи позволит вам продвинуться дальше, чем стратегия одной большой плитки.
    • Придерживайтесь системы: двигайте плитки из стороны в сторону, соединяя малые плитки вместе, затем сдвигайте их вверх, чтобы получить большее число, выберите свой "большой" угол.
  • Избегайте ситуации, когда плитка с большим числом оказывается посередине. Если вы нацелены на то, чтобы сформировать большее число в верхнем углу, делайте все что угодно, но не сдвигайте плитки вниз. Аналогично, если вы выбрали нижний угол, не сдвигайте плитки вверх. Если вы это сделаете, плитки с меньшим числом (2 или 4) вклинятся в ряд с "наибольшим числом", а это плохо.

    • Если у вас нет выбора, вы можете сдвинуть плитки в другую сторону (вверх или вниз), но старайтесь избегать такой ситуации. Если ничего другого не остается, постарайтесь сформировать последовательность из больших чисел в ряду с крупнейшей плиткой.
  • Игра "2048" появилась не так давно, но сразу завоевала популярность у множества игроков. Когда в первый раз запускаешь игру, сразу задаешься вопросом: "Как играть в 2048?" Об этом мы расскажем в данной статье.

    Несмотря на то, что не все сразу понимают, как играть в "2048", с каждым днем количество скачиваний данной игры становится все больше. И это не удивительно, в ней есть все, чтобы привлечь игрока: легкость в управлении, простой ненавязчивый дизайн, доступность и невероятная увлекательность. Не удивляйтесь, если ваш знакомый целый день играет в нее. Даже частые проигрыши не остановят вас на пути к долгожданной победе. А с какой гордостью вы будете говорить о своем триумфе друзьям!

    Как играть в "2048"?

    Создатель данной игры представляет вам поле, разделенное на 15 клеточек, после каждого хода на поле появляется цифра 2 или 4. Цель игры - это собрать на поле ячейку с цифрой 2048. Но что нужно делать, чтобы выиграть?

    Давайте представим, что в начале игры у нас на поле две заполненные ячейки, на каждой - цифра 2. Чтобы эти цифры сдвинуть, нужно нажать на кнопку по экрану вниз, вверх, влево или вправо. В зависимости от того, в какую сторону вы нажмете кнопку, туда и сдвинутся ячейки с цифрами. Если две ваши ячейки с номиналом 2 соприкоснутся и объединятся, то у вас получится одна ячейка с цифрой 4. Таким же образом соединяются и ячейки номиналом 4, образуя клетку с цифрой 8. Теперь вы видите, что ответ вопрос о том, как играть в "2048", не такой уж сложный.

    Если у вас получилось объединить ячейки так, чтобы получилась цифра 2048, - поздравляю, вы выиграли. А если на поле не осталось ни одной свободной клетки и невозможно объединить никакие из ячеек, то, к сожалению, вы проиграли.

    Пример игры

    Теперь давайте на примере посмотрим, как работает основное правило игры "2048". К примеру, у вас на поле есть две ячейки с цифрой 2, сначала необходимо сместить их, чтобы они находились рядом. А потом еще раз, чтобы они соединились, образовав цифру 4, далее необходимо создать еще одну ячейку 4, для этого проводим те же манипуляции, и теперь у нас есть две 4-ки. Соединим их и получим 8, потом аналогично собираем еще одну ячейку с числом 8, соединяем их. На самом деле все не так сложно.

    Где играть в "2048"?

    Разобравшись с основными правилами игры, вы задаетесь вопросом, а где же найти эту игру? Те, кто хочет играть в нее с телефона, смогут скачать игру, зайдя на Play Market системы Android. Игру для телефона также можно скачать, сидя за компьютером в интернете, и, скинув на телефон, установить. Но если вы хотите играть на компьютере, не обязательно, чтобы она была установлена, игра "2048" онлайн тоже доступна всем желающим.

    Стратегия и тактика игры

    Стоит отметить, что данная игра - для людей, которые любят ребусы и головоломки, а также имеют аналитический Вот несколько советов, с которыми вам будет легче пройти всю игру до конца.

    • Изучите основное правило игры. Что имеется в виду? Сыграйте в "2048" много раз, пока не поймете до конца, как перемещаются ячейки с цифрами, как они складываются, пока не начнете продумывать действия на несколько ходов вперед.
    • Не спешите. В данной игре важно продумывать каждый ход, прежде чем его совершать, не стоит передвигать ячейки в беспорядке туда-сюда.
    • Просчитывайте ходы. Этот момент нужно обязательно занести в правила игры "2048", поскольку, если его не соблюдать, вероятность выигрыша ничтожно мала.
    • В одно движение необходимо соединять как можно больше ячеек. Интересно то, что в одно движение вы можете соединить даже три цифры. Это позволит вам быстро расчистить поле и собрать больше крупных цифр.
    • Обращайте больше внимания на маленькие цифры. Вы допустите большую ошибку, если будете собирать много крупных цифр, при этом не следя за маленькими.

    Маленькие хитрости игры

    Как вы видите, правила довольно просты. Кажется, что все легко, и вы запросто выиграете, но, думая так, вы обманываете себя. Недостаточно просто знать правила, надо еще изучить секрет игры "2048" в мелочах. И мы расскажем вам те самые мелочи, которые приведут вас к победе.

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

    Те, кто играл в "2048", знает, что не всегда получает держаться одного угла. И случаются ситуации, когда нет другого выхода, и приходится выводить свою самую большую ячейку на середину поля. Если это случилось и с вами, сделайте что нужно, но следующим же ходом возвращайтесь в свой угол.

    Игра "2048" - это увлекательное приложение, которое поможет вам скоротать время и развить свою логику. Игра имеет несколько основных несложных правил, приятное оформление. Несмотря на то, что это просто игра-головоломка, она имеет определенную пользу. Не стоит сразу унывать, как только вы проиграете, Теперь вы не только знаете, как играть в "2048", но и обладаете ценными знаниями, которые помогут вам почувствовать вкус победы. Запасайтесь терпением и с удовольствием играйте!

  • Библиотека LWJGL (версии 2.x.x) для работы с графикой (опционально). Обратите внимание, что для LWJGL версий выше 3 потребуется написать код, отличающийся от того, что приведён в статье;
  • Спрайты, т.е. картинки плиток всех возможных состояний (пустая, и со степенями двойки до 2048). Можно нарисовать самому, или скачать использовавшиеся при написании статьи .
  • 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 .

    Интерфейсы же, после добавления в них всех упомянутых выше методов, будут выглядеть следующим образом:

    Графический модуль

    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(); }

    Метод логики

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

    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).

    Самое сердце программы. Метод shiftRow()

    Если подумать, то вам предстоит решить задачку - как за наименьшее (линейно зависящее от количества поступающих данных) время произвести с рядом чисел следующие последовательные операции: (1) если в ряде есть нули, их необходимо удалить, (2) если любые два соседних числа равны, то вместо них должно остаться одно число, равное сумме двух равных чисел. И (3) - если число получено через пункт (2), оно не может совмещаться с другими числами.

    Если представить себе алгоритм таким образом, то придумать линейное решение будет гораздо легче. Вот какой алгоритм должен получиться:

    • Выкидываем все нули - проходимся по всему массиву и копируем элемент в новый массив, только если он не равен нулю. Если вы попробуете удалять эти нули из середины того же массива, алгоритм будет работать за O(n^2).
    • Рассмотрим (поставим указатель на) первое число получившегося массива без нулей .
      1. Если с ним можно совместить следующее за ним число (наш указатель +1), то переписываем в новый массив лишь их сумму, затем ставим указатель на третье число (второго уже нет).
      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», создал итальянский разработчик Gabriele Cirulli.

    Игровое поле, состоит из сетки 4х4.
    Игра начинается. На сцене две плитки с номиналом 2.
    Передвигая, нужно сложить плитки одного «номинала».
    Движение, возможно в 4 стороны.

    Цель игры, собрать плитку с «номиналом» 2048.

    В ответ на цитату разработчика:

    That screenshot is fake, by the way. I never reached 2048.

    Игру пройти очень просто.

    Эту группу, нужно расположить линейно.
    Проще всего, расположить систему по горизонтали на нижней платформе, при этом, следует, исключить движение вверх.
    Таким образом, сумма продвигается по стеку, справа налево, в «центральный банк», через сеть «малых».

    Используя данную стратегию, шанс проиграть крайне мал.
    Стратегию в действии, можно увидеть на видео.


    К слову, к моменту публикации статьи, мне удалось набрать 131072 в одной плитке.
    Зафиксировал это на видео:

    Прикинул, что максимально возможная плитка в игре, может иметь значение 524288, т.е. мой рекорд побить дважды.

    Спасибо, за внимание!

    Итак, алгоритм простой. Вам нужно собирать максимальное число в левом нижнем углу. При этом нельзя двигать кубики вверх! Иначе есть риск появления там маленьких цифр, которые вы не сможете сложить в большие, и они будут у вас просто занимать место. То есть, у вас будут выстраиваться, например, 1024, 512, 256,128. И, таким образом, вы в течении некоторого времени сложите заветный кубик 2048.Нужно внимательно следить за тем, чтобы в нижнем ряду (особенно в левом углу) не появлялось кубиков 2,4,8 и т. д. Иначе вам будет очень сложно собрать из них большие цифры. Это может помешать вам в достижении победы. Вот скрин: .

    Также вы можете использовать такие стратегии:

    Стратегии 2048

    Для того чтобы выиграть в эту игру за меньшее количество ходов (да и вообще, чтобы просто выиграть ее), подумайте над стратегией. От того, как вы начнете игру, зависит многое и основные действия лучше продумать еще в самом начале.

    1)Стратегия «Змейка»

    Это самая простая стратегия – нужно просто последовательно жать четыре кнопки управления. Например, «Вверх», «Вправо», «Вниз», «Влево», повторить. Эта стратегия почти не требует усилий, и таким образом можно набрать около 512 очков, но скорее всего, в заполненном поле вы уже не сможете сделать никаких действий. Можно начать с этой стратегии, чтобы познакомиться с игрой и понять механизм действия, но для победы она не особо эффективна.

    2)Стратегия 3ех кнопок (стратегия одного столбца)

    Эта стратегия сложнее, но и более результативная. При сдвигании плиток нужно пользоваться только тремя кнопками управления. То есть, например, вы пользуетесь только кнопками «Вверх», «Вправо» и «Влево», а кнопку «Вниз» не нажимаете вообще. Таким образом, плитки суммируются с одной стороны поля и их легче «копить», но у этой стратегии есть и недостаток – при достижении определенной планки, приходится использовать 4ую кнопку, и ячейки с большим номиналом неизбежно сдвигаются в сторону. Там, где они раньше находились, появляются новые двойки или четверки, которые сложно объединить с большими числами, которые стоят рядом. Если вам повезет – хорошо, нет – придется начать все заново.

    3) Стратегия одного угла

    Эта стратегия похожа на предыдущую, но она подразумевает использование двух игровых кнопок – так, чтобы большие цифры копились в углу. Для этого нужно выбрать угол, например, левый нижний и в нем копить ячейки, нажимая преимущественно «Влево» и «Вниз», но, опять же, в определенный момент потребуется сдвинуть ячейки в другую сторону – влево или вверх. Для того чтобы большие цифры не меняли положения, лучше, чтобы ряд, в котором они находятся, был полностью заполнен (и по вертикали и по горизонтали) разными значениями (чтобы они не слились в одно).

    4)Стратегия одного столбца с приоритетом

    Основа этой стратегии такая же, как и у второй. Вы копите большие значения в одной стороне (например, внизу), и тогда вы вообще не используете кнопку «Вверх». При этом при использовании оставшихся трех кнопок, вы держите в приоритете движения в сторону того самого столбца с большими значениями. Если это нижняя строка, то значит в ситуации, когда есть возможность объединить ячейки в нескольких местах, вы всегда сдвигаете их вниз, а не вправо или влево.

    5)Стратегия накопления по нарастающей (как я выше писал)

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