Анимация проблемы Башни Ханоя в 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 снова, чтобы переместить диск вниз на привязку адресата.