Ce document a été produit par HEVEA.
Votre browser peut avoir a être configuré pour afficher correctement certains symboles.
Reportez-vous à la
documentation d'HEVEA.

Licence d'informatique
Module de C/Unix
Projet C

Mots croisés

Jean-Luc Levaire

Décembre 2002

Ce document est disponible sous forme d'un fichier PostScript compressé.





Le but de ce projet est de placer un ensemble de mots sur une grille de taille quelconque. Les mots peuvent être placés soit horizontalement, et ils se lisent alors de gauche à droite, soit verticalement, et ils se lisent de haut en bas. Deux mots peuvent s'intersecter (un mot vertical, un mot horizontal) aux positions où ils possédent des lettres communes. Un mot peut intersecter plusieurs mots. Tout mot placé sur la grille doit être entouré de cases vides, hormis pour les cases où il intersecte un autre mot, et à ses extrémités où les cases en diagonale peuvent être occupées par un autre mot (voir Fig. 1). Tout le problème est de trouver le meilleur placement répondant à un certain critère: taille minimale de la grille englobante, plus grand nombre d'intersections entre mots... ...


Figure 1 : Un exemple de placement pour 4 mots. Les cases en grisé sont celles qui ne peuvent être occupées en raison de la présence du mot hélicoptère.


Lecture de l'ensemble de mots

L'ensemble des mots à placer est contenu dans un fichier texte, dont le nom est passé en paramètre du programme. Le fichier contient un mot par ligne. Les fonctions fopen et fgets permettent d'ouvrir et de lire ligne par ligne un fichier. Les mots sont lus un par un dans un buffer, alloués dynamiquement et insérés dans une liste chaînée. Voici un exemple de programme utilisant ces deux fonctions et imprimant le contenu d'un fichier ligne par ligne.
#include <stdio.h>
#define MAX_LENGTH 80

int main(int argc, char *argv[]) {
  FILE *file;
  char buffer[MAX_LENGTH];
  /* Ouverture du fichier en lecture (¨r¨ pour read */
  /* argv[1] (1er argument) est le nom du fichier   */
  if ((file = fopen(argv[1], "r")) == NULL) {
    fprintf(stderr, "%s: Error opening %s: ", argv[0], argv[1]);
    perror("");
    exit(2);
  }
  /* Lecture d'une ligne */
  while (fgets(buffer, MAX_LENGTH, file))
    printf("%s", buffer);
}

Recherche d'un meilleur placement

La solution triviale pour trouver un meilleur placement est de les parcourir dans leur totalité. Pour cela, on utilise l'algorithme suivant:
  1. Placer le premier mot de la liste à la position (0, 0) horizontalement. La grille G initiale des mots placés est donc réduite à ce mot. Construire une seconde liste L des mots non encore placés;
  2. Pour chaque mot M de la liste L des mots non encore placés:
Le fait qu'un placement soit possible dépend des conditions énumérées dans la section précédente et des mots déjà placées (i.e. la grille courante). Ici on cherchera les intersections du mot avec ceux déjà placés, et pour chaque intersection, on vérifiera si elle est possible par rapport aux mots déjà placés.

Quant au critère d'évaluation d'un placement, on pourra choisir la taille minimale de la grille englobante. L'option -i du programme permet de changer le critère en le plus grand nombre d'intersections de mots.

Structures de données proposées

En plus de la liste des mots, l'algorithme précédent utilise une liste de mots non placés et une grille de mots placés. Nous proposons de représenter une grille de mots placés par un tableau de structures représentant chacune un mot placé, et contenant: Un tableau est alloué dynamiquement au début du programme, avec une longueur égale au nombre de mots lus dans le fichier. Ce tableau représentera la grille courante des mots placés. Une seconde grille est aussi allouée et contiendra le meilleur placement courant. L'ensemble de ces structures est représentée Fig. 2.


Figure 2 : Les structures de données proposées.



Ce document a été traduit de LATEX par HEVEA.