/**
 * tourhanoi.java - jpq - 27/05/11 - 25/04/20 - 29/08/22
 * version avec pointeurs
 *
 */

import java.awt.event.*;
import java.awt.*;
import javax.swing.*;

public class tourhanoi extends JFrame implements ActionListener, Runnable {
	static final long serialVersionUID = 220829L;

	Image img;
	Graphics gimg;
	int wimg, himg, w, h;
	int n;
	JTextField tn;
	JButton ok;
	Dessin d;
	static boolean bdeplace;
	static Thread thr;

/* t[1], t[2] et t[3] contiennent les piles de disques symbolisés par des nombres 1, 2, 3...
 * wt contient les abscisses des piles
 * ptr[1], ptr [2] et ptr [3] pointent le haut de chaque pile (1er emplacement disponible
 * et donc 0 si la pile est vide)
 */
	int[][] t;
	int[] wt;
	int[] ptr;

	public tourhanoi(String s) {
		super (s);
		setBackground (Color.WHITE);
		setFont (new Font ("sans-serif", Font.PLAIN, 10));
		setLayout (new BorderLayout ());
		JPanel p = new JPanel ();
		add (p, BorderLayout.NORTH);
		p.setBorder (BorderFactory.createMatteBorder (1, 1, 1, 1, Color.BLACK));
		p.add (new JLabel ("n ="));
		n = 4;
		p.add (tn = new JTextField ("4", 4));
		p.add (ok = new JButton ("Ok"));
		ok.addActionListener (this);
		ptr = new int [3];
		init (n);
		add (d = new Dessin (), BorderLayout.CENTER);
	}

	private void init (int n) {
		ptr[0] = n;
		ptr[1] = ptr[2] = 0;
		t = new int [3][n];
		for (int i = 0; i < n; i ++) {
			t[0][i] = n - i;
			t[1][i] = t[2][i] = 0;
		}
		bdeplace = false;							// bdeplace = false entraîne la sortie du "deplace" puis du "run"
	}

	public void run() {
		while (bdeplace) {
				d.repaint();
				deplace (n, 0, 1, 2);
				bdeplace = false;
		}
	}

/*
 * fonction récursive deplace
 *
 * l'empilement de n disques nécessite 2^n - 1 déplacements
 */
 
	private void deplace (int nd, int org, int tmp, int dest) {
		if (nd > 0 && bdeplace) {
			deplace (nd - 1, org, dest, tmp);
// déplace le disque du haut de la pile t [org] sur la pile t [dest]
			if (bdeplace) {
				t [dest] [ptr [dest] ++] = t [org] [-- ptr [org]];
				t [org] [ptr [org]] = 0;
				d.repaint();
				try {
					Thread.sleep (500);				// attente de 500 ms
				}
				catch (InterruptedException e) {}
			}
			deplace (nd - 1, tmp, org, dest);
		}
	}

	public void actionPerformed (ActionEvent ae) {
		if (ae.getSource() == ok) {
			try {
				n = Integer.parseInt (tn.getText ());
			}
			catch (NumberFormatException nfe) { }
			tn.setText (Integer.toString (n));
			init (n);
			d.repaint();
			try {
				Thread.sleep (1000);				// attente de 1000 ms
				bdeplace = true;
				thr = new Thread(this);
				thr.start();
			}
			catch (InterruptedException ie) {}
			
		}
	}

/**
 * Dessin 25/04/20
 */

protected class Dessin extends Canvas {
	static final long serialVersionUID = 200425L;

	public void update (Graphics g) {
		paint (g);
	}

	public void paint (Graphics g) {
		w = getWidth();
		h = getHeight();
		if ((img == null) || (w != wimg) || (h != himg)) {
			wimg = w;
			himg = h;
			img = createImage (w, h);
			gimg = img.getGraphics();
// initialise la position des trois piles de disque
			wt = new int [3];
			int deltaw = (w - 25) / 6;
			wt [0] = 10 + deltaw;
			wt [1] = wt [0] + 2 * deltaw;
			wt [2] = wt [1] + 2 * deltaw;
		}
		gimg.setColor (Color.WHITE);
		gimg.fillRect (0, 0, w, h);
		gimg.setColor (Color.BLACK);
		gimg.fillRect (5, h - 10, w - 10, 5);
// dessine les 3 piles
		for (int i = 0; i < 3; i ++) {
			gimg.setColor (Color.BLACK);
			gimg.fillRect (wt [i] - 1, 80, 2, h - 90);
			int k = 0;
			gimg.setColor (Color.RED);
			while ((k < n) && (t[i][k] != 0))
				gimg.fillRect (wt[i] - 5 * t[i][k], h - 20 - 10 * k, 10 * t[i][k++], 10);
		}
		g.drawImage (img, 0, 0, this);
	}
}

	public static void main (String[] args) {
		tourhanoi f = new tourhanoi ("Les tours de Hanoï - version récursive");
		f.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
		f.setSize (400, 200);
		f.setVisible (true);
	}

}