Тайна девятой планеты. Молодой да ранний

2048 — это игра, где отлично воссоединились традиционный тетрис и пятнашки. После запуска игры все начинают задаваться вопросом: “Как играть 2048”, для ознакомления с правилами и победной стратегией читайте далее.

Габриэль Черулли, создатель игры, предлагает игрокам поле с 16 клеточками, на котором с каждым ходом появляется цифра два. Суть заключается в том, что нужно объединять квадратики с одинаковыми значениями до тех пор, пока не получиться цифра 2048.

Правила игры в 2048

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

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

Рассмотрим на примере основное правило. Так, допустим, у вас два кирпичика «2», сместите их так, чтобы они находились рядом и повторите процедуру, пока у вас не получиться цифра «4». Получилось? Дальше необходимо действовать тем же способом и теперь уже собирать клеточку «8» из двух «4». Для того чтобы играть 2048 на компьютере достаточно лишь спуститься ниже.

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

Тактика и стратегия

На то, чтобы пройти всю игру 2048 необходимо потратить всего лишь 20 — 25 минут, при условии, конечно, что не будет допущено страшных и непоправимых ошибок при прохождении, а для этого мы рассмотрим тактику и несколько стратегий.

Следует сразу отметить, что игра предназначена для тех, кто имеет аналитический склад ума и обожает ребусы и головоломки. Логика — понятие, без которого играть в 2048 не возможно, но мы все же дадим несколько советов, согласно которым вы сможете пройти ее от начала и до конца.

  • 1.Изучите свои возможности. А именно речь идет о том, чтобы потратить несколько десятков попыток на то, чтобы поиграть в 2048 и понять, как складываются клеточки, как они перемещаются и прочее.
  • 2.Не спешите. Да, звучит банально, но именно здесь, в этой игре очень важно не метать клеточки из стороны в сторону, а думать, что принесет та или иная комбинация;
  • 3.Просчитывайте ходы наперед. Даже один непродуманный ход, может испортить самую хорошую игру. И причина будет состоять в том, что игрок просто не увидел, например, что нажатие стрелки влево, загонит фигуру с большим номиналом в угол без возможности вытянуть ее оттуда.
  • 4.Соединяйте максимально большое количество клеточек. Примечательным в данной игре является то, что вы можете объединить сразу три цифры в одно число за один ход. Таким образом, вам удастся максимально быстро расчищать поле, образовывая новые, крупные номера.
  • 5.Сосредоточьтесь на клеточках с маленькими числами. Ошибка многих — это сложить как можно больше клеточек с большими цифрами, объединяя маленькие только в процессе. Здесь нужно поменять тактику и заняться теми самыми «крохами» а крупные кирпичи вы всегда успеете удвоить в размере.

Играть 2048 онлайн:

Секреты и хитрости

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

  • Забудьте про стрелочку «вверх» нигде и ни при каких обстоятельствах не нажимайте ее;
  • Постарайтесь сосредоточить все крупные цифры в одном углу;
  • Играйте на нижнем поле, в котором вы не должны допускать пробелов.

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

. Многое из представленного в них является своеобразной классикой развивающих игр, но и за новинками мы стараемся следить. Поэтому сегодня предлагаем вам поиграть в уже известную во всём мире, и приобретающую ещё большую популярность с каждым днём онлайн игру – 2048 .

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

История создания

Это не совсем сравнимо, но и как множество других открытий и изобретений в области компьютерного ПО, 2048 была разработана не с целью создания успешного коммерческого проекта. Её автор, молодой итальянский программист и веб-разработчик Габриэле Чирулли, решил с пользой провести выходные и попробовать свои силы в написании программ на JavaScript. За основу он взял идею нескольких других цифровых головоломок (в частности Threesи 1024). К концу выходных, а именно 9 марта 2014 г. Г. Чирулли посредством Твиттера поделился ссылкой на своё творение, которое загрузил на Github, с друзьями. Дальше произошло то, что могло произойти только в информационную эпоху – меньше, чем за неделю в 2048 сыграло больше 4 млн. людей. 19-летний разработчик был поражён успехом игры, но зарабатывать на ней деньги не собирался. В интервью он честно говорил, что идея приложения не была оригинальной, он сделал лишь модификацию. Несмотря на это, 2048 по популярности значительно опережала аналогичные игры, вышедшие раньше, а после того, как появилась возможность скачать версии для Androidи iOS, спустя 2 месяца после первого релиза, о ней, без преувеличений, заговорил весь мир. Не последнюю роль здесь, конечно же, сыграл тот факт, что приложение распространялось бесплатно. Даже такие издания как «Times», «Wall Street Journal» и «Business Insider» вышли с положительными отзывами о данной компьютерной игре.

Любите подобные загадки, игры, головоломки и тесты? Получите ко всем интерактивным материалам на сайте, чтобы развиваться эффективнее.

