/*tp carrés magiques
  Laure Gonnord, nov 2004*/

#include <stdio.h>
#define N 20

int demande_carre(int t[N][N])
{
  int i,j,n,res;
  printf("Donnez l'ordre du carré \n");
  scanf("%d",&n);
  
  for (i=0;i<n;i++)
    {
      for (j=0;j<n;j++)
	{
	  printf("case %d,%d =",i+1,j+1); /*décalage !*/
	  scanf("%d",&res);
	  t[i][j] = res;
	}
    }
  /*je fais passer l'ordre*/
  return n;
}

void affiche_carre(int t[N][N],int n)
{
  int i,j;
  for (i=0;i<n;i++)
    {
      for (j=0;j<n;j++)
	{
	  printf("%d ",t[i][j]);
	}
      printf("\n"); /*saut de ligne*/
    }
}

/*répond 0 si pas presque magique, 1 sinon*/
int est_presque_magique(int t[N][N], int n)
{
  int i,j;
  int diag1 = 0; /*somme diagonale 1*/
  int diag2 = 0; /*somme diagonale 2*/
  int ligne[n]; /*ligne[j] contiendra la somme de la colonne j*/
  int colonne[n]; /*colonne[i] contiendra la somme de la ligne i*/

  /*mise à 0 des cases des tableaux ligne et colonne*/
  for (i=0;i<n;i++)
    {
      colonne[i]=0;
      ligne[i]=0;
    }

  /*calcul des cases des tableaux ligne et colonne*/
  for (i=0;i<n;i++)
    {
      for (j=0;j<n;j++)
	{
	  ligne[j] = ligne[j] + t[i][j];
	  colonne[i] = colonne[i] + t[i][j];
	  if (i == j) {diag1 = diag1 + t[i][j];} /*si sur première diag*/
	  if (i == n-j-1) {diag2 = diag2 + t[i][j];}
	} 
    }

  /*comparaison des valeurs relatives des sommes lignes/colonnes*/
  if (diag1 != diag2) {printf("Carre pas presque-magique\n");return 0;}
  for (i=0;i<n;i++)
    {
      if ( (ligne[i]!=diag1) || (colonne[i] !=diag1))
	{
	  printf("Carré pas presque-magique %d\n",i);
	  return 0;
	}
    }
  /*si on arrive ici c'est que toutes les cases sont égales donc ...*/

  printf("Carré presque-magique\n");
  return 1;
}

int rentre_candidat_magique(int t[N][N])
{
  int i,j,n,res;
  int deja_vu[N];/*la case i aura 1 si i a déjà été vu*/
  printf("Donnez l'ordre du carré \n");
  scanf("%d",&n);
  
  /*cas où N est trop petit*/
  if (n*n+1>N) {return -1;};
  /*mise à 0 du tableau deja_vu*/
  for (i=0;i<n*n+1;i++)  
    {
      deja_vu[i] = 0;
    }
  
  for (i=0;i<n;i++)
    {
      for (j=0;j<n;j++)
	{
	  /*objectif : mettre un nb qui convient dans t[i][j]*/
	  scanf("%d",&res);
	  while (res<1 || res >n*n || deja_vu[res]==1)
	    {
	      scanf("%d",&res);
	    }
	  /*a ce stade on a un élément qui convient*/
	  t[i][j] = res;
	  deja_vu[res] = 1;
	}
    }
  /*je fais passer l'ordre*/
  return n;
}

/*on suppose que n est impair*/
/*attention aux indices*/
void genere_magique(int t[N][N], int n)
{
  int x, xi, xj; /*nombre x, position i et j dans la grille*/
  int k = n/2;
  
  /*placement du chiffre 1*/

  xi = k+2;
  xj = k+1;
  t[xi-1][xj-1] = 1;

  /*placement des chiffres par ordre croissant*/
  for (x=2; x<=n*n; x++)
    {
      if ((x-1) %n !=0)
	{
	  xi = 1 + (xi%n);
	  xj = 1 + (xj%n);
	  t[xi-1][xj-1] = x;
	}
      else
	{
	  xi = 1 + ((xi+1) %n);
	  /*colonne inchangée*/
	  t[xi-1][xj-1] = x;
	}
    }
}

int main (void)
{
  int carre[N][N];
  int carre2[N][N];
  int carre4[N][N];
  int n,r;
  
  n = demande_carre(carre);
/* Donnez l'ordre du carré  */
/* 3 */
/* case 1,1 =1 */
/* case 1,2 =2 */
/* case 1,3 =3 */
/* case 2,1 =4 */
/* case 2,2 =5 */
/* case 2,3 =6 */
/* case 3,1 =7 */
/* case 3,2 =8 */
/* case 3,3 =9 */

  affiche_carre(carre,n);
/* 1 2 3  */
/* 4 5 6  */
/* 7 8 9  */

  carre2[0][0] = 1;
  carre2[0][1] = 2;
  carre2[0][2] = 3;
  carre2[1][0] = 4;
  carre2[1][1] = 2;
  carre2[1][2] = 0;
  carre2[2][0] = 1;
  carre2[2][1] = 2;
  carre2[2][2] = 3;

  affiche_carre(carre2,3);
  printf("\n");
  r = est_presque_magique(carre2,3);
/* 1 2 3  */
/* 4 5 6  */
/* 7 8 9  */
/*        */
/* 1 2 3  */
/* 4 2 0  */
/* 1 2 3  */
/* Carré presque-magique */


  /*test de est_presque_magique*/
  n = rentre_candidat_magique(carre);
  if (n != -1)
    {
      if (est_presque_magique(carre,n) ==1)
	{
	  printf("Carré Magique \n");
	}
    }
/* Donnez l'ordre du carré  */
/* 3 */
/* 4 */
/* 9 */
/* 2 */
/* 3 */
/* 5 */
/* 7 */
/* 8 */
/* 1 */
/* 6 */
/* Carré presque-magique */
/* Carré Magique  */


  /*construction auto puis verif*/
  genere_magique(carre4,3);
  affiche_carre(carre4,3);
  if (est_presque_magique(carre,n) ==1) 
    {printf("Carré Magique \n");}
/* 4 9 2  */
/* 3 5 7  */
/* 8 1 6  */
/* Carré presque-magique */
/* Carré Magique */
  
  return 0;
}

