Après la présentation de carré magiques, nous voyons quatre façons d'en construire, qui sont programmées dans l'applet présentée.

I. Introduction

Un carré magique est un carré rempli par des entiers consécutifs à partir de 1, sans répétition et placés de telle sorte que la somme des éléments d'une ligne soit la même pour chaque ligne mais aussi que la somme des éléments chaque colonne soit la même, et que de plus la somme des éléments de chaque diagonale soit cette même somme.
On appelle généralement ordre le nombre de lignes ou de colonnes du carré.

On voit à droite un carré magique d'ordre 3, avec sa somme magique 15 et un carré magique d'ordre 4 avec sa somme magique 34.

Appelons n l'ordre du carré et remarquons que dès que toutes les lignes ont la même somme, notée s , alors la somme de tous les éléments du carré est n*s . On appelle somme magique cette valeur, qui ne dépend pas de n.
Observons que si toutes les colonnes ont la même somme, celle-ci est alors à nouveau s .

     carré d'ordre 3 
    8  1  6 : 15
    3  5  7 : 15
    4  9  2 : 15
    .. .. ..
    15 15 15

     carré d'ordre 4 
    1 15 14  4 : 34
   12  6  7  9 : 34
    8 10 11  5 : 34
   13  3  2 16 : 34
   .. .. .. ..
   34  34  34  34
La somme magique d'un carré magique contenant les entiers consécutifs de 1 à n2 est:                         n (n2+1) / 2

Remarques
Calcul et affichages de carrés magiques

♦ On choisit l'ordre, puis un carré magique est affiché en appuyant sur bouton .
♦ Six méthodes différentes de génération sont utilisées, suivant que l'ordre du carré est un nombre impair, ou un nombre pair, mutltiple de 4 ou multiple de 4 + 2.
♦ Les touches →   ←   ↑   ↓   L   C   D   4   2   permettent de changer les sommes affichées.

II. Constructions d'un carré d'ordre impair

Première méthode

On remplit le carré par les entiers successifs de 1 à n2 de façon particulière: on suit les "pseudo-diagonales ascendantes", en observant les règles:
→ partir du milieu de la première ligne
→ quand on déborde vers le haut, continuer sur la dernière ligne
→ quand on déborde vers la droite haut, continuer sur la première colonne
→ quand une diagonale est remplie, commencer une autre diagonale, par la case immédiatement en dessous
    (voir signe + sur le schéma ci-dessous)
En bref, l'augmentation ou la diminution d'indice se font en calculant modulo n.

Carré d'ordre 5
de 1 à 5 de 6 à 10 de 11 à 10 de 16 à 20 de 21 à 25 Au complet
 - - 1 - -
 - 5 - - -
 4 + - - -
 - - - - 3
 - - - 2 - 
 - - - 8 -
 - - 7 - -
 - 6 - - -
10 - - - -
 + - - - 9 
 - - - -15
 - - -14 +
 - -13 - -
 -12 - - -
11 - - - - 
17 - - - -
 - - - -16
 - - -20 -
 - -19 + -
 -18 - - - 
 -24 - - -
23 - - - -
 - - - -22
 - - -21 +
 - -25 - - 
 17 24  1  8 15
 23  5  7 14 16
  4  6 13 20 22
 10 12 19 21  3
 11 18 25  2  9 

Deuxième méthode