Помимо оригинального варианта 2048 со временем появилось достаточно много дополнений и даже разновидностей игры, ведь она распространяется с открытым исходным кодом. Так, во многих версиях появились списки лидеров, управление было адаптировано для сенсорных экранов. Было выпущено несколько модификаций, где вместо стандартной плитки с числами использовались фигуры из Тетриса, изображения персонажей сериала «Доктор Кто» и т.д. Созданы даже отдельные сайты-конструкторы, где любой желающий может использовать в качестве плитки всё, что угодно. Так, студенты одного вуза создали версию с фотографиями своих преподавателей, где плитке с номиналом «2» соответствовало фото методистки, а «2048» – декана факультета.

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

Описание и правила игры

Игровое поле для 2048 представляет собой квадрат 4×4 (многие российские пользователи сразу углядели в этом общий момент с другой давно популярной у нас игрой «пятнашки»), на котором в стартовой позиции две плитки (иногда – тайлы, от английского «tile» – «плитка») уже открыты. Они могут располагаться как угодно, варианты начальной расстановки – «2» и «2», «2» и «4», «4» и «4» (реже всего). «Костяшки» можно перемещать в одну из четырёх сторон (если этому не мешает расположение), при этом, когда две плитки одинакового номинала сталкиваются друг с другом, то стают одним тайлом, значение которого удваивается. За один ход плитка может складываться в разных местах игрового поля, но лишь один раз увеличивать свой номинал. Другими словами, если подряд расположены «2», «2» и «4», то за ход можно объединить только «2» и «2» в «4», а получившуюся «4» с блоком такого же значения – лишь во время следующего хода.

Особенностью 2048 является то, что движется всё игровое поле до границы, а не отдельные столбцы или строчки. После каждого такого хода на случайной пустой клетке появляется новая плитка номинала «2» (с вероятностью 90%) или «4» (с вероятностью 10%). Игра считается проигранной, если у вас не осталось ходов (все клетки заполнены «костяшками», возможностей их объединить нет). Для победы в изначальной версии игры нужно было собрать тайл номиналом «2048» (откуда собственно и название). Позже алгоритм был несколько изменён, что позволило продолжать игру до получения максимально возможного значения плитки – 2 17 .

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

В старой версии помимо функции перезапуска игры с начала, была также функция UNDO– отмены сделанных ходов, но на момент написания статьи разработчик её убрал.

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

2 способа как победить в 2048

2048 – простая цифровая головоломка. Но это лишь на первый взгляд. Сама суть действительно такова – что может быть проще, чем складывать плитки меньшего достояния с целью получить в конце нужную плитку большего номинала? В этом был уверен и сам Г. Чирулли, придумавший концепцию. Правда, 11 марта (спустя 2 дня после представления игры как готового продукта) он в социальной сети сообщил, что потратил 16 часов на игру, а добиться нужного результата так ни разу и не смог.

В этом же убедились и многие другие, кто хотя бы пару раз пробовал сыграть. Стало очевидно, что без определённой тактики выиграть невозможно. Некоторое время спустя, которое понадобилось фанатам и другим заинтересованным на то, чтобы провести и проверить их на практике, появилось пару выигрышных стратегий. С существенной поправкой на то, что 100% действующей методики, как набора готовых решений, следуя которым можно набрать заветные «2048», нет. Они задают лишь верный алгоритм, но многое остаётся зависимым от совершаемых игроком действий, а порой и игровой раскладки.

Стратегия «змейка»

Стратегия «змейка» получила своё название на русскоязычных форумах от принципа одноименной старой игры. Её суть в расположении подряд блоков с ниспадающим номиналом (512-256-128-64). Разберёмся более подробно.

Первое что следует сделать – определиться с рабочей областью, тем участком игрового поля, где вы собственно и будете собирать «2048». Им может быть любой из углов. На рисунке выше показан вариант с расположением плитки наибольшего значения в левом нижнем углу. Его и возьмём за отправную точку. Суть всего метода в том, чтобы исключить одно из направлений движения. В нашем случае это «вверх». В этом нет никакого скрытого сакрального смысла, просто, если вы поднимете все блоки вверх (особенно на поздних этапах игры, когда большая часть поля уже занята тайлами), на месте в углу с высокой долей вероятности может возникнуть «2» или «4». Это сломает стратегию, ведь «костяшку» такого значения очень тяжело будет собрать, особенно если она окружена плитками достояния 64 и больше. В противном же случае, собирая именно в угловой клетке наибольшее число, вероятность победы равняется 80%. Остальные блоки нужно стараться собирать в этой же строке по принципу уменьшения их номинала (как показано на рисунке). Это позволит вам, используя большую часть игрового поля, собирать нужные плитки и поочерёдно их соединять, что очень удобно.

