A la base de l'algorithme, il y a les objets "CcaseNB"
représentant chacun une case de l'échiquier. Pour construire des carrés
magiques, l'algorithme reste le même. Seules, les méthodes
des objets, sur lesquels l'algorithme opère, ont été modifiées.
Le polymorphisme, mis en oeuvre à travers les méthodes virtuelles
du C++, permet de conserver, quel que soit le type de recherche (carré
magique, carré quelconque, parcours utilisant en priorité
les cases excentrées, parcours privilégiant les cases centrales
...) le même algorithme.
CcaseNB propose de nombreuses méthodes publiques mais seulement 4 de
ces méthodes sont utilisées dans l'algorithme de recherche:
virtual bool IsFree(int Index);
virtual int FirstStep(int Src);
virtual int NextStep();
virtual int GetSource();
La première méthode, IsFree(index)
demande à la case visée si elle est libre, c'est à dire s'il est possible
d'effectuer un saut sur cette case. Le paramètre Index
n'existait pas dans l'algorithme standard qui recherchait simplement des chemins
sur l'échiquier. Grâce à Index, la
case peut par avance calculer la somme qui serait obtenue sur la ligne et sur la
colonne si le bond est effectué. Si la ligne est complète (toutes les cases de
la ligne sont occupées) ou si la colonne est complète et que la somme des
Index sur la ligne ou sur la colonne ne vaut pas 260, la case n'est pas libre et
IsFree() retourne false.
Le deuxième méthode FirstStep(Src)
effectue le bond sur la case. Cette méthode retourne la case suivante dans la
liste des possibilités. Cette liste est initialisée en début de programme
pour chaque case. Cette initialisation est réalisée dans le constructeur
spécialisé de la case qui prend en paramètre la position de la case sur
l'échiquier.
La troisième méthode, NexStep() est
appelée pour obtenir de la case courante une autre case de l'échiquier,
lorsque la case retournée par FirstStep(),
ou par NexStep() s'est avérée être
occupée. En effet chaque case proposée en retour de l'une de ces 2 méthodes
est ensuite testée par IsFree(Index).
Le tableau des cases atteignables, à partir d'une case donnée, est
terminée par -1. Lorsque FirstStep() ou NextStep()
retourne -1, GetSource() est appelé.
GetSource retourne la case d'origine
et indique que la case est a nouveau libre (attribut free = true). Il est
important de remarquer que chaque appel de GetSource()
est suivi d'un appel de NextStep().
Ainsi, lorsque le cavalier recule, il arrive sur une case et essaye ensuite la
deuxième possibilité du tableau des destinations possibles de cette case. La
première possibilité ne convient pas car le cavalier vient de reculer. Lorsque
le cavalier recule de la case n, l'arbre complet de tous les chemins possibles a
partir de la case n a été parcouru.
FirstStep fait avancer effectivement
le cavalier et GetSource le fait reculer,
les 2 autres méthodes des cases ne le font pas bouger. Il y a 2 séquences dans
l'algorithme
- FirstStep / IsFree
- NextStep
/ IsFree
L'algorithme, au cœur du contrôle Kmagic, est le suivant :

Il peut être surprenant de ne pas trouver dans l'algorithme ci-dessus un
test indiquant que l'arbre de recherche a été entièrement parcouru.
Cependant, ce test est bien présent. L'algorithme exploite un tableau de
pointeurs de CcaseNB[64]. Au début du
programme, la case du départ est spécialisée. La méthode NextStep()
de cette case indique qu'il n'y a pas de solution lorsque cette dernière
retourne -1. La méthode GetSource()
retourne une case spéciale, la case 64, qui met fin à la boucle de recherche (Save2Do
= true) .
Dans sa structure actuelle, le même algorithme permet de rechercher à la
fois des parcours complets de cavalier sans contraintes particulières, des
parcours complets qui répondent à la contrainte de carré magique ou de carré
semi-magique(1). Il est aussi possible, sans changer l'algorithme, d'imposer
comme but de recherche un carré magique dont la somme des diagonales vaut la
même valeur que les lignes et les colonnes, c'est à dire un carré magique
avec diagonales. Les différents objectifs sont configurables en début de
programme. Ce sont des propriétés du contrôle.
Un contrôle ActiveX a deux modes de fonctionnement : un mode création (design-time)
et un mode exécution (run-time). Pendant la phase de création, les propriétés
du contrôle sont
accessibles à travers une boite de dialogue spécialisée, programmée par le
développeur du contrôle. Ces propriétés sont également accessibles à travers
différentes APIs (Application Program Interface) dans différents langages C++,
Visual Basic ou des langages de script (Visual Basic Script). En mode exécution
le déroulement du programme est paramétré par les propriétés qui ont été
initialisées en mode création.
Certaines propriétés du contrôle Kmagic permettent de modifier
l'objectif de la recherche. Ce n'est pas l'algorithme qui change mais
les objets "CcaseNB" utilisés
par l'algorithme , qui sont modifiés. Comme l'algorithme exploite un tableau
de pointeur de CcaseNB à travers 4 méthodes propres à chaque case, il
faut que ces méthodes soient virtuelles dans la case racine pour que la
méthode correcte de la case spécialisée soit invoquée.
L'initialisation en début de recherche du tableau pcaseNB[] est
assez complexe car la combinatoire n'est pas triviale. Elle est décrite selon 2
axes
De plus, afin de réduire le temps de recherche, il est important de
supprimer dans les méthodes des classes dérivées chaque test dépendant d'un
paramètre (d'une propriété) du contrôle. Ainsi, plus le contrôle possède
de propriétés, plus le nombre de classes est important.
(1) Un carré semi-magique est un carré 8x8 ou chaque quart 4x4 est
lui même magique. Dans ce cas la somme des lignes et des colonnes de chaque
quart vaut 130
|