Вообще‑то я не особый любитель игр. Но прочитал тут на любимом Хабре про Кужлёвку и захотелось в это дело поиграть. Не буду утомлять описанием игры, скажу только что игра на мой взгляд исключительно достойная, хотя и не без серьёзных (опять‑таки на мой дилетантский взгляд) недостатков. Перехожу к делу. Первый (и пока единственный) затык у меня случился в эпизоде, где Михалычу нужно собрать Серп и Молот из плиток типа пятнашек. Помучившись с этим часа полтора, я понял, что не смогу этого сделать даже за миллион. Хотя может конечно я просто тупой как пробка. Но на берегу спасённый мной мечехвост ждёт сигаретку! Не могу же я бросить древнее живое существо одно, да ещё без курева! Так что пойдём добывать сигареты! Первым делом сделаем скриншот игры с головоломкой, загрузим его в графический редактор (я использую gimp) и перенумеруем в нём все плитки числами от 0 до 7. Числом 8 занумеруем пустую плитку (дырку): Попробуем теперь решить задачу в том же графическом редакторе, с помощью вырезаний и вставок. У меня хоть криво и косо, но получилось вот так: Забудем теперь про картинки и будем смотреть только на номера плиток. Тогда задача сформулируется так: Есть таблица размером 3x3, в которой записаны числа от 0 до 8. Каждым ходом разрешается менять позиции числа 8 и одного из его соседей по горизонтали или вертикали. Требуется найти последовательность ходов, преобразующих таблицу 0 1 2 3 4         5 6 7 8 в таблицу                       1                   0                   4                       6                   3                   5                       2                   7                   8 Поможет нам в этом волновой алгоритм. Волновой алгоритм это алгоритм поиска пути в лабиринте, моделирующий распространение волны в некоей среде в соответствии с принципом Гюйгенса — каждая точка волнового фронта является независимым источником волны. Среда тут может обладать самыми разнообразными свойствами. Содержать препятствия, давать штрафы или поощрения на некоторые пути и т. п. Алгоритм хоть и не очень знаком начинающим, однако применяется повсюду, где грубо говоря требуется попасть из точки А в точку В (либо определить, что такой путь невозможен). От трассировки топологии чипов, до известной офисной игры Lines.  Забудем теперь и про таблицы. Вместо таблиц будем использовать массивы целых, в которых элементы таблицы записаны слева направо, сверху вниз. Например исходная таблица представляется массивом {0, 1, 2, 3, 4, 5, 6, 7, 8}, а целевая — {1, 0, 4, 6, 3, 5, 2, 7, 8}. Среда в которой распространяется наша волна и представляет собой множество таких массивов. Точнее не совсем так. Алгоритм завершится успехом (он может завершиться и не успешно!), когда мы достигнем целевой точки — массива {1, 0, 4, 6, 3, 5, 2, 7, 8}. Но нас интересует не сам факт успеха, а путь от начального массива к целевому. Значит вместе с массивом изображающим таблицу, среда должна хранить ещё и ссылку на предыдущий узел (из которого волна пришла в данную точку). Для самого первого узла (содержащего начальный массив) эта ссылка очевидно будет пустой. Таким образом двигаясь от целевого узла по предыдущим, мы вытащим задом наперед весь путь. Ну и раз уж узел среды более сложен чем просто массив целых, в нём можно заодно хранить и ещё что‑то полезное. Будем там заодно хранить номер передвигаемой плитки (т. е. число, которое при переходе от предыдущего, меняется позициями с восьмёркой). Напишем класс (будем всё писать на java), представляющий узел среды: В словесном описании алгоритм выглядит примерно так: Создаем первый узел среды, значение которого установим в {0, 1, 2, 3, 4, 5, 6, 7, 8}, и помещаем его в волновой фронт и список узлов. Обновляем волновой фронт. Для этого создаем новый изначально пустой волновой фронт, а затем для каждого элемента старого: Получаем позицию восьмерки и список её соседей. Для каждого соседа восьмерки создаем новый массив, в котором этот сосед и восьмерка меняются местами. Если такой массив уже был, ничего не делаем. Если этот массив ещё не встречался, создаем новый узел, с этим массивом в качестве значения. В качестве предыдущего указываем узел из старого волнового фронта. И в качестве активной плитки - число, с которым восьмерка менялась местами. Включаем этот узел в список узлов и новый волновой фронт. Проверяем, не является ли полученный массив целевым. Если да, то успешное завершение. Если новый волновой фронт пуст, не успешное завершение. Если не пуст, переходим к пункту 2. Ниже приведена программа на java полностью решающая задачу. Не пинайте ногами, если коряво получилось, писал её по-быстрому. Кроме собственно волнового алгоритма, она ещё выводит картинки, показывающие ходы, и возникающие при этом позиции. Манипуляции с картинками довольно просты, и я их здесь не рассматриваю. Для рисования картинок ей нужен файл puzzle.png. Чтобы получить его, просто сохраните под этим именем  первую картинку в статье.  Текст программы:  Ну и наконец картинка решения. Позиции тут следуют слева направо сверху вниз. Первая в левом верхнем углу, последняя — в правом нижнем. В каждой позиции подсвечена плитка, которую нужно передвинуть.  А вот так прикольно это выглядит на анимации: Всего 20 ходов и откроется портал к товарищу Сталину. У него мы сигаретами и разживемся! Программист, в основном железячник