Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.62/29: Рейтинг темы: голосов - 29, средняя оценка - 4.62
place status here
 Аватар для gunslinger
3186 / 2220 / 640
Регистрация: 20.07.2013
Сообщений: 6,013

Ханойские башни

13.05.2016, 04:24. Показов 5846. Ответов 5
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Стандартная задача с тремя стержнями (простое рекурсивное решение взято с википедии) плюс "визуализация".
Можно задавать количество колец и длительность "кадра анимации".
Играть самому нельзя, доступно только наблюдение.
h и dfm файлы не выкладываю.
ехе во вложении.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
const start_peg = 1, destination_peg = 3, buffer_peg = 2, plate_quantity_max = 15, rod_count = 3, color_count = 15;
TColor color[color_count] = {clRed, clYellow, clGreen, clBlue, clFuchsia, clOlive, clLime, clAqua, clMaroon, clPurple, clTeal, clNavy, clMoneyGreen, clSkyBlue, clGray};
int plates[rod_count][plate_quantity_max+1] = {0}, moves, pause = 250, plate_quantity = 10;
bool go = 0;
//---------------------------------------------------------------------------
TShape *TForm1::static_cast_Shape (String ShapeName, int num)
{
  return static_cast<TShape*>(FindComponent(ShapeName + String(num)));
}
//---------------------------------------------------------------------------
void TForm1::hanoi_init()
{
  for (int i = 0; i <= plate_quantity; i++)
    for (int j = 0; j < rod_count; j++)
      plates[j][i] = 0;
 
  for (int i = 1; i <= plate_quantity; i++)
  {
    TShape *Shape = new TShape(Form1);
    Shape->Parent = Form1;
    Shape->Name = "Shape" + String(i);
    Shape->Shape = stRoundRect;
    Shape->Height = 15;
    Shape->Width = 180 - 10*i;
    Shape->Left = static_cast_Shape("ShapeRod", start_peg)->Left -
                  (Shape->Width - static_cast_Shape("ShapeRod", start_peg)->Width) / 2;
    Shape->Top = ShapePlatform->Top - Shape->Height * i;
    Shape->Brush->Color = color[(i-1)%color_count];
    plates[start_peg-1][i] = i;
  }
  plates[start_peg-1][0] = plate_quantity;
  moves = 0;
}
//---------------------------------------------------------------------------
void TForm1::ShapeMoveTo(int shapenum, int from, int to, int pos)
{
  static_cast_Shape("Shape", shapenum)->Top = static_cast_Shape("ShapeRod", to)->Top - static_cast_Shape("Shape", shapenum)->Height;
  Sleep(pause);
  Application->ProcessMessages();
 
  if (abs(from - to) == 2)
  {
    static_cast_Shape("Shape", shapenum)->Left = static_cast_Shape("ShapeRod", 2)->Left -
                                               (static_cast_Shape("Shape", shapenum)->Width - static_cast_Shape("ShapeRod", 2)->Width) / 2;
    Sleep(pause);
    Application->ProcessMessages();
  }
 
  static_cast_Shape("Shape", shapenum)->Left = static_cast_Shape("ShapeRod", to)->Left -
                                               (static_cast_Shape("Shape", shapenum)->Width - static_cast_Shape("ShapeRod", to)->Width) / 2;
  Sleep(pause);
  Application->ProcessMessages();
 
  static_cast_Shape("Shape", shapenum)->Top = ShapePlatform->Top - static_cast_Shape("Shape", shapenum)->Height * pos;
  Sleep(pause);
  Application->ProcessMessages();
}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
  SpinEditRings->MaxValue = plate_quantity_max;
  SpinEditRings->Value = plate_quantity;
  SpinEditDelay->Value = pause;
  hanoi_init();
}
//---------------------------------------------------------------------------
// quantity - число колец, from - начальное положение колец (1-3),
// to - конечное положение колец (1-3), buf_peg - промежуточный колышек (1-3)
void TForm1::hanoi_towers(int quantity, int from, int to, int buf_peg)
{
  if (quantity && go)
  {
    int temp, i = plate_quantity + 1;
    hanoi_towers(quantity-1, from, buf_peg, to);
    moves++;
    Memo->Lines->Add("#" + String((moves < 10) ? "0" : "") + String(moves) + ": " + String(from) + " -> " + String(to));
 
    plates[from-1][0]--;
    plates[to-1][0]++;
    do
    {
      i--;
      temp = plates[from-1][i];
    }
    while (!temp);
    plates[from-1][i] = 0;
 
    i = 0;
    do
    {
      i++;
    }
    while (plates[to-1][i]);
    plates[to-1][i] = temp;
 
    if (go)
      ShapeMoveTo(temp, from, to, i);
 
    hanoi_towers(quantity-1, buf_peg, to, from);
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonStartClick(TObject *Sender)
{
  go ^= 1;
  if (go)
  {
    Memo->Clear();
    for (int i = 1; i <= plate_quantity; i++)
      static_cast_Shape("Shape", i)->~TShape();
    hanoi_init();
 
    Sleep(pause);
    Application->ProcessMessages();
 
    ButtonStart->Caption = "Стоп";
    SpinEditRings->Enabled = 0;
    hanoi_towers(plate_quantity, start_peg, destination_peg, buffer_peg);
    go = 0;
  }
  ButtonStart->Caption = "Рестарт";
  SpinEditRings->Enabled = 1;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
  go = 0;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SpinEditRingsChange(TObject *Sender)
{
  Memo->Clear();
  for (int i = 1; i <= plate_quantity; i++)
    delete static_cast_Shape("Shape", i);
  plate_quantity = SpinEditRings->Value;
  hanoi_init();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SpinEditDelayChange(TObject *Sender)
{
  pause = SpinEditDelay->Value;
}
Миниатюры
Ханойские башни  
Вложения
Тип файла: zip hanoi_towers.zip (1.40 Мб, 106 просмотров)
4
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
13.05.2016, 04:24
Ответы с готовыми решениями:

Ханойские башни
Головоломка “Ханойские башни” состоит из трех стержней, пронумерованных числами 1, 2, 3. На стержень 1 надета пирамидка из n дисков ...

Ханойские башни
Ханойские башни. Алгоритм я приблизительно понимаю, но программу написать не могу... Мне не нужно решение, просто скажите, может лучше...

Ханойские башни
Не могу понять где ошибка,проверяла на 3 монетках ,разного достоинства, наложенных друг на друга,на основе этого и составляла код.но...

5
 Аватар для BRcr
4043 / 2333 / 292
Регистрация: 03.02.2011
Сообщений: 5,066
Записей в блоге: 10
13.05.2016, 21:31
Ляпота, можно вечно наблюдать, как головоломка решается сама собой.

Только две вещи слегка вымораживают. Покритиковать хоть для разнообразия
Вызовы static_cast_Shape() и явный вызов деструкторов. Просто как серпом по.., ну, то есть в глаза бросается очень, я хотел сказать.
1
place status here
 Аватар для gunslinger
3186 / 2220 / 640
Регистрация: 20.07.2013
Сообщений: 6,013
14.05.2016, 02:00  [ТС]
Лучше dynamic_cast, чем static?
Есть отличие между delete и ~...?
Или сам подход к выбору "инструментария" в корне неверный?
P.S.: а еще я Sleep использую вместо таймера, но это я хотя бы понимаю.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33376 / 21500 / 8236
Регистрация: 22.10.2011
Сообщений: 36,895
Записей в блоге: 11
14.05.2016, 10:21
Цитата Сообщение от gunslinger Посмотреть сообщение
Лучше dynamic_cast, чем static?
Я бы занес шейпы в массив TShape*, и забыл бы о касте вообще как о страшном сне. Зачем каждый раз искать компонент, если можно запомнить ссылку на него при создании?

Второе, более серьезное замечание: у тебя проблема с конструктором формы. Попробуй в редакторе формы выставить в SpinEditRings значение, отличное от plate_quantity (если они совпадают - то все будет нормально, а вот при НЕсовпадении - бум...), и потом запустить программу. Понимаешь, что будет, да?
1
place status here
 Аватар для gunslinger
3186 / 2220 / 640
Регистрация: 20.07.2013
Сообщений: 6,013
15.05.2016, 06:17  [ТС]
Спасибо. Второй момент упустил из виду. Плохо я тестировал. Так нормально будет? Ошибка, конечно, "ушла".
C++
1
2
3
4
5
6
7
8
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
  hanoi_init();
  SpinEditRings->MaxValue = plate_quantity_max;
  SpinEditRings->Value = plate_quantity;
  SpinEditDelay->Value = pause;
}
И можно пример кода по первому пункту? Не то чтобы я совсем не понимаю, но лучше наверно увидеть, как это нужно делать правильно.

Небольшое лирическое отступление: у меня до сих пор вызывает некоторые трудности (восприятия) создание динамических массивов. А принципы ООП в (очень) общем виде хоть и понимаю, но реализация всегда идет "туго".
Видимо, в свое время вместо Стивена Кинга нужно было читать совсем другую литературу.

Добавлено через 19 часов 17 минут
Исправил:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
const start_peg = 1, destination_peg = 3, buffer_peg = 2, plate_quantity_max = 15, rod_count = 3, color_count = 15;
TColor color[color_count] = {clRed, clYellow, clGreen, clBlue, clFuchsia, clOlive, clLime, clAqua, clMaroon, clPurple, clTeal, clNavy, clMoneyGreen, clSkyBlue, clGray};
int plates[rod_count][plate_quantity_max+1] = {0}, moves, pause = 250, plate_quantity = 10;
TShape *Shape[plate_quantity_max], *ShapeRod[rod_count];
bool go = 0;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
  for (int i = 0; i < rod_count; i++)
    ShapeRod[i] = dyn_cast_Shape("ShapeRod", i+1);
 
  for (int i = 1; i <= plate_quantity_max; i++)
  {
    TShape *shape = new TShape(Form1);
    shape->Parent = Form1;
    shape->Name = "Shape" + String(i);
    shape->Shape = stRoundRect;
    shape->Height = 15;
    shape->Width = 180 - 10*i;
    shape->Left = ShapeRod[start_peg-1]->Left - (shape->Width - ShapeRod[start_peg-1]->Width) / 2;
    shape->Top = ShapePlatform->Top - shape->Height * i;
    shape->Brush->Color = color[(i-1)%color_count];
    shape->Visible = 0;
    Shape[i-1] = shape;
  }
 
  SpinEditRings->MaxValue = plate_quantity_max;
  SpinEditRings->Value = plate_quantity;
  SpinEditDelay->Value = pause;
  hanoi_init();
}
//---------------------------------------------------------------------------
TShape *TForm1::dyn_cast_Shape (String ShapeName, int num)
{
  return dynamic_cast<TShape*>(FindComponent(ShapeName + String(num)));
}
//---------------------------------------------------------------------------
void TForm1::hanoi_init()
{
  for (int i = 0; i <= plate_quantity; i++)
    for (int j = 0; j < rod_count; j++)
      plates[j][i] = 0;
 
  for (int i = 0; i < plate_quantity; i++)
  {
    Shape[i]->Left = ShapeRod[start_peg-1]->Left - (Shape[i]->Width - ShapeRod[start_peg-1]->Width) / 2;
    Shape[i]->Top = ShapePlatform->Top - Shape[i]->Height * (i+1);
    Shape[i]->Visible = 1;
    plates[start_peg-1][i+1] = i+1;
  }
  plates[start_peg-1][0] = plate_quantity;
  moves = 0;
}
//---------------------------------------------------------------------------
void SleepProcMes()
{
  Sleep(pause);
  Application->ProcessMessages();
}
//---------------------------------------------------------------------------
void TForm1::ShapeMoveTo(int shapenum, int from, int to, int pos)
{
  shapenum--;
  from--;
  to--;
 
  Shape[shapenum]->Top = ShapeRod[to]->Top - Shape[shapenum]->Height;
  SleepProcMes();
 
  if (abs(from - to) == 2)
  {
    Shape[shapenum]->Left = ShapeRod[1]->Left - (Shape[shapenum]->Width - ShapeRod[1]->Width) / 2;
    SleepProcMes();
  }
 
  Shape[shapenum]->Left = ShapeRod[to]->Left - (Shape[shapenum]->Width - ShapeRod[to]->Width) / 2;
  SleepProcMes();
 
  Shape[shapenum]->Top = ShapePlatform->Top - Shape[shapenum]->Height * pos;
  SleepProcMes();
}
//---------------------------------------------------------------------------
// quantity - число колец, from - начальное положение колец (1-3),
// to - конечное положение колец (1-3), buf_peg - промежуточный колышек (1-3)
void TForm1::hanoi_towers(int quantity, int from, int to, int buf_peg)
{
  if (quantity && go)
  {
    int temp, i = plate_quantity + 1;
    hanoi_towers(quantity-1, from, buf_peg, to);
    moves++;
    Memo->Lines->Add("#" + String((moves < 10) ? "0" : "") + String(moves) + ": " + String(from) + " -> " + String(to));
 
    plates[from-1][0]--;
    plates[to-1][0]++;
    do
    {
      i--;
      temp = plates[from-1][i];
    }
    while (!temp);
    plates[from-1][i] = 0;
 
    i = 0;
    do
    {
      i++;
    }
    while (plates[to-1][i]);
    plates[to-1][i] = temp;
 
    if (go)
      ShapeMoveTo(temp, from, to, i);
 
    hanoi_towers(quantity-1, buf_peg, to, from);
  }
}
//---------------------------------------------------------------------------
void TForm1::hanoi_reset()
{
  Memo->Clear();
  for (int i = 0; i < plate_quantity_max; i++)
    Shape[i]->Visible = 0;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonStartClick(TObject *Sender)
{
  go ^= 1;
  if (go)
  {
    hanoi_reset();
    hanoi_init();
 
    SleepProcMes();
 
    ButtonStart->Caption = "Стоп";
    SpinEditRings->Enabled = 0;
    hanoi_towers(plate_quantity, start_peg, destination_peg, buffer_peg);
    go = 0;
  }
  ButtonStart->Caption = "Рестарт";
  SpinEditRings->Enabled = 1;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
  go = 0;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SpinEditRingsChange(TObject *Sender)
{
  hanoi_reset();
  plate_quantity = SpinEditRings->Value;
  hanoi_init();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SpinEditDelayChange(TObject *Sender)
{
  pause = SpinEditDelay->Value;
}
1
 Аватар для BRcr
4043 / 2333 / 292
Регистрация: 03.02.2011
Сообщений: 5,066
Записей в блоге: 10
15.05.2016, 19:42
Цитата Сообщение от gunslinger Посмотреть сообщение
Есть отличие между delete и ~...?
Явный вызов используется после placement new, в остальных случаях в этом просто нет смысла. И брать за правило использовать без нужды явный вызов - это плохая идея. А вдруг оператор delete по какой-то причине перегружен для класса или глобально?
2
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
15.05.2016, 19:42
Помогаю со студенческими работами здесь

Ханойские башни
Ребята, помогите разобраться с алгоритмом, то что сначала перемещаются n-1 дисков на вспомогательный стержень, затем n-ый нижний диск на...

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

Ханойские башни
Кто-то из вас может решить адачу о ханойских башнях на си++ рекурсивным способом, а тоя никак не могу догнат что в даное задаче является...

Ханойские башни
Уважаемые программисты. Срочно очень нужно рекурсивное решение задачи “Ханойские башни” на С# с графическим отображением. Может у...

Ханойские башни
У Дейтлов есть задача: Не могу до конца сформулировать алгоритм. Предположим, я беру 3 колышка и 4 диска int k1, k2, k3;...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Новые блоги и статьи
Загрузка PNG-файла с альфа-каналом с помощью библиотеки SDL3_image на Android
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
Вывод текста со шрифтом TTF на Android с помощью библиотеки SDL3_ttf
8Observer8 25.01.2026
Содержание блога Если у вас не установлены Android SDK, NDK, JDK, и т. д. то сделайте это по следующей инструкции: Установка Android SDK, NDK, JDK, CMake и т. д. Сборка примера Скачайте. . .
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net REST сервисы временно не работают, только через Web. Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
Модель сукцессии микоризы
anaschu 24.01.2026
Решили писать научную статью с неким РОманом
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru