program carre_magique;
uses wincrt;
type mat = array [1..19,1..19] of integer ;
{ Remarquer qu'une indexation de 0 à 18 rendrait possible l'utilisation de la fonction "mod" au lieu de la fonction
F définie plus loin. }
var N, D : integer ; A : mat;
procedure lecture (var N : integer ; var P : integer );
begin write ('Carrés magiques de coté impair avec des entiers consécutifs positifs.');
write ('Nombre de lignes et de colonnes: ');
repeat
readln (N)
until odd (N); {seule une valeur impaire est acceptée}
write ('Valeur de départ: ');
readln (P)
end ;
procedure ecriture (M : mat ; N, P : integer );
{ Affichage d'une matrice de N lignes et P colonnes }
var I, J : integer ;
begin
for I := 1 to N do
begin
for J := 1 to P do
write (M[I, J] : 4 );
writeln { passage à la ligne}
end
end ;
function f (X, N : integer ) : integer ;
{F est construite pour donner un résultat entre 1 et N dans tous les cas, on peut bien sûr se contenter de : "si
X<N alors X sinon X-N ", mais indexer le tableau de 0 à n-1 permet d'utiliser "mod" et donc de se dispenser de F }
begin if X < 1 then F := F(X + N ,N)
else if X > N then F := F(X - N,N)
else F := X
end;
procedure construc (N, D : integer ; var A : mat ); {D est la valeur initiale, N la dimension du carré}
var I, J, X : integer ; {I , J sont les coordonnées de la case courante }
begin for I := 1 to N do for J := 1 to N do A [I, J] := 0; {Initialisation nécessaire}
I := (N div 2) + 1 ; J := I-1;
for X := 0 to (N*N) -1 do
begin if A[F(I+1, N), F (J+1, N)] = 0
then begin I := F (I+1, N); J := F (J+1, N) end
else repeat I := F (I+2, N) until A[I, J] = 0;
{ Si la case suivante est vide, alors la case courante devient cette case-là.}
A[I, J] := X + D
end; { D est la valeur de départ }
end;
begin
lecture (N, D);
construc (N, D, A);
ecriture (A, N, N);
writeln ('La somme vaut : ', (N*(N*N-1) div 2) + N*D )
end.