//=============================================================================

#include <iostream>
#include <limits>
#include <string>
#include <vector>
using std::cin;
using std::cout;
using std::numeric_limits;
using std::streamsize;
using std::string;
using std::vector;

//-------------------------------------------------------------------------------

using tower = vector<int>;
using size = tower::size_type;

//-------------------------------------------------------------------------------

tower tower1, tower2, tower3;
int count;
int move;

//-------------------------------------------------------------------------------

void print_tower_layer(const tower& t, int layer)
{
   size l = static_cast<size>(layer);
   int sw = t.size() <= l ? 0 : t[l];

   string::size_type space_count = static_cast<string::size_type>(count - sw);
   string::size_type slice_width = static_cast<string::size_type>(sw);

   string spaces(space_count, ' ');
   string half_slice(slice_width, '-');
   cout << spaces << half_slice << '|' << half_slice << spaces;
}

//-------------------------------------------------------------------------------

void print()
{
   cout << '\n' << move << ".\n";
   for (int layer = count - 1; layer >= 0; --layer)
   {
      cout << ' ';
      print_tower_layer(tower1, layer);
      cout << ' ';
      print_tower_layer(tower2, layer);
      cout << ' ';
      print_tower_layer(tower3, layer);
      cout << '\n';
   }
   cout << string(6 * count + 7, '*') << '\n';
}

//-------------------------------------------------------------------------------

void move_slice(tower& source, tower& dest)
{
   int slice = source.back();
   source.pop_back();
   dest.push_back(slice);
   ++move;
   print();
}

//-------------------------------------------------------------------------------

void move_tower(size layer, tower& source, tower& dest, tower& help)
{
   // Wenn die zu bewegende Ebene die oberste ist, 
   // dann kann die Scheibe direkt bewegt werden.
   if (layer == source.size() - 1)
   {
      move_slice(source, dest);
      return;
   }

   // Um den gesamten Haufen von Scheiben ab der angegebenen Ebene
   // zu bewegen, muss:
   // - zuerst der Haufen Scheiben ueber der Ebene zum Hilfs-Turm bewegt werden,
   // - dann die Scheibe zum Ziel-Turm bewegt werden, und dann
   // - der verschobene Haufen auf die bewegte Scheibe bewegt werden.
   size help_layer = help.size();
   move_tower(layer + 1, source, help, dest);
   move_slice(source, dest);
   move_tower(help_layer, help, dest, source);
}

//-------------------------------------------------------------------------------

int main()
{
   cout << "Aufg_12_10_Tuerme_von_Hanoi_1\n\n";

   for (;;)
   {
      cout << "Mit wie vielen Scheiben (1-20) sollen die Tuerme von Hanoi gespielt werden: ";
      cin >> count;
      if (!cin.fail() && count > 0 && count < 21) break;
      cout << "\nEingabe-Fehler\n\n";
      cin.clear();
      cin.ignore(numeric_limits<streamsize>::max(), '\n');
   }

   for (int i = count; i > 0; --i)
   {
      tower1.push_back(i);
   }

   // Zug initialisieren, Anfangs-Zustand ausgeben, und dann los mit der Simulation...
   move = 1;
   print();
   move_tower(0, tower1, tower3, tower2);
}
