/**
 * taquin.java - 13/11/11 - 19/11/11
 *
 * auteur : Jean-Paul Quelen
 *
 * Pour que le jeu soit possible il suffit qu'il y ait un nombre pair de permutations
 *
 * ajout de main() le 08/01/18. Modifié le 29/08/22
 */

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.*;
import java.util.*;
import java.awt.Toolkit;

public class taquin extends JPanel implements MouseListener, MouseMotionListener {
	static final long serialVersionUID = 220829L;
	Image[] img;
	int x[], y[];
	Cursor defaut, hand, move;
	int idep, depx, depy, x0, y0, x1, y1;
	Random rnd;
	int i0;

	public taquin() {
		setBackground (Color.BLACK);
		java.awt.Toolkit toolkit = java.awt.Toolkit.getDefaultToolkit();
		addMouseMotionListener (this);
		addMouseListener (this);
		img = new Image [10];
		x = new int [9];
		y = new int [9];
		for (int i = 0; i < 3; i++) {
			int xi = i * 58 + 1;
			for (int j = 0; j < 3; j++) {
				int k = i * 3 + j;
				img [k] = toolkit.getImage ("i" + k + ".jpg");		// img[0]: image "Jeu du Taquin" 
				y [k] = xi;
				x [k] = j * 58 + 1;
			}
		}
		img [9] = toolkit.getImage ("ig.jpg");						// image "GAGNÉ"

// 8 permutations
		rnd = new Random();
		for (int i = 0; i < 8; i++) {
			int j = rnd.nextInt (8) + 1;							// nbre aléatoire dans {1, 2, 3, 4, 5, 6, 7, 8}
			int k = j;
			while (k == j)
				k = rnd.nextInt (8) + 1;
			int l = x [j];
			x [j] = x [k];
			x [k] = l;
			l = y [j];
			y [j] = y [k];
			y [k] = l;
		}

		x0 = x1 = 1;
		y0 = y1 = 1;
		depx = 0;
		depy = 0;
		defaut = this.getCursor();
		hand = new Cursor (Cursor.HAND_CURSOR);
		move = new Cursor (Cursor.MOVE_CURSOR);
//		i0 = 0;
	}

	public void update (Graphics g) {
		paint (g);
	}

	public void paint (Graphics g) {
		g.setColor (Color.BLACK);
		g.drawLine (0, 0, 0, 174);
		g.drawLine (0, 0, 174, 0);
		g.fillRect (x0, y0, 58, 58);
		g.fillRect (x1, y1, 58, 58);
		for (int i = i0; i < 9; i++)
			g.drawImage (img [i], x [i], y [i], this);
	}

	public void mousePressed (MouseEvent e) {
		e.consume();
		int X = e.getX();
		int Y = e.getY();
		if (test (X - 58, Y)) {
			depx = -1;
			depy = 0;
		} else if (test (X + 58, Y)) {
			depx = 1;
			depy = 0;
		} else if (test (X, Y- 58)) {
			depx = 0;
			depy = -1;
		} else if (test (X, Y + 58)) {
			depx = 0;
			depy = +1;
		} else {
			depx = depy = 0;
			setCursor (defaut);
		}
		if (depx != 0 || depy != 0) {
			for (int i = 1; i < 9; i++)
				if ((X >= x [i]) && (X < x [i] + 58) && (Y >= y [i]) && (Y < y [i] + 58)) {
					x1 = x [i];
					y1 = y [i];
					idep = i;
					break;
				}
			setCursor (move);
			i0 = 1;
		}
	}

	public void mouseDragged (MouseEvent e) {
		e.consume ();
		if (depx != 0 || depy != 0) {
			if (x [idep] != x0 || y [idep] != y0) {
				x [idep] += depx;
				y [idep] += depy;
			}
			repaint();
		}
	}

	public void mouseReleased (MouseEvent e) {
		e.consume ();
		if (depx != 0 || depy != 0) {
			x [idep] = x0;
			y [idep] = y0;
			x0 = x1;
			y0 = y1;
			depx = depy = 0;
			boolean gagne = true;
			for (int i = 1; i < 9; i ++)
				if ((x [i] != (i % 3) * 58 + 1) || (y [i] != (i / 3) * 58 + 1)) {
					gagne = false;
					break;
				}
			if (gagne) {
				img [0] = img [9];
				i0 = 0;
			}
			repaint();
		}
	}

	private boolean test (int ix, int iy) {
		return (ix >= x0) && (ix < x0 + 58) && (iy >= y0) && (iy < y0 + 58);
	}

	public void mouseMoved (MouseEvent e) {
		e.consume ();
		int X = e.getX();
		int Y = e.getY();
		if (test (X - 58, Y) || test (X + 58, Y) || test (X, Y - 58) || test (X, Y + 58))
			setCursor (hand);
		else
			setCursor (defaut);
	}

public void mouseClicked (MouseEvent e) {}
public void mouseEntered (MouseEvent e) {}
public void mouseExited (MouseEvent e) {}

	public static void main (String [] args) {
		int w = 200;
		int h = 220;
		taquin t = new taquin ();
		JFrame f = new JFrame ("taquin");
		f.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
		f.add (t);
		f.setSize (w, h);
		f.setVisible (true);
	}
}
