Forum Solarus-Games francophone

Jeux amateurs => Programmation => Discussion démarrée par: Arca le 16 Juin 2014 à 22:30

Titre: [GM8.1 / GML] Tri de plusieurs listes en fonction d'une autre
Posté par: Arca le 16 Juin 2014 à 22:30
Bonsoir chers solarussiens.

Me voilà en présence d'un problème qui est relativement embêtant. Ce n'est pas faute d'avoir essayé plusieurs méthodes, il m'est arrivé de penser avoir trouver la bonne, mais il s'avère un peu plus tard que ce n'est pas le cas quand j'ajoute du contenu.

Voici concrètement ce que je voudrais réaliser : une sorte de "Pokédex" pour ranger les différents dragons disponibles du jeu facebook Dragon City. Seulement voilà, impossible d'associer les informations affichées à l'écran avec le dragon concerné.

Pour être un peu plus précis, je copie la liste contenant le nom des dragons (global.dragonName) dans une liste temporaire (tempList), puis je trie global.dragonName dans l'ordre alphabétique grâce à une fonction de base (ds_list_sort), et j'essaye de trier toutes les autres en récupérant le nouvel index de la liste triée... Enfin en gros, un p'tit bordel.

Je vous passe la fonction que j'ai créé au cas où, vu comment j'explique super bien.

var tempList, i, tempValue, tempIndex; // déclaration de variables

// copie de la liste contenant le nom des dragons dans une liste temporaire
tempList = ds_list_create();
ds_list_copy(tempList,global.dragonName);

// tri de la liste d'origine dans l'ordre alphabetique
ds_list_sort(global.dragonName,argument0);

// parcourt de toutes les autres listes
for (i = 0 ; i <= (ds_list_size(tempList)-1) ; i += 1) // tant que i est inférieur à la taille de la liste (= du nombre total de dragons)
{    
   // récupère le nouvel index grâce à la valeur de la liste temporaire
   tempValue = ds_list_find_value(tempList,i);
   tempIndex = ds_list_find_index(global.dragonName,tempValue);
   
   // déplace les informations de l'index d'origine vers le nouvel index pour chaque liste
   tempValue = ds_list_find_value(global.dragonPictureName,i);
   ds_list_insert(global.dragonPictureName,tempIndex,tempValue);
   if (i < tempIndex) ds_list_delete(global.dragonPictureName,i);
   else ds_list_delete(global.dragonPictureName,i+1);
   
   tempValue = ds_list_find_value(global.dragonDescription,i);
   ds_list_insert(global.dragonDescription,tempIndex,tempValue);
   if (i < tempIndex) ds_list_delete(global.dragonDescription,i);
   else ds_list_delete(global.dragonDescription,i+1);
   
   ... (y'en a plein d'autres !)
   
   tempValue = ds_list_find_value(tempList,i);
   ds_list_insert(tempList,tempIndex,tempValue);
   if (i < tempIndex) ds_list_delete(tempList,i);
   else ds_list_delete(tempList,i+1);
}


Si vous ne comprenez pas le problème, n'hésitez pas à me le dire que j'explique un peu mieux ! :)
Titre: Re : [GM8.1 / GML] Tri de plusieurs listes en fonction d'une autre
Posté par: Neo2 le 16 Juin 2014 à 23:05
La solution la plus simple serait de :
- Copier la liste des noms
- La trier dans l'ordre souhaité
- Garder cette copie

Et pour accéder aux informations :
- Récupérer l'index du dragon dans la liste d'origine grâce à son nom
- Récupérer les informations du dragon via cet index

Idéalement, la liste "triée" devrait même contenir directement les index dans la liste d'origine :p
Titre: Re : [GM8.1 / GML] Tri de plusieurs listes en fonction d'une autre
Posté par: Arca le 16 Juin 2014 à 23:24
Ah tiens tu n'es pas porté disparu toi ? :)

Merci pour ta réponse, mais ce que tu viens d'expliquer, je crois que ça correspond à ce que je fais en fait :

Citation- Récupérer l'index du dragon dans la liste d'origine grâce à son nom

tempValue = ds_list_find_value(tempList,i);
tempIndex = ds_list_find_index(global.dragonName,tempValue);


Ou alors je n'ai pas compris ta solution.
Titre: Re : [GM8.1 / GML] Tri de plusieurs listes en fonction d'une autre
Posté par: Neo2 le 16 Juin 2014 à 23:26
Je parlais plutôt de récupérer l'index à partir du nom lors de l'affichage des informations, et les récupérer a ce moment là, plutôt que de trier toutes les différentes listes ^^
Titre: Re : [GM8.1 / GML] Tri de plusieurs listes en fonction d'une autre
Posté par: Wouf le 17 Juin 2014 à 00:10
Ca remonte tout ça ^^'

Bon alors déjà une première chose: il est délicat de modifier une liste pendant qu'on la parcourt (on risque de modifier les infos dont on aura besoin lors d'une itération ultérieure).

Ensuite, c'est plutôt lourd de trier plusieurs listes (perfs), alors qu'une seule suffirait. Si tu tiens absolument à garder plusieurs listes, pourquoi ne pas simplement créer une liste de positions et t'arranger pour maintenant la correspondance élément à élément avec la liste qui te sert d'ordre (alphabêtique en l'occurence). Ce qui te fait deux listes à réorganiser. Ensuite, tu parcours les éléments de la liste à positions et tu les utilises comme position pour récupérer les éléments depuis les autres listes (que tu n'as plus besoin de trier).

EDIT1: c'est la solution postée par Néo2 entre-temps :P
EDIT2: surtout que récupérer un élément par sa valeur est beaucoup plus coûteux que par sa position. (pour ceux qui me gueuleraient dessus, sachez que les listes Gml sont implémentées par des tableaux).

Sinon, je me demande s'il n'y a pas moyen de grouper toutes les infos relatives aux dragons dans un type d'objet et de créer une liste d'instances vers ces objets. Ainsi, tu n'as qu'une seule liste. Mais ça ne t'arrange pas pour le tri vu que tu ne disposes que de deux tris: croissant et décroissant qui se fera sur les id d'instance dans le cas présent :/

La meilleure solution que je vois passerait par une dll faite maison (un langage tel que le C permet de grouper toutes les données des dragons au sein d'une même structure et de trier selon l'une des caractéristiques via callback comparateur).

En fait, tout dépend du nombre d'ordre de tri que tu aimerais. Si tu ne veux qu'un tri alphabêtique en plus de l'ordre par défaut (id spécifique aux dragons commençant à 0 jusque ton nombre de dragons-1), alors je te conseille de passer par un conteneur map (nomDuDragon->idDuDragon). Je m'explique:
A) création des structures de données
B ) Tri par id
C) Tri par ordre alphabêtique (croissant comme décroissant)

Ca devrait fonctionner à condition que le conteneur map accepte le texte comme clef.
Si tu veux trier par type, ça sert à rien d'utiliser un conteneur map puisque plante correspond à plusieurs Pokémon --> lequel choisir ? En fait, la relation caractéristique <-> id doit être bijective :)