Для визуального представления о том, как реализовать эту стратегию – смотрите видео. Помните, с первого раза не получается практически ни у кого.

Стратегия приоритетного столбца

Простой способ, описанный на Хабрахабре . Суть примерно та же, что и в «змейке», но реализация другая. Условно делим игровое поле на 4 столбца (на картинке показано слева направо, но можно так, как удобно вам), нумеруем их – крайний левый – первый, крайний правый – четвертый. При сложении плиток следуем принципу: блоки с наибольшим значением должны быть в первом столбце, во втором числа меньше, чем в первом, в третьем меньше, чем во втором и т.д. Наибольшими тайлами мы заполняем весь первый столбец. Как и в случае с предыдущей методикой, двигать его нельзя (что касается нашего примера, это движение «вправо»). На основе этого строится стратегия игры – выбирать стоит тот ход, который увеличивает номинал первых столбцов. Существенный нюанс – следует так планировать игру, чтоб новое появившееся число не стало четвертым в столбце, без возможности его соединить, и не привело к ситуации, когда другого выхода кроме движения «вправо» не останется.

Как это выглядит на практике:

Рекорды

Плитка со значением «2048» означает, что вы победили, но игру после этого можно продолжить. Максимально возможный номинал блока – 131 072 (или 2 17). Кроме того, много игроков, следуя зову заложенной в человеческой природе жажде к достижениям, соревнуются в наборе наибольшего количества очков. Максимальный результат, который можно набрать – 3 932 100, но это идеальный случай, а так – каждая новая «4» уменьшает эту сумму на 4. В Интернете встречается много видеозаписей и снимков экрана с запечатлёнными на них рекордными счетами. Но сказать, не использовался ли для их достижения скрипт для автоматического прохождения игры, сложно.

"2048": как выиграть?



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

Игра "2048" быстро стала очень популярной, и появились стратегии выигрыша в нее. Поговорим подробнее о том, как выиграть в "2048".

Способ трех кнопок

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

У этой стратегии есть минус: рано или поздно придется нажать кнопку "вверх", и тогда плитки с крупными числами сдвинутся в сторону и на их место придут двойки или тройки. Если удастся их соединить и нейтрализовать, вам повезло, если же нет - придется начинать сначала.

Способ одного угла

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

Накопление по нарастающей

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

