Backtracking : Les 8 Reines

Le problème des huit reines consiste à positionner 8 reines sur un échiquier afin qu'aucune de ces reines ne puissent en menacer une autre, c'est-à-dire qu'elles ne partagent ni la même ligne, ni la même colonne, ni la même diagonale.

Ce programme initialement réalisé en 1992 donne l'ensemble des solutions.

Version initiale

// problème des huit reines

#include <conio.h>         
#include <stdio.h>
#include <time.h>

typedef int bool;

typedef struct {
  int nb_reines;
  int reineligne[8];
  bool reinecol[8];
  bool reinediagp[15];
  bool reinediags[15];
} Echiquier;

void afficher (Echiquier *echiq)
{
int i;
static n=1;

  printf ("\n----------%d\t",n++);
  for (i=0; i<8; i++)
    printf ("%d-%d ", i+1, echiq->reineligne[i]);
}

bool case_ok (Echiquier *echiq, int ligne, int col)
{
int diagp, diags;

  diagp = ligne + col - 2;
  diags = col - ligne + 7;
  return echiq->reinecol[col-1] && echiq->reinediagp[diagp]
    && echiq->reinediags[diags];
}

void ajouter_reine (Echiquier *echiq, int ligne, int col)
{
  echiq->nb_reines++;
  echiq->reineligne[ligne-1] = col;
  echiq->reinecol[col-1] = 0;
  echiq->reinediagp[ligne + col - 2] = 0;
  echiq->reinediags[col - ligne + 7] = 0;
}

void retirer_reine (Echiquier *echiq)
{
int i;

  echiq->nb_reines--;
  for (i = 0; i < 8; i++)
    echiq->reinecol[i] = 1;
  for (i = 0; i < 15; i++)
    echiq->reinediags[i] = echiq->reinediagp[i] = 1;
  for (i = 0; i < echiq->nb_reines; i++) {
    echiq->reinecol[ echiq->reineligne[i] - 1] = 0;
    echiq->reinediagp [ i + echiq->reineligne[i] -1 ] = 0;
    echiq->reinediags [ echiq->reineligne[i] - i + 6 ] = 0;
  }
}





void pb_reines (Echiquier *echiq)
{
int ligne,col;

  if (echiq->nb_reines == 8)
    afficher (echiq);
  else {
    ligne = echiq->nb_reines +1;
    for (col = 1 ; col <= 8; col++)
      if (case_ok (echiq, ligne, col)) {
        ajouter_reine (echiq, ligne, col);
        pb_reines (echiq);
        retirer_reine (echiq);
      }
  }
}

main ()
{
Echiquier echiquier = {0, {0, 0, 0, 0, 0, 0, 0, 0},
              {1, 1, 1, 1, 1, 1, 1, 1},
              {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
              {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}};

time_t t1,t2;

  t1 = time(NULL);
  pb_reines (&echiquier);
  t2 = time(NULL);
  printf ("temps = %f", difftime(t2,t1));
  return 0;
}


Version révisée pour une meilleure présentation des résultats

// problème des huit reines

#include <stdio.h>
#include <time.h>

typedef struct {
	int nb_reines;
	int reineligne[8];
	bool reinecol[8];
	bool reinediagp[15];
	bool reinediags[15];
} Echiquier;

void afficher (Echiquier *echiq)
{
int i, j;
static int n=1;

	printf ("----------%d\n",n++);
	for (i=0; i<8; i++) {
		for (j=0; j<8; j++)
			if (echiq->reineligne[i] == j+1)
				printf ("Q ");
			else if ((i+j)%2)
				printf ("□ ");
			else
				printf ("■ ");
		printf ("\n");
	}
	printf ("\n");
}

bool case_ok (Echiquier *echiq, int ligne, int col)
{
int diagp, diags;

	diagp = ligne + col - 2;
	diags = col - ligne + 7;
	return echiq->reinecol[col-1] && echiq->reinediagp[diagp]
		&& echiq->reinediags[diags];
}

void ajouter_reine (Echiquier *echiq, int ligne, int col)
{
	echiq->nb_reines++;
	echiq->reineligne[ligne-1] = col;
	echiq->reinecol[col-1] = 0;
	echiq->reinediagp[ligne + col - 2] = 0;
	echiq->reinediags[col - ligne + 7] = 0;
}

void retirer_reine (Echiquier *echiq)
{
int i;

	echiq->nb_reines--;
	for (i = 0; i < 8; i++)
		echiq->reinecol[i] = 1;
	for (i = 0; i < 15; i++)
		echiq->reinediags[i] = echiq->reinediagp[i] = 1;
	for (i = 0; i < echiq->nb_reines; i++) {
		echiq->reinecol[ echiq->reineligne[i] - 1] = 0;
		echiq->reinediagp [ i + echiq->reineligne[i] -1 ] = 0;
		echiq->reinediags [ echiq->reineligne[i] - i + 6 ] = 0;
	}
}





void pb_reines (Echiquier *echiq)
{
int ligne,col;

	if (echiq->nb_reines == 8)
		afficher (echiq);
	else {
		ligne = echiq->nb_reines +1;
		for (col = 1 ; col <= 8; col++)
			if (case_ok (echiq, ligne, col)) {
				ajouter_reine (echiq, ligne, col);
				pb_reines (echiq);
				retirer_reine (echiq);
			}
	}
}

int main ()
{
Echiquier echiquier = {0, {0, 0, 0, 0, 0, 0, 0, 0},
							{1, 1, 1, 1, 1, 1, 1, 1},
							{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
							{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}};

time_t t1,t2;

	t1 = time(NULL);
	pb_reines (&echiquier);
	t2 = time(NULL);
	printf ("temps = %f", difftime(t2,t1));
	return 0;
}

Solutions

92 solutions sont trouvées. En voici une :