TDM n°2 : Manipulez les Listes avec adresse !
Posté le 04/07/2018 18:00
Le Tuto Du Mercredi [TDM] est une idée qui fut proposée par Ne0tux. Voici le principe : un mercredi sur deux, nous postons un petit tutoriel sur l'Utilisation de la calculatrice, le Transfert, la Programmation, ou encore la Conception de jeu ! En voici donc la deuxième édition ! (une édition bien grosse !)
Manipulez les Listes avec l'adresse d'un expert ! (BASIC)
Niveau : ★ ★ ★ ☆ ☆
Les listes sont des suites de valeur que l'on appelle via la fonction List. Celles-ci sont visible dans le menu STAT de la calculatrice. Elles sont très pratiques et souvent utilisées pour des suites logiques de variables, des sauvegardes de jeu, du DrawStat et bien plus encore. Nous allons donc explorer les techniques à connaître pour profiter du potentiel des Listes !
Partie I : Initialiser une liste
Il existe plusieurs manières d'initialiser des listes. Il est préférable de toutes les connaître pour choisir la bonne méthode en fonction de vos besoins ! La première méthode, la plus évidente, est celle-ci :
{1, 5, 3} → List 1
Dans cet exemple, j'attribue respectivement les valeurs 1, 5 et 3 dans les cases 1, 2 et 3 de la liste 1. Cela effacera tout le contenu de la liste 1 pour le remplacer par ces trois valeurs.
/!\ Attention : le premier index d'une liste en Basic Casio n'est pas 0 mais 1. Vous rencontrerez une Memory Error si vous tentez de rentrer un nombre en List1[0]. Vous verrez plus tard à quoi sert List 1[0] en réalité.
3 → Dim List 1
Cette méthode est redoutablement efficace. Elle réinitialise la liste en lui attribuant une nouvelle dimension : autrement dit, cette ligne me donnera une liste de 3 cases. Chaque case se voit attribuer la valeur 0. En quelques octets, vous pourrez donc remplir une centaine de cases de zéros aisément. Cela vous permet aussi d'anticiper les Dim Error, puisque vous saurez précisément jusqu'où s'étend votre liste.
"MALISTE1" → List 1 [0]
« Quoi ? On peut mettre des chaînes de caractères dans une liste ? À l'indice 0, qui plus est ?! » Alors. Laissez-moi vous expliquez cette méthode : une liste peut avoir un nom. Oui, un nom, donc une chaîne de caractères. Et, ce nom, sachez qu'il est contenu dans la case 0 de la liste. Vous pouvez le voir dans le menu STAT :
En employant cette commande, vous donnez donc un nom à la liste. Attention toutefois à ne pas dépasser les 8 caractères. Si cette liste contient déjà des valeur, cette méthode n'affectera pas le contenu. En revanche, si la liste est vide, cette méthode attribuera la valeur 0 à la case 1. Autrement dit, c'est une excellente méthode pour vérifier si votre liste est vide ou non en évitant le Dim Error. Pour plus de sûreté, vous pouvez aussi vérifier que votre Liste a les dimensions attendues.
"MYLIST" → List 6 [0]
If List 6 [1] != 0 And Dim List 6 = 5: Then //Si la première case n'égale pas zéro, c'est que la liste était déjà remplie. Ma liste est aussi censée faire 5 cases.
// Donc... Tout va bien.
Else //Sinon, ça pue.
« Error : No List. »
Stop
IfEnd
//Le même code, un peu optimisé :
"M" → List 6 [0
If List 6 [1 : Then
// Tout va bien
Else
« Error : No List. »
Stop
IfEnd
Sachez que vous pouvez également appeler une liste
par son nom plutôt que par son indice :
1 → List "MALISTE" [1]
3→Dim List "MALISTE"
etc.
Il existe encore d'autres méthodes moins répandues, comme celle-ci :
Seq(X^2, X, 1, 10, 1) → List 1
La description de la fonction
Seq( se trouve ici. Elle permet de rentrer une séquence de nombres dans une liste. La fonction prend les arguments suivants :
Seq( Expression/Fonction mathématique à exécuter, Variable utilisée pour la fonction, Première valeur de la variable à utiliser, Dernière valeur de la variable, Le pas (de 1 en 1, de 2 en 2, de 0,55 en 0,55...) ) → List 1
Dans mon exemple, je remplis donc dix cases avec les résultats de la fonction f(x) = x², en partant de x=1 jusqu'à x=10 et en allant de 1 en 1. J'aurai donc cette liste comme résultat :
{1, 4, 9, 16, 25, 36, 49, 64, 81, 100}
En résumé, cette fonction
génère une liste à partir d'une expression dépendant d'une variable.
{1, 3, 5, 15}
Il est aussi possible d'écrire une liste sans l'attribuer. Cette ligne remplira en fait la List Ans, ce qui est utile si vous manipulez une liste pour un court moment (comme un Drawstat). Vous pouvez appeler la List Ans de la même manière que les autres listes, à condition bien sûr qu'elle ne soit pas vide.
Partie II : Le calcul listique
Parce que
listique rime avec
balistique, ce chapitre pourrait faire frémir certains d'entre vous. Rassurez-vous jeunes gens, le calcul listique n'est pas très dur à comprendre. Suivez-moi !
Pour commencer, voici un exemple de calcul listique :
List 1 [2] + List 1 [3] → List 6[1]
Ici, rien de bien compliqué ! On se sert des cases des listes exactement de la même manière que des variables. J'additionne la valeur de la case 2 de la liste 1 avec la valeur de la case 3 de la liste 1 pour attribuer le résultat à la case 1 de la liste 6. Du point de vue de la forme, ça serait la même chose que « A + B → C ».
15 + List 1 → List 1
// ou encore
15 + {1, 3, 5} → List 1
« Heu... »
Mais non ! Tout va bien ! Cette ligne assez particulière ajoute 15 à l'ensemble des valeurs de la liste 1. Autrement dit, j'aurai ce résultat :
{16, 18, 20}
À partir de là, vous pouvez tout envisager : additions, soustractions, multiplications, divisions.
Mais c'est là que ça devient encore plus tordu !
List 1 + List 2 → List 3
//ou bien
{12, 5, 6} + {20, 0, -10} → List 3
Vous ne rêvez pas : il est également possible de faire des calculs avec des listes entières ! Attention toutefois ; ces listes
doivent IMPÉRATIVEMENT avoir la même dimension, autrement c'est l'erreur fatale. Cette méthode permet donc d'additionner chaque case une à une, comme indiqué dans ce schéma :
À partir de là, je peux vous montrer comment faire une liste de valeurs complexes, utiles pour stocker des coordonnées :
{10, 12, 4, 5, 0} + i {2, 3, 10, 0, 12} → List 1
Sachez aussi que vous pouvez faire des conditions avec des listes ! On plonge encore plus dans le délire !
{25,10,0,-85,-2,2,100000, -1} → List 1
List 1 < 0 → List 2
Cette deuxième ligne permet de faire vérifier une condition sur toutes les valeurs de la List 1. Autrement dit, cette deuxième ligne renvoie une liste de booléens. « 0 » si la condition demandée et fausse, « 1 » si cette dernière est vraie. List 2 contient donc ceci :
{0,0,0,1,1,0,0,1}
Si vous ne comprenez pas, ça reviendrait à faire la même chose que ce code :
For 1 → A To Dim List 1
If List 1 [A] < 0 : Then
1 → List 2 [A]
Else 0 → List 2 [A]
IfEnd
Next
Puissant, hein ?
Partie III : Optimiser, économiser, compresser.
Dans cette partie, nous allons parler d'une chose essentielle, nécessaire même, en Basic Casio : l'optimisation.
Il est important de savoir qu'une liste, ça prend de la place. Écrire une suite de nombres dans la code à attribuer à une liste, ça prend de la place aussi. Nous allons voir comment gagner / économiser des octets lorsqu'on utilise des listes.
1) Chaque case a un poids.
Sachez que lorsque vous attribuez un réel à une case, celle-ci occupera 12 octets dans la mémoire de la calculatrice. Un nombre complexe, quant à lui, occupera 24 octets ! Voici un bout de code qui pèse 24 octets :
"Je suis une banane !!!"
Ce n'est pas négligeable. Donc, lorsque vous stockez des coordonnées pour votre
Drawstat, plutôt que d'occuper 24 octets par points (soit en complexes, soit en ayant deux listes pour les abscisses et les ordonnées), il existe une technique pour n'en prendre que 12 par points. Vous êtes prêts ?
{10, 12, 4, 5, 0} + i * {2, 3, 10, 0, 12} → List 1 //24 octets par cases.
{10.02, 12.03, 4.10, 5.00, 0.12} → List 1 //12 octets par cases.
//En plus optimisé :
{10.02, 12.03, 4.1, 5, .12} → List 1
L'astuce consiste à stocker l'abscisse de chaque point dans la partie entière du nombre et l'ordonnée dans la partie fractionnaire. Il faut cependant partir du principe que les ordonnées de vos points sont comprises entre 0 et 99. Rien ne vous empêche d'intervertir les deux. Pour ensuite extraire les valeurs de vos cases, vous pouvez faire ceci :
Int List 1 //toutes les parties entières des valeurs
100 Frac List 1
// ou encore :
E2 Frac List 1 //toutes les parties fractionnaires des valeurs
Ensuite, dans d'autres cas, vous n'avez que des petites valeurs à stocker, comme des suites de 0 et de 1 ou bien des chiffres compris entre 0 et 9. Par exemple, mettons que j'aie des caractéristiques de base à distribuer à mon héros dans un RPG, chacune comprise entre 0 et 9. Avec 6 caractéristiques, par exemple, voici ce qu'on serait tenté de faire dans l'immédiat :
{2, 2, 4, 5, 6, 7} → List 1
// Dans l'ordre : PV, Attaque, Défense, Attaque Spé, Def. Spé, Vitesse.
Cette liste occupera 72 octets dans la mémoire de votre calculatrice. Voici maintenant ce que vous pourriez faire :
224567 → List 1 [1]
Non seulement ces informations ne prendront que 12 octets dans la liste, mais en plus vous économisez des octets en n'écrivant pas les accolades et les virgules. Pour récupérer chaque valeur individuellement, vous pouvez avoir recours à cette formule :
MOD(Int (A/10^(n-1)),10)
Cette dernière vous donnera le nième chiffre de A. Je ne vais pas
rentrer dans les détails de cette formule. Poursuivons notre chemin !
Enfin, si vous n'avez plus besoin d'une liste de valeurs, alors ne la laissez pas prendre de la place inutilement sur votre mémoire. N'oubliez donc jamais
cette commande :
ClrList 1
2) Il n'y a pas de « petites » optimisations !
Depuis le début de ce topic, j'ai fait en sorte d'écrire « proprement » chaque ligne de code, c'est à dire de ne pas y faire d'optimisations étranges. Il y a une chose que l'on peut faire en Basic Casio, qui pourtant serait intolérable dans un quelconque langage de programmation : se passer des accolades, crochets et parenthèses finales. À partir de maintenant, ne faites plus :
{10, 12, 4, 5, 0} + i * {2, 3, 10, 0, 12} → List 1
Mais faites :
{10, 12, 4, 5, 0} + i {2, 3, 10, 0, 12 → List 1
De même, ne faites plus :
10 * Int (List 1 [2] + List 1 [3]) → List 6[1]
Mais faites :
10Int (List 1 [2] + List 1 [3 → List 6[1
Je sais. C'est moche, mais on gagne des octets, eh !
Pour plus d'informations, consultez cette page.
3) Soyez malin, soyez radin !
Ne laissez jamais passer une occasion de gagner de la place. Mettons que vous vouliez hardcoder (écrire directement dans le code) une liste comme celle-ci :
{10, 12, 14, 15, 10, 12, 13, 20, 10, 12} → List 1
C'est l'occasion d'utiliser le calcul listique pour gagner de la place ! En avant, toutes !
10 + {0, 2, 4, 5, 0, 2, 3, 10, 0, 2 → List 1 // 7 octets gagnés !
Ou bien une liste comme ça :
{420, 150, 980, 1000, 10 000, 122, 540} → List 1 // avant
10{42, 15, 98, E2, E3, 12.2, 54 → List 1 //après !
Poussons le vice !
{10, 15, 8, 6, 12, 13, 11, 11, 7, 7} → List 1 //Avant...
6+{4, 9, 2, 0, 6, 7, 5, 5, 1, 1 → List 1 //Après...
//Toutes mes valeurs sont comprises entre 0 et 9 ! Alors...
4920675511 → List 1 [1
//Pour retrouver le nième chiffre...
6 + MOD(Int (List 1 [1]/10^(n-1)),10)
// Vous remarquerez que cette dernière ligne peut paraître lourde, mais elle représente un gain de place conséquent quand elle est appliquée sur plusieurs variables de ce type.
Partie IV : Application directe.
1) Faire une sauvegarde de jeu.
Dans beaucoup de jeux différents, il est nécessaire de sauvegarder des données de jeu : un score, des caractéristiques, une avancée de quête, des accomplissements... On évitera de laisser ces données dans les variables alphanumériques qui pourraient très facilement être changées par un autre programme ou par l'utilisateur. On pourrait décider de stocker ces données à sauvegarder dans une liste, ce qui est judicieux, mais il y a toujours le risque que le joueur efface ces données par inadvertance. Il existe une solution assez sure pour effectuer une sauvegarde de jeu :
la fonction File.
Le réglage List File disponible dans Shift → Menu (Set up)
Saviez-vous que vous avez accès en réalité à 156 listes différentes ? Vous avez en fait 6 fichiers de liste (appelées ListFiles) différents. Vous travaillez avec le fichier 1 par défaut. Voici comment s'en servir :
File 2 //Exploite le deuxième ListFile.
{1, 2, 45 → List 1 //Vous remplissez une liste de valeurs dans le ListFile 2
File 1 //Revient au premier ListFile
ClrList //Efface toutes les listes du ListFile 1, mais pas des autres !
Voici donc un exemple d'application directe, dans le cas où les données à sauvegarder se situent dans List 5 sur le fichier 1.
//Quand j'effectue une sauvegarde :
List 5 //la liste 5 du fichier 1 va dans la List Ans qui est universelle.
File2 //Je me mets sur le fichier 2
List Ans → List 1 //Je copie la List Ans dans la List 1 du fichier 2
File1 //Je reviens au fichier 1 pour continuer.
[…]
//Lorsque je quitte le jeu :
ClrList //J'efface tout le fichier 1
Stop
//Quand je reprends la partie :
File 2
"S" → List 1[0]
If Not List 1[1 : Then
"Aucune sauvegarde disponible."◢
Stop
IfEnd
List 1
File 1
List Ans → List 5
Une autre application : Un
Super Drawstat.
[...]
D = 2 ⇒ {.1,5.03,2.08,10.08,12.15 → List 6 //Ceci est un premier sprite à afficher pour un combat : le monstre.
[…]
{4.04, 5.04, 6.03, 15.03, 16.04, 17.04, 17.14, 12.19, 9.19, 4.14, 4.04 → List 4 //Un deuxième sprite, le joueur.
//Puis on dessine.
Augment(15+List 4, 80+List 6) // J'assemble les deux listes en modifiant leurs valeurs
1 → Tθmin
Dim List Ans → Tθmax
Graph(X,Y)=(Int List Ans[T], 100 Frac List Ans[T
Il existe également un tutoriel pour réaliser des effets de particules, réalisé par
Ninestars. Il est assez complexe et fait appel à une utilisation assez poussée des listes. Si vous avez suivi ce tutoriel jusqu'au bout, il ne devrait pas y avoir de problème ! Le
lien se trouve ici.
Liens utiles
Le précédent TDM : Créez de magnifiques écrans-titre pour vos jeux !
Le Jeu du Mois : le retour ! N'oubliez pas de voter !
Savoir manipuler le
Super Drawstat, une méthode de dessin puissante !
Mettez vos nouvelles connaissances à l'usage avec
ce tutoriel sur les effets de particules .
Si vous connaissez mal les fonctions utilisées :
Seq(,
List,
File,
Augment(,
ClrList,
Frac.
Citer : Posté le 04/07/2018 18:13 | #
Super tutoriel ! Je ne connaissais moi-même pas tous les détails.
Seulement si la valeur qu'on avait stocké dans la première case de la liste n'est pas 0 ! C'est tout l'intérêt d'utiliser cette case comme sentinelle.
On peut aussi écrure "MYLIST"→List 1.
Et tu as oublié un truc crucial, c'est manipuler des listes par leur nom !
"TRUC"→List "TRUC" // Une *tuerie* !
Citer : Posté le 04/07/2018 18:23 | #
"TRUC"→List "TRUC" // Une *tuerie* !
Je n'ai pas tout à fait compris comment tu t'en sers. Ta première ligne n'est pas tout à fait juste : elle provoque une erreur dimension si aucune liste ne se nomme "TRUC" !
Citer : Posté le 04/07/2018 18:41 | #
Ah oui, pardon. La première ligne permet d'accéder à une liste par son nom, quand elle existe.
La seconde est beaucoup plus intéressante, elle choisit une liste vide et la nomme "TRUC". Ensuite tu peux t'en servir partout dans le programme sous ce nom sans avoir à connaître son numéro !
Citer : Posté le 04/07/2018 21:02 | #
La seconde est beaucoup plus intéressante, elle choisit une liste vide et la nomme "TRUC". Ensuite tu peux t'en servir partout dans le programme sous ce nom sans avoir à connaître son numéro !
Sérieux ? Je ne connais pas cette astuce
Vitesse des fonctions en Basic Casio | 7 days CPC | Casio Universal Wiki | Tutoriel Basic Casio
>>> Give me a click Brother <<< >>> Teste mon générateur de mots nouveaux <<<
>>> Random Youtube Video <<<
Citer : Posté le 04/07/2018 21:03 | #
Hé hé, et attends, t'as pas tout vu. Renommer une liste !
Citer : Posté le 04/07/2018 21:22 | #
Je le rajouterai plus tard, alors. Ce soir je n'ai pas trop envie. Merci de l'info, Lephé !
Ajouté le 04/07/2018 à 23:01 :
Note à moi-même :
– Rajouter l'astuce made in Lephé.
– Double vérification de liste : Le Dim et la case 1.
Citer : Posté le 05/07/2018 00:34 | #
Vraiment sympa ce tutoriel !!
Citer : Posté le 05/07/2018 11:24 | #
Une excellente idée que de parler des listes !
Citer : Posté le 05/07/2018 11:34 | #
Merci ! L'idée vient plutôt du reste de l'équipe qui m'a proposé de réaliser un tutoriel là-dessus.
Citer : Posté le 05/07/2018 12:31 | #
J'avoue lire à chaque fois le «TDM» en «Tour De Magie», et le titre du tuto s'accorde là bien à cette lecture, pas trop mal au moins.
Mais sinon beau tuto Drak ! Qui couvre pas mal de choses… Je me demande parfois si certaines astuces (typiquement les «allocations dynamiques» dans les listes) sont des features ou des conséquences juste assez magiques et heureuses du fonctionnement du Basic…
Citer : Posté le 05/07/2018 13:32 | #
Super tuto !!
J'ai une question peut on remplacer
par
{List 1[5],List 1[2],List1[15]} + {List 2[4],List 2[1],list 2[14]}→List 3
merci d'avance
Citer : Posté le 05/07/2018 13:35 | #
@Nehmardy : Merci beaucoup ! C'est vrai qu'il y a un côté "Tour de Magie" !
@Shadow : Bien sûr ! Il est tout à fait possible de remplacer les valeurs par des variables, dont les cases de liste. Après, je me demande ce que tu as derrière la tête avec cet exemple ?
Citer : Posté le 05/07/2018 13:44 | #
Ah oui, autre astuce pour les octets, il existe des opcodes List1 à List6 utilisés par les vieux modèles, qui permettent d'accéder au premières listes en sauvegardant (il me semble) un octet.
Citer : Posté le 05/07/2018 13:46 | #
Pour simplifier l'interaction des armes dans mes phase de combat
la list 1contient mes capacités
la liste 2,les capacités de l'arme utilisée
{List 1[1],list 1[2],list 1[3],list 1[4],list 1[5]} +{list 2[1],list 2[2],...list2[5]} → list 3
For 1→A to 5
List 3 [A] = List 1[A] ⇒0→List 3[A]
Next
Citer : Posté le 05/07/2018 13:47 | #
Bonjour,
Je ne sais plus à quel occasion mais j'avais eu besoin de faire
{2+3T,5+2T->list 1
et en fait je n'avais ps à mettre en dur les valeurs et je pouvais par exemple décalé le graphique en changeant la valeur de T.
et j'ai reussi a faire une rotation avec les drawstats. Je m'explique
{1+i,i-1,-1-i,1-i->list 3
'on tourne de π~card~ quart
e^(iπ/4)*list 3 ->list 3
'on cenvertit en x,y
rep liste 3-> liste 1
im liste 3-> liste 2
'plus qu'a fait le draw stat et on a un beau carré avec une rotation de 45°
Citer : Posté le 05/07/2018 19:49 | #
Ton exemple ne fonctionne pas Shadow, on peut malheureusement pas faire {List 1[1]}->List 2
T'es obligé de passer par une boucle For ou des variables alphanumériques intermédiaires
Vraiment un super tutorial Drak ! Encore une fois j'ai bien aimé ton écriture, en plus tu t'appuies sur des exemples, avec beaucoup de liens pour en savoir plus sur une fonction par exemple.
Tu as certainement développé tous les aspects des listes, c'est complet bien joué.
J'ai sourie quand j'ai lu "calcul listique" haha ! J'aime bien quand j'invente des mots et que c'est repris plus tard, merci de m'avoir cité
En effet c'est une bonne astuce Et7f3 (bordel comment on prononce ça ) ! Personnelement je préfère garder en mémoire la liste inchangée. Dans ton exemple tu modifies la List 3, donc si tu veux réutiliser cette liste plus tard sans la modification tu dois la réinitialiser, donc j'aurai fait :
e^(iπ/4)*list 3
GraphXY=(ReP List Ans, ImP List Ans)
Avce un Super DrawStat tant qu'a faire
Citer : Posté le 05/07/2018 20:21 | #
Ah... ok merci Ninestars
Citer : Posté le 06/07/2018 01:29 | #
Question, du coup. Je suis en train d'essayer tout un tas de manipulations contre-natures sur les noms de liste. Est-il possible, par un moyen quelconque, d'utiliser les fonctions Str___ (telles que StrSrc, StrLeft, StrMid, StrLwr...) sur des noms de Listes (List A [0]) ?
Citer : Posté le 06/07/2018 07:13 | #
Non, par contre on peut stocker le nom de la liste dans une Str et inversement donc en passant par une Str on peut achever tous les résultats dont tu parles.
Citer : Posté le 06/07/2018 09:19 | #
Bonjour 9*
Oui après c'est un détail ou on stocke (je peux stocker dans une liste 4 et effacé) et n'oublie pas que pour tout z ∈ C* z est inversible et l'inverse de (e^(iπ/4))^-1=e^(-iπ/4) (propriété de l'exponentielle)
on peux donc tout-a-fait faire
'on tourne de π~card~ quart
e^(iπ/4)*list 3 →list 3
'on zoom par un facteur 2
2list3→list3
'on cenvertit en x,y
rep liste 3→liste 1
im liste 3→liste 2
'plus qu'a fait le draw stat et on a un beau carré avec une rotation de 45°
'et on remet la liste3 comme à l'origine
.5e^(-iπ/4)*list 3 →list 3
@Drak on peux réinitialiser une liste avec 0→list 1 (il me semble)
@Drak déjà tu fais pas la double vérification dans les deux exemples et aussi ces vérifications sont des indices d'une liste corrompue mais en aucun cas tu certifie l'authenticité: il faut tester toutes les cases (ou automatiquement réaffecter à chaque fois toutes les valeures)
H-S: mon pseudo et un rétro rétro-acronyme (au départ c'est un générateur de pseudo aléatoire) se prononce iti (comme le film E-T) sept (bah ou comme 7 le chiffre porte bonheur romain) et eftrois (mon appart de rêve est un f3)
donc tu peux m'appeler itisepteftrois.