/**
 * cd1.java - 16/07/2010
 *
 * auteur : JPQ
 *
 * L'ordinateur propose une grille de 2 lignes et 2 colonnes dans laquelle
 * se trouvent des disques de couleur bleu ou des carrés de couleur jaune
 *
 * Le but du jeu pour l'ordinateur est d'arriver à obtenir 4 figures
 * du même type : 4 disques bleus ou 4 carrés jaunes.
 *
 * Le but du jeu pour l'utilisateur est d'éviter que l'ordinateur gagne !
 *
 * Le bouton "Init" relance une grille aléatoire
 * ajout de main() le 08/01/18, modification le 29/08/22
 */

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;

public class cd1 extends JPanel implements ActionListener {
	static final long serialVersionUID = 220829L;
	JButton reinit = new JButton ("Init");
	JTextField tf = new JTextField (40);
	feuille dessin = new feuille();
	Random rnd = new Random();
// forme contient le type de figures pour les 4 cases de la grille
// true pour le disque, false pour le carré
	boolean[] forme = new boolean[4];
// liste des commandes
	char[] cmds = {'D', 'L', 'D', '1', 'D', 'L', 'D'};
	int icmds = 0;
// une commande en cours => on sauvegarde son type et le numéro de la case cliquée
	char dercmd = ' ';
	int derclic = -1;

	public cd1() {
		setFont(new Font("Arial, Helvetica, sans-serif", Font.PLAIN, 12));
		setLayout (new BorderLayout());
		JPanel p = new JPanel();
		p.setBackground(Color.LIGHT_GRAY);
		p.setBorder (BorderFactory.createMatteBorder(1, 1, 1, 1, Color.BLACK));
		add(p, BorderLayout.NORTH);
		p.add(reinit);
		reinit.addActionListener(this);
		p.add (tf);
		add (dessin, BorderLayout.CENTER);
		for (int i = 0; i < forme.length; i++)
			forme [i] = rnd.nextBoolean();
	}

	public void actionPerformed (ActionEvent evt) {
		if (evt.getSource() == reinit) {
			for (int i = 0; i < forme.length; i++)
				forme [i] = rnd.nextBoolean();
			dercmd = ' ';
			derclic = -1;
			icmds = 0;
			dessin.repaint();
		}
	}

	public boolean gagne() {
		boolean f0 = forme [0];
		for (int i = 1; i < forme.length; i++)
			if (forme [i] != f0)
				return false;
		return true;
}

	public static void main (String [] args) {
		int w = 600;
		int h = 400;
		cd1 c = new cd1 ();
		JFrame f = new JFrame ("cd1");
		f.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
		f.add (c);
		f.setSize (w, h);
		f.setVisible (true);
	}

/**
 * classe feuille 29/08/22
 *
 */

protected class feuille extends Canvas implements MouseListener, MouseMotionListener {
	static final long serialVersionUID = 220829L;
	int margex, margey, cote, cotefig;
	int margeext = 10;
	int margeint = 10;
	int intc;
	String s = "";

	public feuille() {
		setBackground (Color.WHITE);
		addMouseListener (this);
		addMouseMotionListener (this);
	}

	private void figure (Graphics g, int n) {
		int x = margex;
		int y = margey;
		if (n / 2 == 1)
			y += cote;
		if (n % 2 == 1)
			x += cote;
		g.setColor(Color.BLACK);
		g.drawRect (x, y, cote, cote);
		x += margeint;
		y += margeint;
		if (forme[n]) {
			if (derclic == n)
				g.setColor (Color.LIGHT_GRAY);
			else
				g.setColor(Color.BLUE);
		g.fillOval (x, y, cotefig, cotefig);
		} else {
			if (derclic == n)
				g.setColor (Color.LIGHT_GRAY);
			else
				g.setColor(Color.YELLOW);
		g.fillRect (x, y, cotefig, cotefig);
		}
	}

	public void paint (Graphics g) {
// Calcul des marges (margex et margey) et de la longueur du carré : cote
		int dgw = getWidth();
		int dgh = getHeight();
		if (dgw >= dgh) {
			cote = (dgh - 2 * margeext) / 2;
			margex = dgw / 2 - cote;
			margey = margeext;
		} else {
			cote = (dgw - 2 * margeext) / 2;
			margex = margeext;
			margey = dgh / 2 - cote;
		}
// cotefig est le diamètre du disque ou la longueur du côté du carré
// dans le carré de bord noir
		cotefig = cote - 2 * margeint;
		for (int i = 0; i < forme.length; i ++)
			figure (g, i);
		if (gagne()) {
			g.setFont(new Font("Arial, Helvetica, sans-serif", Font.BOLD, 20));
			g.setColor (Color.RED);
			g.drawString ("GAGNÉ", dgw / 2 - 40, dgh / 2 + 10);
			tf.setText ("Gagné");
			dercmd = 'X';
		} else {
			if (s.length() == 0) {
				switch (cmds [icmds]) {
					case 'D' :
						s = "Cliquer sur 2 éléments d'une même diagonale";
						break;
					case 'L' :
						s = "Cliquer sur 2 éléments d'une même ligne ou colonne";
						break;
					case '1' :
						s = "Cliquer sur 1 élément";
						break;
					default :
						s = "Erreur dans la commande";
				}
			}
			tf.setText (s);
			s = "";
		}
	}

	public void mouseExited (MouseEvent e) {}
	public void mouseEntered (MouseEvent e) {}
	public void mouseReleased (MouseEvent e) {}
	public void mousePressed (MouseEvent e) {}
	public void mouseDragged (MouseEvent e) {}
	public void mouseClicked (MouseEvent e) {
		int x = e.getX();
		int y = e.getY();
// récupère le numéro de la case cliquée dans intc
		if ((x > margex) && (x < margex + 2 * cote) && (y > margey) && (y < margey + 2 * cote)) {
			intc = 0;
			if (x > margex + cote)
				intc = 1;
			if (y > margey + cote)
				intc += 2;
			switch (dercmd) {
				case ' ' :
					if (cmds [icmds] == '1') {
						forme [intc] = ! forme [intc];
						icmds++;
					} else {
						dercmd = cmds [icmds];
						derclic = intc;
					}
					break;
				case 'L' :
					if ((intc + derclic) != 3) {			// somme = 3 sur les diagonales
						forme [intc] = ! forme [intc];
						forme [derclic] = ! forme [derclic];
						dercmd = ' ';
						derclic = -1;
						icmds++;
					} else
						s = "D'UNE MÊME LIGNE OU COLONNE !";
					break;
				case 'D' :
					if ((intc + derclic) == 3) {			// somme = 3 sur les diagonales
						forme [intc] = ! forme [intc];
						forme [derclic] = ! forme [derclic];
						dercmd = ' ';
						derclic = -1;
						icmds++;
					} else
						s = "D'UNE MÊME DIAGONALE !";
					break;
			}
			repaint ();
		}
	}

	public void mouseMoved (MouseEvent e) {
		int x = e.getX();
		int y = e.getY();
		if ((x > margex) && (x < margex + 2 * cote) && (y > margey) && (y < margey + 2 * cote))
			setCursor (new Cursor (Cursor.HAND_CURSOR));
		else
			setCursor (new Cursor (Cursor.DEFAULT_CURSOR));
	}
}

}