//
Construction de carrés magiques : applet Java
// CarMagique.java
// Trois classes:
// CarMagique : choix de méthode
// CarreFen : présentation de carré
// Carre : construction de carré
//
// jar -cvf raCarreM.jar Car*.class
// lancement de l'applet par: raCarreMagie.html
import java.awt.*;
import java.awt.event.*;
// // // // // // // // // // // // // // // // // ////
// Choix de méthodes de construction //
// applet ou application //
// // // // // // // // // // // // // // // // // ////
public class CarMagique extends java.applet.Applet
implements ActionListener, ItemListener {
Choice choixP, choixI, choixI2, choixI3, choixI4, choixP4n, choixP4np2;
// Pour utilisation mixte, applet ou application
public void init() { creerIU(null); }
private void creerIU(Frame f) {
choixI = new Choice(); Button btnI=new Button("Ordre impair 1");
for(int i=3; i<32; i+=2) choixI.add(""+i);
choixI.addItemListener(this); // add(choixI);
btnI.addActionListener(this); btnI.setActionCommand("impair1");
choixI2 = new Choice(); Button btnI2=new Button("Ordre impair 2");
for(int i=3; i<32; i+=2) choixI2.add(""+i);
choixI2.addItemListener(this); // add(choixI2);
btnI2.addActionListener(this); btnI2.setActionCommand("impair2");
choixI3 = new Choice(); Button btnI3=new Button("Ordre impair 3");
for(int i=3; i<32; i+=2) choixI3.add(""+i);
choixI3.addItemListener(this); // add(choixI2);
btnI3.addActionListener(this); btnI3.setActionCommand("impair3");
choixI4 = new Choice(); Button btnI4=new Button("Ordre impair 4");
for(int i=3; i<32; i+=2) choixI4.add(""+i);
choixI4.addItemListener(this); // add(choixI2);
btnI4.addActionListener(this); btnI4.setActionCommand("impair4");
choixP = new Choice(); Button btnP=new Button("Ordre pair");
for(int i=4; i<32; i+=2) choixP.add(""+i);
choixP.addItemListener(this); // add(choixI);
btnP.addActionListener(this); btnP.setActionCommand("pair");
// this.add(choixP);
choixP4n = new Choice(); Button btnP4n=new Button("Multiple de 4");
for(int i=4; i<37; i+=4) choixP4n.add(""+i);
choixP4n.addItemListener(this); // add(choixI);
btnP4n.addActionListener(this); btnP4n.setActionCommand("pair4n");
choixP4np2 = new Choice(); Button btnP4np2=new Button("2+ multiple de 4");
for(int i=6; i<37; i+=4) choixP4np2.add(""+i);
choixP4np2.addItemListener(this); // add(choixI);
btnP4np2.addActionListener(this); btnP4np2.setActionCommand("pair4np2");
Button aff=new Button("HyperMagique"); // this.add(aff);
aff.addActionListener(this); aff.setActionCommand("c8");
if(f != null) f.add(this);
this.setLayout(new BorderLayout());
Panel p1=new Panel(new GridLayout(0,2)), p2=new Panel();
p1.add(btnI);p1.add(choixI);
p1.add(btnI2);p1.add(choixI2);
p1.add(btnI3);p1.add(choixI3);
p1.add(btnI4);p1.add(choixI4);
p1.add(btnP);p1.add(choixP);
p1.add(btnP4n);p1.add(choixP4n);
p1.add(btnP4np2);p1.add(choixP4np2);
p2.add(aff);
this.add(p1,BorderLayout.CENTER);
this.add(p2,BorderLayout.SOUTH);
}
public void actionPerformed(ActionEvent evt){
CarreFen f; int ordre=0, c[][]=Carre.c8;
if(evt.getActionCommand().equals("c8")) ordre=8;
else if(evt.getActionCommand().equals("impair1")) {
ordre= Integer.parseInt(choixI.getSelectedItem());
c=Carre.cImpair(ordre);
}
else if(evt.getActionCommand().equals("impair2")) {
ordre= Integer.parseInt(choixI2.getSelectedItem());
c=Carre.cImpair2(ordre);
}
else if(evt.getActionCommand().equals("impair3")) {
ordre= Integer.parseInt(choixI3.getSelectedItem());
c=Carre.cImpair3(ordre);
}
else if(evt.getActionCommand().equals("impair4")) {
ordre= Integer.parseInt(choixI4.getSelectedItem());
c=Carre.cImpair4(ordre);
}
// Ordre pair
else if(evt.getActionCommand().equals("pair")) {
ordre= Integer.parseInt(choixP.getSelectedItem());
c=Carre.cPair(ordre);
}
else if(evt.getActionCommand().equals("pair4n")) {
ordre= Integer.parseInt(choixP4n.getSelectedItem());
c=Carre.cPair4n(ordre);
}
else if(evt.getActionCommand().equals("pair4np2")) {
ordre= Integer.parseInt(choixP4np2.getSelectedItem());
c=Carre.cPair4np2(ordre);
}
// Créer une fenêtre affichant le carré
if(ordre>0 && ordre!=2)
(new CarreFen(c)).show();
}
public void itemStateChanged(ItemEvent e) {
int ordre= Integer.parseInt((String)e.getItem());
Choice choix=(Choice)e.getSource();
int c[][]=Carre.c8;
if(choix==choixI) c=Carre.cImpair(ordre);
else if(choix==choixI2) c=Carre.cImpair2(ordre);
else if(choix==choixI3) c=Carre.cImpair3(ordre);
else if(choix==choixI4) c=Carre.cImpair4(ordre);
else if(choix==choixP) c=Carre.cPair(ordre);
else if (choix==choixP4n)c=Carre.cPair4n(ordre);
else if (choix==choixP4np2)c=Carre.cPair4np2(ordre);
CarreFen f=new CarreFen(c);
f.show();
}
// Pour version application
static Frame initAppli() {
int xxFen=200, yyFen=220;
Frame fen = new Frame();
fen.setSize(xxFen,yyFen);
// Placer un composant dans cette fenêtre
CarMagique cm=new CarMagique();
cm.creerIU(fen);
WindowAdapter pf = new WindowAdapter() {
public void windowClosing(WindowEvent e){System.exit(0);};
};
fen.addWindowListener(pf);
return fen;
}
// Utilisation application
public static void main(String[] args) {
Frame fen = initAppli();
fen.show();
// int c[][]=Carre.cImpair2(7); Carre.aff(c,c.length);
}
}
// // // // // // // // // // // // // // // // // ////
// Présentation de carrés //
// // // // // // // // // // // // // // // // // ////
/** Fenêtre affichant un carré, avec les ommes par ligne
* colonne ou diagonale
*/
class CarreFen extends Frame
implements ActionListener, MouseListener, KeyListener {
int car[][]; // le carré magique
int n;
// Cases sélectionnées pour alignement: ligne, colonne, diagonales ...
boolean csa[][]; // vrai:case choisie, faux:case simple
Point caseClic;
int choixCases; // 1:ligne 2:colonne 3:diag.S 4:diag.P
final int CXLI=1, CXCO=2, // choix ligne, colonne
CXDM=3, CXDD=4, // diagonale montante, descendante
CXC4=5, CXC2=6; // carré 4x4 ou 2x2
static final String chChoix[][]= { // intitulé item, et commande associée
{"Ligne","Colonne","Diagonale montante","Diagonale descendante"
,"Carre 4*4","Carre 2*2"}
,{"li","co","dm","dd","c4","c2"}};
int nChoix=chChoix[0].length;
Dialog info;
Canvas can;
// Position et dimensions de la case en haut à gauche
int xchg=50, ychg=40, xxc=25, yyc=24;
int xxFen, yyFen;
public CarreFen(int c[][]) {
car=c;
n=c.length;
// tous les choix pour carré hypermagique seul
nChoix = (n==8) ? 6 : 4;
xxc = (n<32) ? 25 : 30;
csa = new boolean[n][n];
caseClic=new Point(0,0); choixCases=1; selec(1);
can = new Canvas() {
public void paint(Graphics g) { afficheCarre(g); }
};
ScrollPane pa = new ScrollPane();
add(pa); pa.add(can);
setMenuBar(barreMenus());
setTitle("Carre magique d'ordre "+n);
// Largeur variable pour avoir l'affichage de toute la somme
xxFen = xchg+(n<7?7:n)*(xxc+1)+
xchg*(n<10?1:(n<22)?2:3);
yyFen = ychg+(n+1)*yyc+3*ychg;
setSize(xxFen,yyFen);
this.setLocation((int)(100*(1+Math.random())),100);
// Pour fermer la fenêtre
WindowAdapter pf = new WindowAdapter() {
public void windowClosing(WindowEvent e){dispose();};
};
this.addWindowListener(pf);
// On réagit à la souris et au clavier
can.addMouseListener(this);
can.addKeyListener(this);
// Dialogue avec un texte et bouton fermer
info=new Dialog(this,false); info.setSize(250,160);
info.setLayout(new GridLayout(0,1));
info.add(new Label("Carrés complétés par Roger Astier",Label.CENTER));
info.add(new Label("Carré crée par Kathleen Ollerenshaw",Label.CENTER));
info.add(new Label("Applet écrite par Yannick Devaux",Label.CENTER));
Button vu=new Button("Fermer");
info.add(vu);
// Pour fermer la boîte de dialogue
vu.addActionListener(this); vu.setActionCommand("fermerBD");
WindowAdapter pfInfo = new WindowAdapter() {
public void windowClosing(WindowEvent e){info.dispose();};
};
info.addWindowListener(pfInfo);
}
MenuBar barreMenus() {
// Choix type de ligne
Menu m1=new Menu("Type");
MenuItem mi;
for( int i=0; i=5)?"":somme;
// dernière ligne
g.drawString(""+som,xchg+n*xxc+10,ychg+jt*yyc+yyc/2+5);
g.drawString("Somme : "+somme+som,xchg-xxc,ychg+n*yyc+yyc);
// marquer le milieu
if(n%2==0 && n>10){
p=xchg+n/2*xxc;
g.drawLine(p-1,ychg-1,p-1,ychg+yyc*n);
g.drawLine(p+1,ychg-1,p+1,ychg+yyc*n);
p=ychg+n/2*yyc;
g.drawLine(xchg,p-1,xchg+xxc*n,p-1);
g.drawLine(xchg,p+1,xchg+xxc*n,p+1);
}
else if(n>10) {
p=xchg+n/2*xxc;
g.drawLine(p-1,ychg-1,p-1,ychg+yyc*n);
g.drawLine(p+xxc+1,ychg-1,p+xxc+1,ychg+yyc*n);
p=ychg+n/2*yyc;
g.drawLine(xchg,p-1,xchg+xxc*n,p-1);
g.drawLine(xchg,p+yyc+1,xchg+xxc*n,p+yyc+1);
}
// Texte explicatif
if(n<10) {
p=ychg+n*yyc+yyc;
g.drawLine(0,p+4,xxFen,p+4);
miniTexte(g,xchg-xxc,ychg+n*yyc+yyc);
}
}
public void actionPerformed(ActionEvent evt){
String act=evt.getActionCommand();
if (act=="Quitter") dispose();
else if (act=="Info") { info.show(); }
else if (act=="fermerBD") {info.dispose(); }
else
{ // Changement ligne, colonne, diagonale ...
int i;
for(i=0; i=xchg)&&(y>=ychg)) {
x=(x-xchg)/xxc; y=(y-ychg)/yyc;
if ((x>=0)&&(x=0)&&(y=n) i=i-n;
j=(j==0)?n-1:j-1;
}
return c;
}
// Deuxième méthode pour construire des carrés d'ordre impair
static int [][] cImpair2(int n) {
int c[][]=new int[n][n], a[][]=new int[n][n];
int i,j,jj,k;
// Premier ligne du carré initial: mettre n/2 sur la première case et
// ajouter 2 pour passer à chaque case suivante.
for(i=0, k=n/2; i=n) i=i-n;
j=j-1; if(j<0) j=n-1;
}
return c;
}
// Quatrième méthode pour construire des carrés d'ordre impair
static int [][] cImpair4(int n) {
int m=(n-1)/2;
if(2*m+1 != n) return null;
int c[][]=new int [n][n];
int i0,j0,d,i,j,k,kk,vp,vi;
i0=m; j0=0; d=1; vi=1; vp=2;
for(k=0; k=2*m+1) s=s-2*m-1;
r=(r==0)?2*m:r-1;
}
*/
s=1; // indice ligne du carré (2m+1)x(2m+1)
r=m-1; // indice colonne
for(rr=0, v=-3; rr<(2*m+1); rr++) {
for(ss=0; ss<(2*m+1); ss++) {
// -1 en ligne, +1 en colonne
s=(s==0) ? 2*m : s-1;
r=(r==2*m) ? 0 : r+1;
v+=4;
// Suivant lignes du haut, milieu(presque) ou bas
lux = (s<=m) ? L : (s==m+1 ? U : X);
if((s==m || s==m+1) && r==m) lux=1-lux;
for(k=0; k<4; k++) {
i=2*s+yy[lux][k];
j=2*r+xx[lux][k];
c[i][j]=v+k;
}
}
// Avant la collision
s+=2; if(s>=2*m+1) s=s-2*m-1;
r=(r==0)?2*m:r-1;
}
return c;
}
// Construction d'un carré d'ordre pair (méthode pour n>=6)
static int [][] cPair(int n) {
// utilise:
// la constante c4
// les méthodes: cPAir, cImpair, complement, isoLiDi, symetrieLigne
if(n<6) { return c4;}
// ta, tb, tc, td sontdes carrés d'ordre n/2
// ta ne contient que des 0 et des 3; ta et tc sont complémentaires
// tb ne contient que des 1 et des 2; tb et td sont complémentaires
// cm est un carré magique d'ordre n/2; cn est symétrique-ligne de cm
// Le carré est | ta tb | | ca cm |
// (n/2)^2 * | | + | |
// | tc td | | cs cs |
int nn=n/2, n2=nn*nn;
int ta[][], tc[][];
int tb[][], td[][], tt[][];
tb = new int[nn][nn];
tc = new int[nn][nn]; tc = new int[nn][nn];
// m2=nb.de 2 par ligne dans tb; m1= nb.de 1 dans tb
// m3=nombre de 3 par ligne dans ta;
// à vérifier: 3*m3+m2 = nn
// Générer ta et tc
int m3=nn/2, d3=nn-m3;
ta = isoLiDi(m3,d3,nn,3,0); tc = complement(ta,nn,3);
// Générer tb et td
int m2=2*nn-3*m3,m1=nn-m2; // dans tb
m2=nn-m2;m1=nn-m1; // dans td
int d2=nn-m2,d1=nn-d2;
td = isoLiDi(m1,d2,nn,1,2); tb = complement(td,nn,3);
// Un carré magique,et son "symétrique ligne"
int cm[][], cc[][];
if(nn%2==0) cm=cPair(nn); else cm=cImpair(nn);
int cs[][] = symetrieLigne(cm,nn);
// Carré complet
int i,ip,j,jp, c[][] = new int [n][n];
for(tt=ta, cc=cm, ip= 0, jp= 0, i=0; i=n) j-=n;
t[i][j]=vp;
}
// va pour les autres positions de la ligne i
for( ; ml=n) j-=n;
t[i][j]=va;
}
}
return t;
}
static int[][] complement( int a[][], int n, int vc) {
// Construit le complément du carré a
// c est rempli de haut en bas d'après les lignes de a, utilisées
// de bas en haut
// si a[i][j]==v, alors c[n-1-i][j]==vc-v
int i,j,ii, c[][] = new int[n][n];
// c est rempli de haut en bas; les lignes de a de bas en haut
for(i=0, ii=n-1; i v2 par rapport à ligne ii de a
for(j=0; j