BASIC pas si simple...
Modérateurs : Papy.G, fneck, Carl
BASIC pas si simple...
Au cours de mes différentes saisies de logiciel Basic, je me suis aperçu que de nombreuses astuces en Basic étaient utilisées pour accélérer son fonctionnement!
Rarement documentées, ces utilisations atypiques sont précieuses pour une meilleure programmation, et un gain appréciable.
Il faut savoir que lors de l'exécution d'un programme basic (pour différentes machines):
- Les retours à la line sont gourmands en cycle processeur (ZX81,SPECTRUM)
- L'emplacement de la routine dans un long programme est différent en tête ou en fin de programme (Ti99a)
- Que la nature des variables joue un grand rôle dans le temps de l'exécution des tâches (commande 'def' Amstrad et Spectrum)
- L'appel de routines assembleur est gourmande en temps ("RAND{omize} USR" du Zx81/Spectrum)
Il va sans dire, que les retard d'exécution sont non négligeable lors de l'affichage ou les routines de calcul.
Je vais vous donner quelques astuces, glanées çà et là...
à noter, que même si ce fil ressemble à un monologue pseudo-tutoriel, le but n'est pas de donner des cours de Basic, mais bel et bien de donner une liste de conseils et d'astuces sans prétention aucune.
Re: BASIC pas si simple...
Suppression de lignes:
Soit,
Code : Tout sélectionner
1 LET X=1
2 GOTO 10
5 LET X=0
10 PRINT "RESULTAT : ";
20 IF X=1 THEN PRINT "VRAI"
30 IF X=0 THEN PRINT "FAUX"
20 IF X THEN PRINT "VRAI"
30 IF NOT X THEN PRINT "FAUX"
(lancement par RUN 1 ou RUN 5)
DONNE:
Code : Tout sélectionner
1 LET X=1
2 GOTO 10
5 LET X=0
10 PRINT "RESULTAT : ";("VRAI" AND X)+("FAUX" AND NOT X)
Re: BASIC pas si simple...
Code : Tout sélectionner
1 LET B=0
10 FOR A=1 TO 1000
20 LET B=B+1
30 IF B>500 THEN GOTO 50
40 NEXT A
Remplacé par:
Code : Tout sélectionner
1 LET B=0
10 FOR A=1 TO 1000
20 LET B=B+1
30 IF B>500 THEN NEXT A
40 REM SUITE
Re: BASIC pas si simple...
10 DATA 0,0,0,0,0,0,0
Les '0' peuvent être supprimés sur certains basics.
10 DATA ,,,,,,
Re: BASIC pas si simple...
La gestion des chaînes de caractère est plus lente avec des variables de grande taille!
Préférer les lectures multiples de courtes chaînes.
10 LET A$="1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ"
>> Traitement...
10 LET A$="1234567890ABCDEFG"
traitement...
20 LET A$="HIJKLMNOPQRSTUVWXYZ"
traitement...
Pour avoir une accélération du traitement, il est possible de réduire la chaîne avec retrait de l'information déjà lue.
100 PRINT A$(1)
110 LET A$=A$(2 TO)
120 GOTO 100
affichage data avec la fonction équivalente de A$=right(LEN A$-1) ou MID$(2,LEN A$-1)
Re: BASIC pas si simple...
Code : Tout sélectionner
10 {LET} a=0
20 {LET} b=0
30 {LET} c=0
40 {LET} d=0
50 {LET} e=0
Code : Tout sélectionner
10 {LET} a=0
20 {LET} b=a
30 {LET} c=a
40 {LET} d=a
50 {LET} e=a
Sur Zx81:
10 LET A=0
Encodé en 6 octets.
10 LET A=VAL "0"
Encodé en 4 octets.
Possibilité d'utiliser la fonction CODE (asc sur certains basics)
Re: BASIC pas si simple...
Oubliez définitivement les BIN 00010010 ou &H0023 !
Pratique pour le codage, ils ralentissent l'exécution des routines avec des appels de routines en ROM...
De plus, certaines routines de décodages peuvent boguer et retourner des valeurs fantaisistes (CPC).
Donc, une fois codé, les remplacer par des valeurs converties.
Dans le même genre, évitez les calculs non utiles du style:
Code : Tout sélectionner
10 FOR A=1 TO 1000+8
20 POKE A+255+32,255+12
30 NEXT A
Par contre, pour la ligne 20, ce calcul est répété "1000+8" fois...
Des poignées de secondes perdues à cause d'une paresse intellectuelle, que vous ferai subir aux utilisateurs, à chaque exécution de cette routine.
Re: BASIC pas si simple...
La redondance ! (exemple trouvé dans l'Hebdogiciel!)
Code : Tout sélectionner
10 LET SALLE=INT(RND*5)+1
20 ON SALLE GOSUB 100,110,120,...
50 GOTO 10
100 PRINT "TU ES DANS LA SALLE DU TRESOR"
105 RETURN
110 PRINT "TU ES DANS LA SALLE DE TORTURE"
115 RETURN
120 PRINT "TU ES DANS LA SALLE VERTE"
125 RETURN
130 PRINT "TU ES DANS LA SALLE D'ARMES"
135 RETURN
Quatre fois "TU ES DANS LA SALLE " !
Des GOSUB et des RETURN provocateurs d'embrouilles...
M'énerve de voir ça... Surtout, qu'au bout du compte, il faudra supprimer des salles pour tout faire tenir dans 16k de RAM!
Première chose, tu vires les redondances textuelles...
Code : Tout sélectionner
10 LET SALLE=INT(RND*5)+1
15 PRINT "TU ES DANS LA SALLE ";
20 ON SALLE GOSUB 100,110,120,...
50 GOTO 10
100 PRINT "DU TRESOR"
105 RETURN
110 PRINT "DE TORTURE"
115 RETURN
120 PRINT "VERTE"
125 RETURN
130 PRINT "D'ARMES"
135 RETURN
Code : Tout sélectionner
10 LET S$(1)= "DU TRESOR"
11 LET S$(2)= "DE TORTURE"
12 LET S$(3)= "VERTE"
13 LET S$(4)= "D'ARMES"
100 LET SALLE=INT(RND*5)+1
105 PRINT "TU ES DANS LA SALLE ";S$(SALLE)
Mais! l'initialisation des variables S$(x) mange de la mémoire à l'exécution, car stockée en RAM!
Donc, les informations sont dupliquée dans la mémoire basic et dans la mémoire variable.
Cela encombre l'espace vital du programme, lors de son exécution (memory full en plein programme!).
Donc, cette alternative est plus appropriée:
Code : Tout sélectionner
100 RESTORE 100:FOR SALLE=1 TO INT(RND*5)+1:READ S$:NEXT SALLE:DATA "DU TRESOR", "DE TORTURE",VERTE, "D'ARMES"
105 PRINT "TU ES DANS LA SALLE ";S$
Les retirers donne des octets en plus!
Pour le fun, ça donne ça:
Code : Tout sélectionner
100 RESTORE 50:FOR SALLE=1 TO INT(RND*5)+1:READ S$:NEXT S:PRINT "TU ES DANS LA SALLE ";S$:DATA "DU TRESOR", "DE TORTURE",VERTE, "D'ARMES"
Pour les machines sans FONCTION DATA, Il est toujours possible de tout mettre en une seule REM, et de faire pointer une lecture mémoire sur cette même REM, puis indiquer à la routine une caractère particulier pour la fin de la lecture d'une phrase... mais c'est assez long, car il doit tout lire si la phrase est en fin de REM.
Donc, en début, on mets la taille de la première phrase, puis le texte. Les sauts ce feront de taille en taille de phrase... ce qui est plus rapide.
25,ABCDEFGHIJKLMNOPQRSTUVWXY
26,ABCDEFGHIJKLMNOPQRSTUVWXYZ
5,ABCDE
3,FIN
Donc Phrase 1=X, Phrase 2=X+25,Phrase 3=X+25+26,...
Avec des FOR la localisation de la phrase est plus rapide.
Re: BASIC pas si simple...
opérateur booléen:
AND, OR et NOT.
Rappel:
"OR" (ou) symbolisé par "+" et AND (et) symbolisé par "." [edité car "+"/"." inversés (1+0=1 et 1.0=1)].
N'importe quelle variable peut être utilisée en variable Booléen.
Elle prend souvent la valeur de 0 pour Faux (false) et 1 pour vraie (true)
Sauf, sur certains basic, ou False= -1.
Pour une condition OR, on remplace "OR" par "Si on a * ou * " : A OR B = 1 Si on a A ou B en TRUE (<>0)
Pour une condition AND, on remplace "AND" par "Si on a * et * " : A AND B = 1 Si on a A et B sont en TRUE (<>0)
LET A=1
LET B=1
LET C= A OR B = 1 (car A est à 1; B est à 1; Si A ou B est à 0 même résultat. C=1)
LET C= A AND B = 1 (car A est à 1; B est à 1; C=1 sauf si A ou B changent d'état.)
Bon, c'est simple...
NOTA : On oublie la fonction XOR, qui ne peut être utilisée sur une fonction booléen, car le XOR de A= NOT A !
J'en viens à mon exemple!
On prend des coordonnées fixes sur l'écran de 21x32 caractères.
Utilisées si l'on passe avec un bonhomme (curseur) sur ces coordonnées, ça fait quelque chose... un "Booom!" pour rester ludique.
Donc, test en X (lignes) et Y(colonnes). x(de 0 à 20) y(0 à 31)
Ligne Y n°1: X coordonnées 7, 14 et 20 piégées!
Ligne Y n°2: X coordonnées 3, 10 et 15 piégées!
Ligne Y n°3: X coordonnées 7,13 et 15 piégées!
Voici donc les conditions:
Code : Tout sélectionner
100 IF X=7 AND Y=1 OR X=14 AND Y=1 OR X=20 AND Y=1 THEN GOTO 200
110 IF X=3 AND Y=2 OR X=10 AND Y=2 OR X=15 AND Y=2 THEN GOTO 200
120 IF X=7 AND Y=3 OR X=13 AND Y=3 OR X=15 AND Y=3 THEN GOTO 200
180 GOTO 50
200 PRINT "BOOM!!"
Comme on l'a vu, trop de codes ralenti le basic, donc, il faut simplifier et effacer les redondances!
On va résonner par ligne... si on est en ligne 1 tester les points X des colonnes!
Donc,
Code : Tout sélectionner
100 IF Y=1 AND (X=7 OR X=14 OR X=20) THEN GOTO 200
110 IF Y=2 AND (X=3 OR X=10 OR X=15) THEN GOTO 200
120 IF Y=3 AND (X=7 OR X=13 OR X=15) THEN GOTO 200
180 GOTO 50
200 PRINT "BOOM!!"
Mais, pourquoi tester toutes les ligne quand X n'a qu'une valeur possible?
Donc,
Code : Tout sélectionner
95 ON Y+1 GOSUB 100,110,120,130,... (Y+1 car y commence à 0)
98 GOTO 50
100 REM
110 IF X=7 OR X=14 OR X=20 THEN GOTO 200
115 RETURN
120 IF X=3 OR X=10 OR X=15 THEN GOTO 200
125 RETURN
130 IF X=7 OR X=13 OR X=15 THEN GOTO 200
135 RETURN
200 PRINT "BOOM!!"
Nota: Il est possible de faire une réduction plus pointue grâce au tableau de Karnaugh
Mais, l'exécution sera forcement trop gourmande en temps, même si réduite en une seule ligne.
Donc, dans ce cas, les conditions ne passent pas forcement par des IF !
A l'inverse, si le code comprend un trop grand nombre de conditions redondantes...
Il est parfois utile d'utiliser une condition booléenne via une variable.
110 IF (X=7 OR X=14) AND (X=20 OR X=12) THEN GOTO 200
120 IF (X=5 OR X=4) AND (X=20 OR X=12) THEN GOTO 200
Au lieu de répéter (X=20 OR X=12), placez le déclencheur (trigger) dans une variable!
100 LET trig=(X=20 OR X=12)
110 IF (X=7 OR X=14) AND trig THEN GOTO 200
120 IF (X=5 OR X=4) AND trig THEN GOTO 200
La condition est ainsi calculée qu'une fois.
Re: BASIC pas si simple...
"erreur" courante dans de nombreuse routines, les sauts inutiles!
Exemples:
Code : Tout sélectionner
100 LET trig= X AND 1
110 IF trig THEN GOTO 200
120 IF NOT trig THEN GOTO 200
200 GOTO 100
Code : Tout sélectionner
100 LET trig= X AND 1
110 IF trig THEN GOTO 100
120 IF NOT trig THEN GOTO 100
200 GOTO 100
Re: BASIC pas si simple...
Evitez d'inclure une routine d'affichage non utile dans un calcul cyclique!
(trouvé dans un programme de labyrinthe)
Code : Tout sélectionner
300 D=INT(RND*5)+1
305 COLOR0,15:locate12,24:PRINT" Patientez... ";
310 on D GOTO320,350,380,410,380
400 GOTO300
Suggestion:
Code : Tout sélectionner
299 COLOR0,15:locate12,24:PRINT" Patientez... ";
300 D=INT(RND*5)+1
310 on D GOTO320,350,380,410,380
400 GOTO300
- Totor le Butor
- Messages : 2237
- Inscription : 07 sept. 2011 16:14
- Localisation : Paris - Mezels
Re: BASIC pas si simple...
Quand on lit, on se dit "c'est une évidence" et puis on regarde le dernier truc qu'on a programmé et là... on pleure .
[Rch] Vieux composants électroniques et circuits intégrés toute époque et vieilles cartes .
Re: BASIC pas si simple...
En effet, il était difficile de s'y retrouver dans un listing car il fallait constamment faire des "list" et des "edit"!
De nos jours, les textes défilent avec les barres de déplacement, et il est possible de faire des recherches facilement.
Donc, ce qui nous parait faux, nous saute au yeux plus facilement.
Personnellement, créer un jeux directement sur émulateur ou vrai machine, me stress.
Tout bon programme réalisé à l'époque se préparait sur papier, avant de l'entrer sur la machine.
Sans cette préparation, le programme devient rapidement un programme déstructuré et qui part dans tous les sens!
En mode texte, des copiers, des collers, des déplacements et renumérotations!
Il n'était pas rare de trouver des lignes en doublon dans les programmes, car déplacées ou renumérotées.
C'est pour cela que certaines erreurs semble évidentes, facilement évitables et ridicules.
Re: BASIC pas si simple...
- Si le Basic permet de choisir les types de variables, n'utilisez pas de nombres en virgule flottante, sauf absolue nécessité. Définissez des variables entières. Par exemple X% au lieu de X en Basic Microsoft, ou, en début de programme :
Code : Tout sélectionner
DEFINTA-Z
- Dans les boucles FOR ... NEXT, si le Basic le permet, ne mettez pas le nom de la variable de boucle après le NEXT. Ecrivez
Code : Tout sélectionner
FOR I%=1 TO 100: NEXT
Code : Tout sélectionner
FOR I%=1 TO 100: NEXT I%
- Partout où c'est possible supprimez les espaces. Exemple
Code : Tout sélectionner
IFX%=0THENPRINT"TOTO"ELSEPRINT"TATA":GOTO100
Code : Tout sélectionner
FORI%=0TO9:A$"A"+RIGHT$(STR$(I%),1):PRINTA$:NEXT
Code : Tout sélectionner
A$="A ":FORI%=0TO9:MID$(A$,2)=RIGHT$(STR$(I%),1):PRINTA$:NEXT
L'obstacle augmente mon ardeur.
Re: BASIC pas si simple...
Code : Tout sélectionner
IFX%=0THENPRINT"TOTO"ELSEPRINT"TATA":GOTO100
Les programmes non sauvegardés en mode texte (option trouvées sur Amstrad, msx, Apple2 etc...) sont encodés en "tokens".
Cela consiste à donner une valeur ASCII en dehors des valeurs d'affichage. Cette méthode permet d'associer une valeur binaire d'un ou de deux octets à un commande, fonction ou signe mathématique.
Par exemple sur Amstrad: "gosub"= 159 ; "input"= 163; "merge"= 171
Ce système rend la mémoire basic impossible à décoder visuellement, mais la taille du programme et réduit à un ou deux octet par commande ou fonction.
Ajouter des espaces ajoute des octets supplémentaire au programme à chaque fois!
Dans le cas de certains Basic, comme le ZX81 et le Spectrum, les espaces sont inclus dans les commandes affichées!
Résultat, l'ajout d'espaces ajoute un espace supplémentaire à la commande.
Code : Tout sélectionner
L'espace réservé aux chaînes de caractères se remplit quand une chaîne provisoire est créée.
Sur Zx81 et Spectrum, la mémoire est placée après le basic (écran pour le ZX81), et est dynamique, car ils placent les valeurs des variables dans l'ordre d'initialisation.
Donc, si une variable chaîne est dimensionnée à 3 caractères en début de mémoire "variable" (VARS) (en début de programme), la routine en ROM doit déplacer toutes les valeurs suivantes pour donner de la place à cette donnée.
Résultat, un très court moment d'attente est à prévoir, mais qui peut être répétée.
Le mieux est de créer une valeur de variable non utilisée, juste avant le traitement de la chaîne, pour que le déplacement soit en fin de mémoire incluant les variables.
Sur ZX81 et Spectrum, il existe deux types de variables chaînes: les fixes de taille prédéfinies et les dynamiques.
La fonction DIM a$(1,10) permet de créer une variable simple de dix caractères (dix espaces à l'initialisation) où la fonction a$=a$+"*" est interdite.
Ce qui est "marrant", sur Zx81, c'est que la mémoire écran est placée juste avant la mémoire "variables".
Mais la taille de l'encombrement de la mémoire écran est variable...et a chaque redimensionnement de celui-ci, les données des variables sont automatiquement déplacées... et parfois, un CLS est pénible, car peut durer près d'une seconde!