Le vrai problème n’est pas de savoir si les machines pensent, mais de savoir si les hommes pensent - B.F. Skinner
La question de savoir si un ordinateur peut penser n'est pas plus intéressante que celle de savoir si un sous- marin peut nager - Edgar W. Dijkstra
Ceci n’est pas un dérèglement de votre téléviseur. Nous contrôlons tout, nous savons tout, et les phénomènes paranormaux que vous constatez sont dus au fait que vous êtes passés dans… la quatrième dimension (musique angoissante : « tintintin… »).
Oui, enfin bon, avant d’attaquer la quatrième, on va déjà se coltiner la deuxième.
Une seule ne suffisait-elle pas déjà amplement à notre bonheur, me demanderez-vous ? Certes, répondrai-je, mais vous allez voir qu’avec deux (et davantage encore) c’est carrément le nirvana. Prenons le cas de la modélisation d’un jeu de dames, et du déplacement des pions sur le damier. Je rappelle qu’un pion qui est sur une case blanche peut se déplacer (pour simplifier) sur les quatre cases blanches adjacentes.
Avec les outils que nous avons abordés jusque là, le plus simple serait évidemment de modéliser le damier sous la forme d’un tableau. Chaque case est un emplacement du tableau, qui contient par exemple 0 si elle est vide, et 1 s’il y a un pion. On attribue comme indices aux cases les numéros 1 à 8 pour la première ligne, 9 à 16 pour la deuxième ligne, et ainsi de suite jusqu’à 64.
Arrivés à ce stade, les fines mouches du genre de Cyprien L. m'écriront pour faire remarquer
qu'un damier, cela possède 100 cases et non 64, et qu'entre les damiers et les échiquiers, je me suis
joyeusement emmêlé les pédales. A ces fines mouches, je ferai une double réponse de prof :
Reprenons. Un pion placé dans la case numéro i, autrement dit la valeur 1 de Cases(i), peut bouger vers les cases contiguës en diagonale. Cela va nous obliger à de petites acrobaties intellectuelles : la case située juste au-dessus de la case numéro i ayant comme indice i-8, les cases valables sont celles d’indice i-7 et i-9. De même, la case située juste en dessous ayant comme indice i+8, les cases valables sont celles d’indice i+7 et i+9.
Bien sûr, on peut fabriquer tout un programme comme cela, mais le moins qu’on puisse dire est que cela ne facilite pas la clarté de l’algorithme. Il serait évidemment plus simple de modéliser un damier par… un damier !
L’informatique nous offre la possibilité de déclarer des tableaux dans lesquels les valeurs ne sont
pas repérées par une seule, mais par deux coordonnées.
Un tel tableau se déclare ainsi :
Tableau Cases(7, 7) en Numérique
Cela veut dire : réserve moi un espace de mémoire pour 8 x 8 entiers, et quand j’aurai besoin de l’une de ces valeurs, je les repèrerai par deux indices (comme à la bataille navale, ou Excel, la seule différence étant que pour les coordonnées, on n’utilise pas de lettres, juste des chiffres).
Pour notre problème de dames, les choses vont sérieusement s’éclaircir. La case qui contient le pion est dorénavant Cases(i, j). Et les quatre cases disponibles sont Cases(i-1, j-1), Cases(i-1, j+1), Cases(i+1, j-1) et Cases(i+1, j+1).
Il n’y a aucune différence qualitative entre un tableau à deux dimensions ( i, j ) et un tableau à une dimension ( i * j ). De même que le jeu de dames qu’on vient d’évoquer, tout problème qui peut être modélisé d’une manière peut aussi être modélisé de l’autre.
Simplement, l’une ou l’autre de ces techniques correspond plus spontanément à tel ou tel problème, et facilite donc (ou complique, si on a choisi la mauvaise option) l’écriture et la lisibilité de l’algorithme. Une autre remarque : une question classique à propos des tableaux à deux dimensions est de savoir si le premier indice représente les lignes ou le deuxième les colonnes, ou l’inverse. Je ne répondrai pas à cette question non parce que j’ai décidé de bouder, mais parce qu’elle n’a aucun sens.
« Lignes » et « Colonnes » sont des concepts graphiques, visuels, qui s’appliquent à des objets du monde réel ; les indices des tableaux ne sont que des coordonnées logiques, pointant sur des adresses de mémoire vive. Si cela ne vous convainc pas, pensez à un jeu de bataille navale classique : les lettres doivent-elles désigner les lignes et les chiffres les colonnes ? Aucune importance ! Chaque joueur peut même choisir une convention différente, aucune importance ! L’essentiel est qu’une fois une convention choisie, un joueur conserve la même tout au long de la
Si vous avez compris le principe des tableaux à deux dimensions, sur le fond, il n’y a aucun problème à passer au maniement de tableaux à trois, quatre, ou pourquoi pas neuf dimensions. C’est exactement la même chose. Si je déclare un tableau Titi(2, 4, 3, 3), il s’agit d’un espace mémoire contenant 3 x 5 x 4 x 4 = 240 valeurs. Chaque valeur y est repérée par quatre coordonnées.
Le principal obstacle au maniement systématique de ces tableaux à plus de trois dimensions est que le programmeur, quand il conçoit son algorithme, aime bien faire des petits gribouillis, des dessins immondes, imaginer les boucles dans sa tête, etc.
Or, autant il est facile d’imaginer concrètement un tableau à une dimension, autant cela reste faisable pour deux dimensions, autant cela devient l’apanage d’une minorité privilégiée pour les tableaux à trois dimensions (je n’en fais malheureusement pas partie) et hors de portée de tout mortel au-delà. C’est comme ça, l’esprit humain a du mal à se représenter les choses dans l’espace, et crie grâce dès qu’il saute dans l’hyperespace (oui, c’est comme ça que ça s’appelle au delà de trois dimensions).
Donc, pour des raisons uniquement pratiques, les tableaux à plus de trois dimensions sont rarement utilisés par des programmeurs non matheux (car les matheux, de par leur formation, ont une fâcheuse propension à manier des espaces à n dimensions comme qui rigole, mais ce sont bien les seuls, et laissons les dans leur coin, c’est pas des gens comme nous).
Écrivez un algorithme remplissant un tableau de 6 sur 13, avec des zéros.
Quel résultat produira cet algorithme ?
Tableau X(1, 2) en Entier
Variables i, j, val en Entier
Début
Val ← 1
Pour i ← 0 à 1
Pour j ← 0 à 2
X(i, j) ← Val
Val ← Val + 1
j Suivant
i Suivant
Pour i ← 0 à 1
Pour j ← 0 à 2
Ecrire X(i, j)
j Suivant
i Suivant
Fin
Quel résultat produira cet algorithme ?
Tableau X(1, 2) en Entier
Variables i, j, val en Entier
Début
Val ← 1
Pour i ← 0 à 1
Pour j ← 0 à 2
X(i, j) ← Val
Val ← Val + 1
j Suivant
i Suivant
Pour j ← 0 à 2
Pour i ← 0 à 1
Ecrire X(i, j)
i Suivant
j Suivant
Fin
Quel résultat produira cet algorithme ?
Tableau T(3, 1) en Entier
Variables k, m, en Entier
Début
Pour k ← 0 à 3
Pour m ← 0 à 1
T(k, m) ← k + m
m Suivant
k Suivant
Pour k ← 0 à 3
Pour m ← 0 à 1
Ecrire T(k, m)
m Suivant
k Suivant
Fin
Mêmes questions, en remplaçant la ligne :
T(k, m) ← k + m
par
T(k, m) ← 2 * k + (m + 1)
puis par :
T(k, m) ← (k + 1) + 4 * m
Soit un tableau T à deux dimensions (12, 8) préalablement rempli de valeurs numériques. Écrire un algorithme qui recherche la plus grande valeur au sein de ce tableau.
Écrire un algorithme de jeu de dames très simplifié. L’ordinateur demande à l’utilisateur dans quelle case se trouve son pion (quelle ligne, quelle colonne). On met en place un contrôle de saisie afin de vérifier la validité des valeurs entrées. Ensuite, on demande à l’utilisateur quel mouvement il veut effectuer : 0 (en haut à gauche), 1 (en haut à droite), 2 (en bas à gauche), 3 (en bas à droite).
Si le mouvement est impossible (i.e. on sort du damier ), on le signale à l’utilisateur et on s’arrête là . Sinon, on déplace le pion et on affiche le damier résultant, en affichant un « O » pour une case vide et un « X » pour la case où se trouve le pion.
Tableau Truc(5, 12) en Entier
Debut
Pour i ← 0 à 5
Pour j ← 0 à 12
Truc(i, j) ← 0
j Suivant
i Suivant
Fin
Cet algorithme remplit un tableau de la manière suivante:
X(0, 0) = 1
X(0, 1) = 2
X(0, 2) = 3
X(1, 0) = 4
X(1, 1) = 5
X(1, 2) = 6
Il écrit ensuite ces valeurs à l’écran, dans cet ordre.
Cet algorithme remplit un tableau de la manière suivante:
X(0, 0) = 1
X(1, 0) = 4
X(0, 1) = 2
X(1, 1) = 5
X(0, 2) = 3
X(1, 2) = 6
Il écrit ensuite ces valeurs à l’écran, dans cet ordre.
Cet algorithme remplit un tableau de la manière suivante:
T(0, 0) = 0
T(0, 1) = 1
T(1, 0) = 1
T(1, 1) = 2
T(2, 0) = 2
T(2, 1) = 3
T(3, 0) = 3
T(3, 1) = 4
Il écrit ensuite ces valeurs à l’écran, dans cet ordre.
Version a : cet algorithme remplit un tableau de la manière suivante:
T(0, 0) = 1
T(0, 1) = 2
T(1, 0) = 3
T(1, 1) = 4
T(2, 0) = 5
T(2, 1) = 6
T(3, 0) = 7
T(3, 1) = 8
Il écrit ensuite ces valeurs à l’écran, dans cet ordre. Version b : cet algorithme remplit un tableau de la manière suivante:
T(0, 0) = 1
T(0, 1) = 5
T(1, 0) = 2
T(1, 1) = 6
T(2, 0) = 3
T(2, 1) = 7
T(3, 0) = 4
T(3, 1) = 8
Il écrit ensuite ces valeurs à l’écran, dans cet ordre.
Variables i, j, iMax, jMax en Numérique
Tableau T(12, 8) en Numérique
Le principe de la recherche dans un tableau à deux dimensions est strictement le même que dans un tableau à une dimension, ce qui ne doit pas nous étonner. La seule chose qui change, c'est qu'ici le balayage requiert deux boucles imbriquées, au lieu d'une seule.
Debut
...
iMax ← 0
jMax ← 0
Pour i ← 0 à 12
Pour j ← 0 à 8
Si T(i,j) > T(iMax,jMax) Alors
iMax ← i
jMax ← j
FinSi
j Suivant
i Suivant
Ecrire "Le plus grand élément est ", T(iMax, jMax)
Ecrire "Il se trouve aux indices ", iMax, "; ", jMax
Fin
Variables i, j , posi, posj, i2, j2 en Entier
Variables Correct, MoveOK en Booléen
Tableau Damier(7, 7) en Booléen
Tableau Mouv(3, 1) en Entier
Le damier contenant un seul pion, on choisit de le coder à l'économie, en le représentant par un tableau de booléens à deux dimensions. Dans chacun des emplacements de ce damier, Faux signifie l'absence du pion, Vrai sa présence.
Par ailleurs, on emploie une méchante astuce, pas obligatoire, mais bien pratique dans beaucoup de situations. L'idée est de faire correspondre les choix possibles de l'utilisateur avec les mouvements du pion. On entre donc dans un tableau Mouv à deux dimensions, les déplacements du pion selon les quatre directions, en prenant soin que chaque ligne du tableau corresponde à une saisie de l’utilisateur. La première valeur étant le déplacement en i, la seconde le déplacement en j. Ceci nous épargnera par la suite de faire quatre fois les mêmes tests.
Debut
Choix 0 : pion en haut à droite
Mouv(0, 0) ← -1
Mouv(0, 1) ← -1
Choix 1 : pion en haut à droite
Mouv(1, 0) ← -1
Mouv(1, 1) ← 1
Choix 2 : pion en bas à gauche
Mouv(2, 0) ← 1
Mouv(2, 1) ← -1
Choix 3 : pion en bas à droite
Mouv(3, 0) ← 1
Mouv(3, 1) ← 1
Initialisation du damier; le pion n’est pour le moment nulle part
Pour i ← 0 à 7
Pour j ← 0 à 7
Damier(i, j) ← Faux
j suivant
i suivant
Saisie de la coordonnée en i ("posi") avec contrôle de saisie
Correct ← Faux
TantQue Non Correct
Ecrire "Entrez la ligne de votre pion: "
Lire posi
Si posi >= 0 et posi <= 7 Alors
Correct ← vrai
Finsi
Fintantque
Saisie de la coordonnée en j ("posj") avec contrôle de saisie
Correct ← Faux
TantQue Non Correct
Ecrire "Entrez la colonne de votre pion: "
Lire posj
Si posj >= 0 et posj <= 7 Alors
Correct ← Vrai
Finsi
Fintantque
Positionnement du pion sur le damier virtuel.
Damier(posi, posj) ← Vrai
Saisie du déplacement, avec contrôle
Ecrire "Quel déplacement ?"
Ecrire " - 0: en haut à gauche"
Ecrire " - 1: en haut à droite"
Ecrire " - 2: en bas à gauche"
Ecrire " - 3: en bas à droite"
Correct ← Faux
TantQue Non Correct
Lire Dep
Si Dep >= 0 et Dep <= 3 Alors
Correct ← Vrai
FinSi
FinTantQue
i2 et j2 sont les futures coordonnées du pion. La variable booléenne MoveOK vérifie la validité de ce
futur emplacement
i2 ← posi + Mouv(Dep, 0)
j2 ← posj + Mouv(Dep, 1)
MoveOK ← i2 >= 0 et i2 <= 7 et j2 >= 0 et j2 <= 7
Cas où le déplacement est valide
Si MoveOK Alors
Damier(posi, posj) ← Faux
Damier(i2, j2) ← Vrai
Affichage du nouveau damier
Pour i ← 0 à 7
Pour j ← 0 à 7
Si Damier(i, j) Alors
Ecrire " O ";
Sinon
Ecrire " X ";
FinSi
j suivant
Ecrire ""
i suivant
Sinon
Cas où le déplacement n’est pas valide
Ecrire "Mouvement impossible"
FinSi
Fin