Qwertiy » 20.09.2012 (Чт) 21:46
Игра на поле n строк, m столбцов. Сначала без кнопок, просто логика.
Есть числа i in 0 to n*m-1. Лишнее значение n*m-1 будем рассматривать как пустую клетку. Для каждого числа есть его текущие координаты (x[i], y[i]). Ход - это своп пустой клетки и соседней с ней клетки с числом.
Обозначим last = n*m-1
Будем хранить массивы:
x(0 to last), y(0 to last) - координаты числа i
index(0 to n-1, 0 to m-1) - число, находящееся в позиции (i,j)
Будем рассматривать ход, именно как перемещение путой клетки.
Пусть (dx,dy) - вектор перемещения пустой клетки (в пределах поля), тогда
i = index(x(last)+dx, y(last)+dy) - клетка, с которой происходит обмен
причём x(i)==x(last)+dx and y(i)==y(last)+dy
соответственно, обмен примет вид x(i)-=dx, y(i)-=dy, x(last)+=dx, y(last)+=dy, index(x(i),y(i))=i, index(x(last),y(last))=last
После каждого хода необходимо проверить, не завершилась ли игра, т. е. верно ли, что ForAll i : i = x(i)*m + y(i).
Для того, чтобы сгенерировать поле, для которого решение существует (а оно сущестует не для любой перестановки чисел), поступим следующим образом.
Сначала расположим числа в заключительном состоянии. Затем сделаем некоторое количество рандомных ходов. Желательно при перемешивании гарантировать, что следующий ход не будет движением в направлении, противоположном предыдущему - это значительно улучшает качество перемешивания.
Теперь про реализацию с кнопками.
На каждой кнопке написано число - её индекс, увеличенный на 1 (чтобы отображались числа 1 to n*m-1, а не 0 to n*m-2).
По индексу из массивов x и y можно получить координаты на поле, которые можно преобразовать в координаты формы (для этого можно сделать функцию, а вызов Scale значительно её упростит). При нажатии кнопки надо проверить существующие соседние клетки поля на наличие дырки (по массиву index), после чего выполнить ход и обновить координаты кнопки.
Замечу, что не следует отображать последовательность ходов, перемешивающих поле. Их надо выполнить "тихо", а потом показать перемешанное поле.
Надеюсь, нигде ошибок не насажал сейчас.