Анимация проблемы Башни Ханоя в C#
Следующий метод AnimateMovement перемещает диск по прямой линии из текущего местоположения в новый.
// Переместите движущийся диск в это место.
private void AnimateMovement(int end_x, int end_y)
{
int start_x = MovingDiskRect.X;
int start_y = MovingDiskRect.Y;
const int pixels_per_second = 400;
float dx = end_x - MovingDiskRect.X;
float dy = end_y - MovingDiskRect.Y;
float dist = (float)Math.Sqrt(dx * dx + dy * dy);
// Вычисление расстояния в секунду.
dx = pixels_per_second * dx / dist;
dy = pixels_per_second * dy / dist;
// Посмотрим, сколько времени займет общий ход.
float seconds = dist / pixels_per_second;
DateTime start_time = DateTime.Now;
// Начнем движение.
for (; ; )
{
// Перерисовать.
this.Refresh();
// Подождите немного.
System.Threading.Thread.Sleep(10);
// Посмотрим, сколько времени прошло.
TimeSpan elapsed = DateTime.Now - start_time;
if (elapsed.TotalSeconds > seconds) break;
// Обновляем позицию прямоугольника.
MovingDiskRect.X =
(int)(start_x + elapsed.TotalSeconds * dx);
MovingDiskRect.Y =
(int)(start_y + elapsed.TotalSeconds * dy);
}
MovingDiskRect.X = end_x;
MovingDiskRect.Y = end_y;
}
Код вычисляет количество пикселей в секунду, которое он должен добавить в координаты X и Y на диске. Затем он входит в цикл, где он добавляет необходимое количество пикселей, в зависимости от того, сколько времени прошло. Он останавливает 10 миллисекунд за каждый проход через цикл.
Следующий метод использует AnimateMovement для перемещения диска с одного привязки и на другой.
// Анимация перемещения диска из привязки from_peg в peg to_peg.
private void AnimateDiskMove(int from_peg, int to_peg)
{
// Удалите диск, чтобы Paint не рисовала его.
int disk_width = PegStack[from_peg].Pop();
// Переместите диск выше from_peg.
int y = PegLocation[from_peg].Bottom -
(PegStack[from_peg].Count + 1) * (DiskThickness + 2);
int x = PegLocation[from_peg].X + DiskThickness / 2 -
disk_width / 2;
MovingDiskRect = new Rectangle(
x, y, disk_width, DiskThickness);
// Переместите диск выше привязки.
int to_y = 10;
AnimateMovement(x, to_y);
// Переместите диск поверх нового привязки.
int to_x = PegLocation[to_peg].X + DiskThickness / 2 -
disk_width / 2;
AnimateMovement(to_x, to_y);
// Переместите диск вниз на привязку.
to_y = PegLocation[to_peg].Bottom -
(PegStack[to_peg].Count + 1) * (DiskThickness + 2);
AnimateMovement(to_x, to_y);
// Перерисовать.
this.Refresh();
// Добавить диск в новый привязку.
MovingDiskRect.X = -1;
PegStack[to_peg].Push(disk_width);
}
Этот метод удаляет верхний диск из исходного привязки и вычисляет его местоположение. Затем он вызывает AnimateMovement, чтобы переместить диск выше исходного кода.
Далее код использует AnimateMovement для перемещения диска по привязке адресата. Он заканчивается с помощью AnimateMovement снова, чтобы переместить диск вниз на привязку адресата.