Универсального способа выиграть в "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++; } } }

    За последние 100 лет астрономы добились грандиозных успехов в изучении космоса. Отыскали пульсары, нейтронные звезды, даже обнаружили планеты за пределами Млечного Пути!

    Но вот парадокс: то, что у нас под боком, зачастую является тайной за семью печатями. Речь идет о Плутоне - небесном теле, обнаруженном более 80 лет назад. Астрономы знают о нем ничтожно мало и называют самым странным и загадочным во всей Солнечной системе.


    История открытия Плутона - одна из самых непростых. Впервые о существовании девятой планеты заговорил выдающийся американский астроном Персивал Лоуэлл. В 1905 году он выступил с сенсационным заявлением: в Солнечной системе не восемь, а девять планет! Заявление прогремело как гром среди ясного неба. Ученые требовали доказательств.

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

    «Девятая планета, - распалялся Лоуэлл,- находится на расстоянии около шести миллиардов километров от Солнца, и ей требуется 282 года для полного Оборота вокруг Солнца». Коллеги внимательно выслушали первооткрывателя, но предоставленных доказательств им показалось недостаточно. Однако Лоуэллу больше крыть было нечем.

    ЕСТЬ ИДЕЯ!

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

    Как же выделить ее из бескрайнего моря звезд? В обсерватории города Флагстафф, что в Аризоне, ночью он навел фотографический телескоп на группу звезд, среди которых должна была находиться планета икс. Астроном зафиксировал время - камере требовалось три часа, чтобы собрать звездный свет.

    Утром Персивал проявил пластинку и отложил в сторону. Дальше - по той же схеме. Ночью снова установил телескоп, навел камеру и стал фотографировать небо в течение тех же трех часов. На следующий день наступил ответственный момент. Лоуэлл проявил вторую пластинку и наложил ее на первую так, чтобы все звезды точно совпали. Затем вооружился лупой и склонился над пластинками. По его прогнозам, если две звездочки не сойдутся, значит, он напал на след планеты икс.

    Час за часом Лоуэлл изучал пластинки и вдруг увидел две несовпадающие точки. От волнения его затрясло. Он еле дождался ночи, чтобы теперь уже прицельно сфотографировать этот участок неба. Утром проявил снимок - расхождение налицо. Казалось, можно трубить победу. Но что-то подсказывало Лоуэллу, что «несовпадающее» небесное тело двигается слишком проворно. Интуиция не подвела: это был астероид!

    ПРОЦЕСС ЗАТЯНУЛСЯ

    Лоуэллу предстояло пережить еще немало разочарований, но он не сдавался. Каждую ночь поднимался в башню обсерватории, наводил телескоп и фотографировал небо, а утром проявлял снимки. Астроном обнаружил сотни астероидов - только не планету икс. Сутки складывались в недели, недели - в месяцы, месяцы - в года... Другой на его месте уже давно забросил бы эту, казалось, безнадежную затею, но Лоуэлл был не из таких.

    За несколько лет он сильно сдал - похудел, осунулся, стал нервным, раздражительным. Но не бросал начатое дело! В те редкие моменты, когда Персивал был в отъезде, за поиски брались его помощники. Прежде чем уехать, шеф инструктировал их: как только посчастливится отыскать планету икс, НЕМЕДЛЕННО телеграфировать ему! Увы - помощникам тоже упорно не везло. Это не мешало Лоуэллу шутить на эту тему: «Я докладываю в академии о своей работе 13 января. Было бы большой любезностью с вашей стороны сообщить об открытии как раз к этому времени».



    Лоуэлл был уверен: рано или поздно ему улыбнется удача. Но организм не выдержал многолетнего напряжения. 12 ноября 1916 года Персивал скоропостижно скончался от апоплексического удара. Его похоронили в его любимом месте - в городе Флагстафф на холме Марс-Хилл, там, где он провел много часов, выискивая в звездном небе заветную планету.

    МОЛОДОЙ ДА РАННИЙ

    В 1929 году в обсерватории, где работал Лоуэлл, появился молодой многообещающий астроном Клайд Томбо. В его распоряжении весьма кстати оказался новый мощный телескоп. Клайд действовал по тому же принципу, что и Лоуэлл. С помощью усовершенствованной техники фотографировал тот участок неба, где могла притаиться планета икс, проявлял, сравнивал пластинки - и так до бесконечности... Но фортуна была более милостива к Клайду: через год, а именно 13 марта 1930 года, он объявил об открытии новой планеты.

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

    КРЕПКИЙ КАМЕШЕК

    И тем не менее Лоуэлл немного просчитался. Небесное тело оборачивалось вокруг Солнца не за 282 года, а за 248 лет. Потом последовали другие, менее приятные открытия! Ученые стали сомневаться: а является ли вообще Плутон планетой? Светит он что-то слишком тускло - это раз, у него отсутствует различимый планетный диск - два, обладает слишком малой для планеты массой - три.

    В 1978 году, когда открыли спутник Плутона-Харон (позже его отнесли к разряду двойных планет), его снова «перевзвесили». И опять неожиданность - масса Плутона оказалась ничтожно малой - примерно 0,2% от массы Земли. Маловато для того, чтобы носить гордое имя планеты! Поводов для беспокойства добавил в 1989 году космический аппарат «Вояджер-2».

    Полученные с него данные и вовсе вызвали замешательство в стройных рядах ученых. По размерам Плутон сравним с Луной, только весит в шесть раз меньше! А потом и вовсе случился конфуз. Некоторые астрономы без тени смущения заявили: лоуэлловской планеты не существует, Томбо открыл... астероид. Что тут началось! Ученые чуть не передрались. И только 24 августа 2006 года сошлись во мнении:
    Плутон - не обычная, а карликовая планета.

    ИЗ БЛЕСКА В ТЕНЬ

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



    До недавних пор считалось, что наименьшей плотностью в Солнечной системе обладает Сатурн. Теперь уже в этом ученые не уверены, ведь Плутон состоит из рыхлых льдов, образованных замерзшими летучими веществами. Но больше всего ученых волнует другое - странный блеск Плутона, вернее, почти полное его отсутствие. За последние 10 лет планета приблизилась к Солнцу и Земле, а значит, освещаться должна как минимум в полтора раза больше.

    Но Плутон стал светить слабее! Как такое может быть? Ученые разводят руками и лишь высказывают догадки. Может, он повернулся к нам более темной стороной? Льды на его поверхности по каким-то неведомым причинам испаряются? Плутон подвергся бомбардировке метеорита и тот поднял жуткий столб пыли?

    А пока серьезные ученые пожимают плечами, альтернативная наука предлагает свою версию. Якобы Плутон - это перевалочная база, а заодно своеобразная лаборатория инопланетян. Долгое время они преспокойно совершали оттуда свои полеты к Земле, не боясь быть замеченными. Но когда Плутон стали пристально изучать, постарались в буквальном смысле слова напустить тумана.

    Так это или нет? Все прояснится в скором будущем. В 2015 году к Плутону вплотную подойдет отправленный НАСА космический аппарат «Новые горизонты», и тогда загадочная планета откроет многие свои тайны.

    Андрей ПАЛЬКО, кандидат физико-математических наук