
// AnimatedHanoi.java
// Robert Sedgewick and Kevin Wayne
// Slightly reformatted by Andrew Davison, Nov. 2022

// https://introcs.cs.princeton.edu/java/23recursion/AnimatedHanoi.java.html

/* Solve the Towers of Hanoi problem on n discs and animate the
   calculation.

   Usage:
     > compile AnimatedHanoi.java
     > run AnimatedHanoi n
   e.g.
     > run AnimatedHanoi 6
*/


import java.awt.Color;


public class AnimatedHanoi
{

  public static void main(String[] args)
  {
    if (args.length != 1) {
      System.out.println("Usage: run AnimatedHanoi <no. of discs>");
      return;
    }

    int n = Integer.parseInt(args[0]);     // number of discs
    int WIDTH  = 200;                      // width of largest disc
    int HEIGHT = 20;                       // height of each disc

    // set size of window and scale
    StdDraw.setCanvasSize(4*WIDTH, (n+3)*HEIGHT);
    StdDraw.setXscale(-1, 3);
    StdDraw.setYscale(0, n+3);
    StdDraw.enableDoubleBuffering();

    int[] poles = new int[n+1];      
       // poles[i] = poles (0-2) that disc i is on
    draw(poles);
    hanoi(n, 0, 1, 2, poles);
    System.out.println("Solved");
  } /* main */


  private static void draw(int[] poles)
  // draw the current state
  {
    StdDraw.clear();
    StdDraw.setPenColor(StdDraw.BLACK);
    StdDraw.setPenRadius(0.002);

    int n = poles.length - 1;

    // draw 3 poles
    for (int i = 0; i < 3; i++)
      StdDraw.line(i, 0, i, n);

    // draw n discs
    int[] discs = new int[3];     // discs[p] = # discs on pole p
    for (int i = n; i >= 1; i--) {
      Color color = Color.getHSBColor(1.0f * i / n, 0.7f, 0.7f);
      StdDraw.setPenColor(color);
      StdDraw.setPenRadius(0.035);      // magic constant
      double size = 0.5 * i / n;
      int p = poles[i];
      StdDraw.line(p-size/2, discs[p], p + size/2, discs[p]);
      ++discs[p];
    }

    StdDraw.show();
    StdDraw.pause(100);
  } /* draw */



  private static void hanoi(int n, int from, int temp, int to, int[] poles)
  {
    if (n == 0)
      return;

    hanoi(n-1, from, to, temp, poles);
    System.out.println("Move disc " + n + " from pole " + from +
                       " to pole " + to);
    poles[n] = to;
    draw(poles);
    hanoi(n-1, temp, from, to, poles);
  } /* hanoi */


}  // end of AnimatedHanoi class
