Un escargot dans une matrice !!!
Titre un peu surprenant je vous l’accorde 🙂
Dans le cadre de mon projet SimImmuno II, j’ai besoin de connaĂ®tre quelles sont les cellules qui avoisine une cellule donnĂ©e. Pour cela, chaque cellule est placĂ©e dans une matrice (tableau Ă deux dimensions !).
Le but de l’algorithme est de parcourir cette matrice Ă Â partir d’un point donnĂ©e (la position de la cellule) en tournant autour comme un escargot.
Petit exemple illustré :
Pour ne penser qu’Ă l’algorithme oublions les histoires de cellule. Prenons un tableau de 100×100 avec un point de rĂ©fĂ©rence aux coordonnĂ©es 50;50.
Nous voulons juste rĂ©cupĂ©rer les coordonnĂ©es des positions autour de notre point de rĂ©fĂ©rence qu’empruntera notre escargot (Il suffira après de tester si aux coordonnĂ©es visitĂ©es il y a ou pas la prĂ©sence d’une cellule).
Dans notre cas, les coordonnĂ©es Ă visiter sont : 50;49, 51;49, 51;50, 51;51, 50;51, 49;51, 49;50, 49;49, etc…
Si l’on illustre ça par le schĂ©ma :
On peut observer que l’on avance de x cases suivant notre avancement par multiple de 2 : 2 fois 1case, 2fois 2cases, 2fois 3cases, 2fois 4 cases, etc… L’on appellera cela le nombre de pas qui s’incrĂ©mentera tous les 2 avancement. Puis l’on « tourne » : Haut->Droit->Bas->Gauche->Haut->etc…
Pour coder ca en c#, dĂ©finissions tout d’abord une Ă©numĂ©ration pour la direction :
1 | public enum Direction { Haut, Bas, Gauche, Droit, } |
Nous allons maintenant créer une fonction Tourner qui prend en argument la direction précédente et retourne la nouvelle direction de cette maniere : Haut->Droit->Bas->Gauche->Haut->etc.. Ce qui nous ammene à écrire :
1 2 3 4 5 6 7 8 9 10 11 | public Direction Tourner(Direction origine) { if (origine == Direction.Haut) return Direction.Droit; else if (origine == Direction.Bas) return Direction.Gauche; else if (origine == Direction.Droit) return Direction.Bas; else if (origine == Direction.Gauche) return Direction.Haut; else return Direction.Haut; } |
Maintenant, il nous faut une fonction nous permettant de nous renvoyer les coordonnĂ©es de la prochaine position en fonction de la position prĂ©cĂ©dente, du nombre de pas et de la direction (a noter que les positions sont matĂ©rialisĂ©s par l’objet Point possĂ©dant les propriĂ©tĂ©s X et Y) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public Point CalculerNewPosition(Point _origine, Direction _direction) { int x = _origine.X; int y = _origine.Y; switch (_direction) { case Direction.Haut: return new Point(x,(y - 10)); case Direction.Bas: return new Point(x,(y + 10)); case Direction.Droit: return new Point((x + 10), y); case Direction.Gauche: return new Point((x - 10), y); default: return new Point(x,y); } } |
Une fois tout cela crĂ©Ă©, il nous reste plus qu’a crĂ©er la fonction principale du programme composĂ©e de 3 boucles :
- La 1er, boucle de 0 au nombre de pas (nommé jump) et calcule les prochaines positions.
- La 2eme, boucle de 0 a 2 et appelle la 1er boucle, incrémente jump puis appelle la fonction Tourner
- Enfin la dernière, de 0 a X oĂą X le point d’arrĂŞt.
Le code donne :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | Point pointRef = new Point(50, 50); int jump = 1; Direction direct = Direction.Haut; Point lastPoint = pointRef; for (int a = 0; a < 20; a++) { for (int avc = 0; avc < 2; avc++) { for (int jmp = 0; jmp < jump; jmp++) { Point newPoint = CalculerNewPosition(lastPoint, direct); // NOUVEAU POINT DANS newPoint ! // Inserer le code voulu ! lastPoint = newPoint; } direct = Tourner(direct); } jump++; } |
Et voila le tour est jouĂ©Â ! Si l’on s’amuse a mettre le code :
1 | g.DrawLine(new Pen(new SolidBrush(Color.Black)), lastPoint, newPoint); |
Ă l’endroit de InsĂ©rer le code voulu ! nous obtenons :
Facile non ? 🙂
y_nk
Merci, je viens de retrouver ce (vieux) post encore bien rĂ©fĂ©rencĂ©, et je l’ai portĂ© sur flash a des proportions dĂ©fiant les limites de flash. Je posterai bientot un article dessus 🙂