On remplit plusieurs carré successifs, pour assurer l'égalité des sommes en lignes, colonnes et diagonales, et assurer également que les nombres placées dans le dernier soient deux à deux distincts.
On présente la construction d'un carré contenant les entiers de 0 à n2-1 .
→   Pour le premier carré, noté A sur l'exemple ci-dessous, mettre les nombres de 0 à n-1 sur la première ligne, dans un ordre quelconque; puis remplir les lignes suivantes en décalant les éléments d'une ligne de deux positions par rapport à la ligne immédiatement au-dessus.
→   Remplir B à partir de A en multipliant chacun de ses éléments par n .
→   Déduire C de B par une symétrie sur les colonnes, par rapport à la colonne centrale.
→   En faisant tout simplement la somme, éléments par élements des carrés A et C , on obtient D qui est magique (la somme magique est 60 sur l'exemple.

Carré d'ordre 5
A B = 5*A C
déduit de B
D = A + C
est magique
  2  4  1  3  0
  1  3  0  2  4
  0  2  4  1  3
  4  1  3  0  2
  3  0  2  4  1
 10 20  5 15 0
  5 15  0 10 20
  0 10 20  5 15
 20  5 15  0 10
 15  0 10 20  5
  0 15  5 20 10
 20 10  0 15  5
 15  5 20 10  0
 10  0 15  5 20    
  5 20 10  0 15
  2 19  6 23 10
 21 13  0 17  9
 15  7 24 11  3 
 14  1 18  5 22
  8 20 12  4 16 

Remarques
♦   On voit facilement que les lignes et colonnes de A contiennent les entiers consécutifs de 0 à n-1; donc les sommes de ces lignes ou colonnes sont identiques, et valent la somme magique.
♦   Le décalage de 2 d'une ligne à la suivant assurre que la diagonale descendante de A contient aussi ces mêmes entiers.
♦   Les éléments de la diagonale ascendante ne sont pas forcément deux à deux distincts, mais en plaçant sur la première ligne n/2 puis les entiers obtenus en ajoutant 2 (modulo n), on est assuré que la somme des éléments sur la diagonale montante est la somme magique.
♦   Puisque toutes les sommes (lignes colonnes et diagonales) sont identiques pour A, elles le sont aussi pour les carrés B, C et D . Elles le seraient également pour le carré calculé comme somme de A et B .
♦   La présence dans D des entiers consécutifs de n2-1 , donc aussi l'unicité des éléments, est obtenu grâce à la symétrie effectuée entre B et C.

Troisième méthode

Elle ressemble à la première méthode qui place les entiers consécutifs sur des pseudo-diagonales. Cependant cette fois on commence au dessus du milieu du carré (voir ci-contre la position de 1), et quand une pseudo-diagonale est remplie (voir passage de 5 à 6), on commence la suivante deux cases au-dessus.
Les débordements vers le haut ou vers la droite, se traitent de la même façon.

   23  6 19 2 15 
   10 18  1 14 22
   17  5 13 21 9
    4 12 25 8 16
   11 24  7 20 3

III. Construction d'un carré d'ordre pair et multiple de 4

On commence par placer régulièrement les entiers de 1 à n2 (64) sur les lignes, en plaçant les entiers de 1 à n sur la première ligne, ainsi de suite. On constate alors (un peu d'arithmétique le démontre) que la somme des éléments portés par chaque diagonale est la somme magique.

Comme l'ordre est multiple de 4, il est possible d'arriver simplement à obtenir les égalités des sommes d'éléments, par ligne ou colonne, sans jamais toucher aux éléments sur les diagonales.
On commence par effectuer une première série d'échanges pour assurer l'égalité des sommes des éléments de chaque ligne. Puis on effectue une deuxième série d'échanges pour obtenir les égalités des sommes par colonne, tout en conservant la propriété sur les diagonales et sur les lignes.

Voyons cette méthode en 3 étapes, pour un carré d'ordre 8.

Rangement régulier (sommes par diagonales)

Après avoir placé les nombres de 1 à 64, le calcul des sommes par ligne (résultat écrit à droite) permet de voir que certaines lignes ont un déficit par rapport à la somme magique et qu'il existe une ligne présentant un excédent égal à ce déficit. Ainsi la ligne 2 a un déficit de 160, alors que la ligne 7 a un excédent de 160.
Un raisonnement arithmétique simple assure que les lignes ainsi associées sont "symétriques".

                        :    somme  
 1  2  3  4  5  6  7  8 :  36=260-224
 9 10 11 12 13 14 15 16 : 100=260-160
17 18 19 20 21 22 23 24 : 164=260- 96
25 26 27 28 29 30 31 32 : 224=260- 32
33 34 35 36 37 38 39 40 : 292=260+ 32
41 42 43 44 45 46 47 48 : 356=260+ 96
49 50 51 52 53 54 55 56 : 420=260+160
57 58 59 60 61 62 63 64 : 484=260+224

Obtenir l'égalité des sommes par ligne

Pour obtenir les égalités de somme par ligne, on échange des éléments (situés même colonne) entre les lignes symétriques (1 et 8; 2 et 7; 3 et 6; 4 et 5), sans jamais toucher aux éléments placés sur les diagonales.
Une possibilité avec le carré ci-dessus (voir les nombres écrits en gras), est d'échanger 4 éléments par ligne:

  • ligne 1: on échange 2, 3, 6, 7 avec les éléments correspondants, ligne 8
  • ligne 2: on échange 11, 12, 13, 14 avec les éléments correspondants, ligne 7
  • ligne 3: on échange 17, 20, 21, 24 avec les éléments correspondants, ligne 6
  • ligne 4: on échange 25, 26, 31, 32 avec les éléments correspondants, ligne 5
  • remarques:
      → un nombre pair d'échanges est effectué par ligne;
      → les colonnes choisis sont "symétriques"
      → un choix est fait parmi plusieurs possibilités envisageables

    Sur le carré obtenu après ces échanges, on a calculé ci-contre les sommes par colonnes et l'écart de la somme obtenue par rapport à la somme magique est affiché sur la ligne en dessous.
    Ce calcul permet de voir que certaines colonnes ont un déficit par rapport à la somme magique et qu'il existe aussi une colonne présentant un excédent égal à ce déficit. Ainsi la colonne 2 a un déficit de 20, alors que la colonne 7 a un excédent de 20.
    Les colonnes en position symétrique, sont ainsi associées.

       1  58  59   4   5  62  63   8 : 260
       9  10  51  52  53  54  15  16 : 260
      41  18  19  44  45  22  23  48 : 260
      33  34  27  28  29  30  39  40 : 260
      25  26  35  36  37  38  31  32 : 260
      17  42  43  20  21  46  47  24 : 260
      49  50  11  12  13  14  55  56 : 260
      57   2   3  60  61   6   7  64 : 260
     ..  ..  ..  ..  ..  ..  ..  ..
    232 240 248 256 264 272 280 288
    -28 -20 -12  -4  +4 +12 +20 +28 
    

    Obtenir l'égalité des sommes par colonne

    Pour obtenir les sommes par colonnes identiques, on va donc faire des échanges entre les colonnes symétriques (1 et 8; 2 et 7; 3 et 6; 4 et 5), sans jamais toucher aux éléments placés sur les diagonales; le choix de nombres placés la même ligne, conserve la somme de la ligne.

    L'égalité des sommes par colonne est acquise en échangeant 4 éléments par colonne. On a indiqué en gras et souligné, sur le carré ci-dessus à droite, les nombres qui changent de place (échanges entre colonne 1 et 8, ou 2 et 6 ...) pour obtenir le carré ci-contre.
    Exemple: 41, 33, 25 et 17 de la colonne 1 sont respectivement échangés avec 48, 48, 32 et 24, placés colonne 8.

          Un carré magique d'ordre 8
         1  58  62   5   4  59  63   8      
         9  10  54  53  52  51  15  16      
        48  23  19  44  45  22  18  41
        40  39  27  28  29  30  34  33
        32  31  35  36  37  38  26  25
        24  47  43  20  21  46  42  17
        49  50  14  13  12  11  55  56
        57   2   6  61  60   3   7  64
    

    IV. Construction d'un carré d'ordre pair au moins égal à 6

    La méthode ci-dessous permet de construire un carré magique d'ordre n (n pair) à partir d'un carré magique d'ordre moitié n/2. Comme il n'existe pas de carré magique d'ordre 2, la méthode n'est pas appliquable pour n=4. Par contre dès que n est au moins égal à 6, elle est valide.

    Dans les exemples ci-desssous, on a placé les entiers de 0 à n2-1; cela simplifie légèrement la présentation, sans changer la construction. On note p=n/2.

    ♦ On va placer les entiers de 0 à n2-1, ou de 1 à 4p2-1 en respectant les les contraintes:
      → A la moitié de gauche contient seulement les entiers compris entre 0 et p2-1 ou entre 3*p2 et 4p2
      → la moitié de droite contient seulement les entiers compris entre p2 et 3*p2.

    La première idée est de considérer, dans un carré d'ordre n, les quatre sous-carrés d'ordre p=n/2 notés A, B, C, D ci-contre; un exemple de carré 6x6 montre les 4 sous-carrés 3x3 (n=6, p=3).
    ♦ En respectant la contrainte, les sous-tableaux A et C, placés à gauche contiennent les entiers de 0 à 8 et de 27 à 35, et les sous-tableaux de droite contiennent les entiers de 9 à 17 et de 18à 26.

    
        +++++    +++++
        + A +    + B +
        +++++    +++++
    
        +++++    +++++
        + C +    + D +
        +++++    +++++
    
               M
    | 34  0  5   25 18 23
    |  2 31  6   20 22 24
    | 30  8  1   21 26 19
    |
    |  3 35 28   12 17 10
    | 29  4 33   11 13 15
    |  7 27 32   16  9 14
    

    Si on décompose chaque nombre en la somme d'un multiple de p2 et d'un reste, et qu'on éclate chaque partie dans un carré respectif, on obtient les deux carrés ci-contre en bleu, dont la somme est le carré en vert, à droite ci-dessus.
    ♦ On voit que la partie gauche de M1 ne contient que 0 et 27, alors que sa partie droite ne contient que 9 et 18.

              M1
     27  0  0   18 18 18
      0 27  0   18 18 18
     27  0  0   18 18 18
    
      0 27 27    9  9  9
     27  0 27    9  9  9
      0 27 27    9  9  9
    
               M2
    |  7  0  5    7  0  5
    |  2  4  6    2  4  6
    |  3  8  1   21  8  1
    |
    |  3  8  1    3  8  1
    |  2  4  6    2  4  6
    |  7  0  5    7  0  5
    
    De plus Quant à M2, il est constitué de 4 sous-carrés, A2, B2, C2 et D2 tels que

    Si on note u le nombre de fois où 3p2 intervient dans chaque ligne de A1, et v le nombre de fois où 2p2 intervient dans chaque ligne de B1, alors on aura égalité des sommes par lignes et par colonnes de M1 dès que:

    3*u + v = 2*p

    → dans A1:
          3p2 intervient u fois sur chaque ligne
          0 intervient p-u fois sur chaque ligne
    → dans B1:
          2p2 intervient v fois sur chaque ligne
          p2 intervient p-v sur chaques par ligne
     
    → dans C1:
          3p2 intervient p-u fois par ligne
          0 intervient u fois par ligne dans C1
    → dans D1:
          2p2 intervient p-v fois par ligne
          p2 intervient v fois par ligne

    Si on note d le nombre de fois où 3p2 intervient dans la diagonale descendante de A1, et e le nombre de fois où 2p2 intervient dans la diagonale descendane de D1 alors la somme des diagonales de M1 vaut aussi 3p3, dès que:

    3*d + e = 2*p

    3p2 intervient d fois sur la diagonale descendante de A1
    2p2 intervient e fois sur la diagonale descendante de D1
    p2 intervient p-e fois sur la diagonale descendante de D1

    3p2 intervient p-d fois sur la diagonale montante de C1
    0 intervient d fois sur la diagonale montante de C1
    2p2 intervient p-e fois sur la diagonale montante de B1
    p2 intervient e fois sur la diagonale montante de B1

    Une fois obtenu A1 contenant u fois 3p2 par ligne et d fois 3p2 sur la diagonale descendante, on obtient C1 immédiatement. On obtient obtient D1 à partir de B1 de la même façon.

    Obtention de C1 et D1
    → C1 se déduit de A1 en
        inversant l'ordre des lignes et en échangeant 3p2 et 0 dans C1.
        le nombre de 3p2 dans les premières colonnes de M1 est p
        le nombre de 0 dans les premières colonnes de M1 est 0 ou p
       
    → D1 se déduit de B1 en
        inversant l'ordre des lignes et en échangeant 2p2 et p2 dans D1.
        le nombre de 2p2 dans les dernières colonnes de M1 est p
        le nombre de p2 dans les dernières colonnes de M1 est p

    Remarque:
    Si SM(p) est la somme magique du carré magique contenant les entiers de 0 à p2-1, alors

  • SM(2p) = 4p3 - p
  • SM(p) = p(p2-1)/2
  • SM(2p) - 2 SM(p) = 3p3
    Il faut avoir
    la somme d'une colonne de M1 doit être 3p3
    → p fois 3p2 dans chaque colonne de gauche de M1 (A1 et C1)
    → p fois 2p2 et p fois p2 dans chaque colonne de droite de M1 (B1 ou C1).

    V. Programmation

    Voici une programmation en langage Java, qui n'utilise pas les possibilités objet de ce langage.
    Deux carrés constants et une méthode.
    
      final static int c8[][]={{1,63,3,61,12,54,10,56}
                       ,{16,50,14,52,5,59,7,57}
                       ,{17,47,19,45,28,38,26,40}
                       ,{32,34,30,36,21,43,23,41}
                       ,{53,11,55,9,64,2,62,4}
                       ,{60,6,58,8,49,15,51,13}
                       ,{37,27,39,25,48,18,46,20}
                       ,{44,22,42,24,33,31,35,29}};
      final  static int[][] c4 = {{ 1,15,14, 4} 
                         ,{12, 6, 7, 9}
                         ,{ 8,10,11, 5}
                         ,{13, 3, 2,16}};
    
      static int [][] c(int n){
         if(n%2==1) return cImpair2(n);
         else       return cPair(n);
         }
    

    Carrés d'ordre impair: méthode 1

    
      static int [][] cImpair(int n) {
         int c[][]=new int [n][n];
         int i,j,k,m,v;
         i=1; j=n/2-1;
         for(v=0, m=0; m<n; m++) {
            for(k=0; k<n; k++) {
               // -1 en ligne, +1 en colonne
               i=(i==0)?n-1:i-1;
               j=(j==n-1)?0:j+1;
               c[i][j]=++v;
               }
            // Avant la collision
            i+=2; if(i>=n) i=i-n;
            j=(j==0)?n-1:j-1;
            }
         return c;
         }
    

    Carrés d'ordre impair méthode 2

    
      static int [][] cImpair2(int n) {
         int c[][]=new int[n][n], a[][]=new int[n][n];
         int i,j,jj,k;
         // Premiere 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++, k=(k<n-2)?k+2:k+2-n) a[0][i]=k;
         // Décalage de 2 entre une ligne et la précédente
         for(i=1; i<n; i++) {
            for(k=0; k<n; k++) {
              j=(k<n-2)?k+2:k+2-n;
              a[i][k]=a[i-1][j];
              }
            }
         // Carré magique
         for(i=0; i<n; i++)
            for(k=n-1, j=0; j<n; j++, k--)  c[i][j]=1+a[i][j]+n*a[i][k];
         return c;
         }
    

    Carrés d'ordre impair méthode 3

    
      static int [][] cImpair3(int n) {
         int c[][]=new int [n][n];
         int i,j,k,v;
         int j0=n/2, i0=1+j0;
         c[i0][j0]=1;
         for(v=1, i=i0-1, j=j0-1; v<=n*n; ) {
            for(k=0; k<n; k++, v++) {
               i=(i==n-1)?0:i+1;
               j=(j==n-1)?0:j+1;
               c[i][j]=v;
               }
            // A la collision
            i=i+1; if(i>=n) i=i-n;
            j=j-1; if(j<0) j=n-1;
            }
         return c;
         }
    

    Carrés d'ordre multiple de 4

    // Construction d'un carré d'ordre multiple de 4
    
      static int [][] cPair4n(int n) {
         int c[][] = new int[n][n], nn=n/2,p=n/4;
         int i,ii,j,jj,k, aux;
    
         // Les entiers consécutifs
         for(i=0,k=1; i<n; i++) for(j=0; j<n; j++,k++) c[i][j]=k;
         // Assurer égalité des sommes par ligne: p valeurs à échanger
         for(i=0,ii=n-1-i; i<nn; i++,ii--)
            for(k=0,j=nn-1, jj=nn; k<p; k++,j--,jj++) {
               if(i==j) {j--; j++;}  // Ne pas modifier la diagonale
               aux =c[i][j];  c[i][j]=c[ii][j];  c[ii][j]=aux;
               aux=c[i][jj]; c[i][jj]=c[ii][jj]; c[ii][jj]=aux;
               }
         
         // Assurer égalité des sommes par colonnes: p valeurs à échanger
         for(j=0,jj=n-1-j; j<nn; j++,jj--)
            for(k=0,i=0, ii=n-1; k<p; k++,i++,ii--) {
               if(i==j) {i++; ii--;}
               aux =c[i][j];  c[i][j]=c[i][jj];  c[i][jj]=aux;
               aux=c[ii][j]; c[ii][j]=c[ii][jj]; c[ii][jj]=aux;
               }
    
         return c;
         }
    

    Carrés d'ordre : 2 + multiple de 4

    La construction d'un carré d'ordre   4*m + 2 est exposée sur le site Wolfram dont la référence est fournie en fin de texte.
    
      static int [][] cPair4np2(int n) {
         int m=(n-2)/4;
         if(4*m+2 != n) return null;
         
         int c[][] = new int[n][n], nn=n/2,p=n/4;
         int i,j           // indices dans carré d'ordre n=4*m+2
         ,r,s              // indices dans carré d'ordre 2*m+1
            ,rr,ss ,k,v,lux;
         final int L=0,U=1,X=2;   //   L         U         X   
         int xx[][] = new int[][] {{1,0,1,0},{0,0,1,1},{0,1,0,1}}; // delta colonne
         int yy[][] = new int[][] {{0,1,1,0},{0,1,1,0},{0,1,1,0}}; // delta ligne
    
         s=1;          // départ ligne 0 du carré (2m+1)x(2m+1)
         r=m-1;        // colonne milieu
         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;
         }
      
    

    Carrés d'ordre pair

    Nous avons ici la programmation la plus longue. La méthode cPair est récursive; de plus elle utilise le carré constant c4 et appelle les méthodes cImpair, complement, isoLiDi et symetrieLigne
    
      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<nn; i++)
            for(j=0; j<nn; j++) c[i+ip][j+jp]=tt[i][j]*n2+cc[i][j];
         for(tt=tb, cc=cm, ip= 0, jp=nn, i=0; i<nn; i++)
            for(j=0; j<nn; j++) c[i+ip][j+jp]=tt[i][j]*n2+cc[i][j];
         for(tt=tc, cc=cs, ip=nn, jp= 0, i=0; i<nn; i++)
            for(j=0; j<nn; j++) c[i+ip][j+jp]=tt[i][j]*n2+cc[i][j];
         for(tt=td, cc=cs,ip=nn, jp=nn, i=0; i<nn; i++)
            for(j=0; j<nn; j++) c[i+ip][j+jp]=tt[i][j]*n2+cc[i][j];
    
         return c;
         }
      
         
      static int[][] isoLiDi( int p, int q, int n, int vp,int va) {
      // Construction de matrice en 0/1 contenant p fois vp par ligne
      //    et q fois vp sur la diagonale principale
      //    les autres elements contiennent va
      // Le matrice construite est symétrique par rapport au point n/2,n/2:
      //          t[i][j] == t[n-1-i][n-1-j]
      // CONDITION:  (0<p<n && 0<=q<=n)  || (p==0 && q<n)  || (p==n && q==n)
      int t[][] = new int[n][n];
      int i,iip1,j,md, ml;
      
      // p fois vp et n-p fois va par ligne ou diag.princ
      // iip1 vaut 0 ou 1 suivant qu'on place vp sur la diagonale ou non
      // md nombre de vp sur la diagonale; ml nombre de vp par ligne
         for(i=0, md=0; i<n; i++) {
            iip1=0;
            if(md<q) md++; else iip1=1;
            // p fois vp à partir de [i][i]  ou [i][i+1]
            for(ml=0,j=i+iip1; ml<p; ml++,j++) {
               if(j>=n) j-=n;
               t[i][j]=vp;
               }
         // va pour les autres positions de la ligne i
            for(           ; ml<n; ml++,j++) {
               if(j>=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<n; i++, ii--) {
         // ligne i de c: échange v1 <--> v2 par rapport à ligne ii de a
            for(j=0; j<n; j++) c[i][j] = vc-a[ii][j];
            }
         return c; 
         }
      
      static int[][] symetrieLigne(int a[][], int n) {
         int i,j, c[][] = new int[n][n];
         for(i=0; i<n; i++) {
             // ligne i de cs = ligne symétrique de cm
            for(j=0; j<n; j++) c[i][j] = a[n-1-i][j];
            }
         return c;
         }
       
    

    Références