?
| Nos forums | NwN2.fr | Lyncya | Notre channel IRC |
La Bibliothéque de Neverwinter Nights
La Bibliothéque de Neverwinter Nights
 
 
 
 
 
Bienvenue, connectez vous ou créez votre compte. Changer d'interface
 
Se connecter:
Login:

Password:


 
Neverwinter Nights 2
  Compendium NWN/NWN2
Classe, Warlock
Classes de Base
Classes de Prestige
Forum Joueur NWN2
Forum Concepteur NWN2
Bestiaire (Créatures)
Races
Tests
 - Collector Chaotique Mauvais (bbnwn, 4 nov 2006)
 - Mask of the Betrayer
 - Storm of Zehir
 - Mysteries of Westgate
Mondes
 - Les Artisans du Mitan
 - Les Légendes de Luiren
 - LanceDragon
 - La Bataille pour Cormanthor
 - Man O'War
 - Sendarie Nouvel Âge
Preview
 - 29 Mars 2006 (BBNWN)
 - 2 mai 2006 (Gamespot)
 - 17 Mai 2006 (WarCry)
 - 19 Mai 2006 (NWVault)
 - Designer Diary #1 (Gamespot, 1er Juin 2006)
Interview
 - Dorian Richard (20/02/2006)
 - Ferret Baudoin (22/02/2006)
 - Feargus Urquhart (2 mai 2006)
 - La Lettre Ouverte de Papermonk
 - Chris Avellone (Total Video Games)
Logs IRC
 - Warcry (27/01/2006)
 - NWVault / NWC (3 Juin 2006)
 - NWN2News.net (30 Juin 2006)
Faciliter la diffusion et l'installation de vos créations

 
Communauté
  Forums
Channel #nwnights-fr
Guide IRC
Liens
CEP

 
Fichier
  Tileset
Module
Hakpak
Objets
Portraits
Créatures
Scripts
Tutoriaux
Autres
Wallpapers

 
Editeur
  Tutorial Editeur
Cinématiques
Musiques
Textures
Tutoriaux NWScripts
Scripts

 
Le jeu
  Solution
Sorts
Classes
Dons (feat)
Aptitudes (skill)
Bestiaire
Règles 3e Edition
Jouer en multiplayer

 
Hordes of the Underdark
  Informations Générales
Solution [forum]

 
Shadows of Undrentide
  Preview
Informations générales
Classes de Prestige
'Lisez Moi.txt' de la Démo
FAQ
Nouveaux tilesets
Solution [forum]

 
Divers
  Traductions Logs Irc
Guides divers

 
Présentation
  Généralités
Configuration minimale
Serveur Dédié
Traduction FAQ
Historique (nwn et bioware)
Contrats de Bioware (vf)

 
Site
  Copyrights
Webmasters

 
     
 
Dîtes non aux inutiles protections contre la copie dans les jeux (SecuROM, StarForce, etc) !!
HADOPI - Le Net en France : black-out

5. Les structures de contrôle


Voir les opérateurs, c'est bien, mais ce n'est pas ça qui va nous permettre par exemple de définir si un script doit forcer le personnage 'x' à aller dans une telle zone ! Pour cela, nous devons utiliser des structures de contrôle, qui vont nous permettre de « conditionner » nos scripts, qui pourront aussi les alléger, etc. !

a. Les conditions (if, else)

Les instructions if et else sont les plus importantes instructions de tout langage de programmation : elles vont vous permettre de décider si une partie de votre code devra être exécuté ou non. Basiquement, le code est exécuté si la condition est vérifiée :

if ( condition )
  instruction;

Mettons que la condition soit : a == b et que a = b (a, b deux entiers). Dans ce cas, la condition renvoie VRAI (true) et l'instruction sera exécutée.

Dans ce cas-ci, notre « instruction » tiens sur une ligne : vous pouvez omettre les accolades. Si votre code fait plusieurs lignes, vous devez utiliser les accolades :

if ( condition )
{
  instruction1;
  instruction2;
}

Maintenant, nous avons notre condition : néanmoins, il ne se passe rien si celle-ci est fausse. Pour cela, on va utiliser la structure else (sinon) :

if ( condition )
  instruction1;
else
  instruction2;

(On suppose que « instruction1 » et « instruction2 » sont sur une ligne)
Ainsi, si on reprend notre exemple : on teste a == b, et dans ce cas a > b. Alors l' « instruction2 » sera exécutée au lieu de l'«instruction1».

Vous pouvez bien sur combiner les else et les if : reprenons notre exemple :

if ( a == b )
  a = b;
else if ( a > b )
  a = b + 1;
else if ( a < b )
  a = b - 1;
else
  a = a;

Nous vérifions donc successivement :

si a == b
  alors a = b
  sinon si a > b
    alors a = b + 1
    sinon a < b
      alors a = b - 1
      sinon a = a

Nous avons indenté notre exemple pour bien vous montrer une chose importante à savoir (ça peut être la cause d'erreurs pour des conditions plus compliquées) : dans un premier temps, on vérifie si a = b, et dans ce cas on va effectuer l'instruction a = b, si a != b alors on va vérifier en premier lieu si a > b, puis en second lieu si ce n'est pas le cas si a < b et enfin si aucune des expressions n'est vérifiée on exécute l'instruction 'a=a'.

Si vous n'avez pas compris, focalisez vous sur les mots 'premier' et 'seconds' : l'ordre des conditions importe, c'est-à-dire que vous ne pourrez pas avoir de condition 'a < b' sans avoir de conditions 'a == b' et 'a > b'.

Au passage, vous noterez l'inutilité totale du else : nous avons vu chacun des cas possibles.

Voici des exemples de conditions plus compliquées (elles proviennent d'un script en PHP) : vous noterez l'utilisation des parenthèses pour bien séparer les différentes parties de la condition.

if ( $iMode != -1 && $this->_s != -1 && ( ( $this->bUserIsModerator == true && ( ( $MB->aUserModerator['SujetOpen'] == 1 && $iMode == 0 ) || ( $MB->aUserModerator['SujetChRestriction'] == 1 && $iMode != 0 ) ) ) || $this->bUserIsAdmin == true ) )
  instruction;


if ( $iType != -1 && $this->_s != -1 && ( ( $this->bUserIsModerator == true && $MB->aUserModerator['SujetChType'] == 1 ) || $this->bUserIsAdmin == true ) )
  instruction;

Il s'agit sûrement d'horreurs pour quelqu'un qui débute, mais ces cas là ne sont pas inexistants. Vous aurez vous aussi peut-être besoin de faire d'aussi longues conditions. Pour éviter les erreurs, vous avez plusieurs méthodes :

Vous pouvez décomposer la condition :
(Note : en PHP les variables ne sont pas typées par défaut. Dans le cas des NWScripts vous devrez déclarer des entiers)

$condition1 = $iMode != -1;
$condition2 = $this->_s != -1;
$condition3 = $MB->aUserModerator['SujetOpen'] == 1 && $iMode == 0;
$condition4 = $MB->aUserModerator['SujetChRestriction'] == 1 && $iMode != 0;
$condition5 = $this->bUserIsModerator == true;
$condition6 = $this->bUserIsAdmin == true;

Ce qui nous donne :

if ( $condition1 && $condition2 && ( ( $condition5 && ( $condition3 || $condition4 ) ) || $condition6 ) )

Ce qui, vous l'avouerez est plus lisible, ou plus compréhensible. Néanmoins, vous stockez des variables supplémentaires pour RIEN. C'est tout l'avantage de la deuxième solution :

if ( $iMode != -1 &&
     $this->_s != -1 &&
     (
       ( $this->bUserIsModerator == true &&
          (
            ( $MB->aUserModerator['SujetOpen'] == 1 &&
               $iMode == 0 ) ||
            ( $MB->aUserModerator['SujetChRestriction'] == 1 &&
               $iMode != 0 )
          )
       ) ||
       $this->bUserIsAdmin == true
     )
   )

Tout de suite, cela prend bien plus de place mais cette méthode est plus utile : premièrement, on n'utilise pas de sous variables, deuxièmement en général le compilateur accepte cette forme, et troisièmement on peut plus facilement savoir ce qui se passe exactement à l'intérieur de notre condition : c'est le but de l'indentation.

Enfin, nous vous avions parlé de l'opérateur ternaire ( « ? : ») : celui-ci permet de faire une condition « if ( condition ) { instruction } else {} » sur une ligne : il a cependant de grandes différences avec le couple if/ else : il ne permet pas d'effectuer toutes les instructions voulues, ça n'est pas son but. Son but ? C'est d'affecter à une variable une valeur en fonction d'une condition.
Voilà la syntaxe générale :

a = (condition) ? instruction_si_vrai : instruction_si_faux;

(On a mis « = » mais ça peut être += , etc.)

Par exemple :

a = ( a < b ) ? b + 1: b - 1;

Cet opérateur ternaire est très pratique, mais évitez d'en abuser. Par exemple évitez ceci :

a = ( a < b ) ? b + 1: b - 1;
b = ( a < b ) ? a + 1: a - 1;

La condition étant la même dans les deux cas, préférez plutôt ceci :

if ( a < b )
{
   a = b + 1;
   b = a + 1;
  // Note : vous remarquerez qu'après cette instruction a est toujours inférieur à < b
}
else
{
   a = b - 1;
   b = a - 1;
}
b. Les boucles (while, for, do ... while)

Un autre aspect pratique de la programmation est la boucle. Si on reprend notre exemple sur les variables globales :

CreateItemOnObject( "item", oPlayer );
// On répète l'instruction 100 fois par exemple
CreateItemOnObject( "item", oPlayer );

Ici, on a écrit 100 fois CreateItemOnObject( "item", oPlayer ); ! Maintenant, avec les boucles, on va pouvoir réduire ceci et corriger cette erreur. L'avantage étant que vous réduirez ainsi la taille de vos scripts (sachant qu'ils sont limités à 512 Ko avec le patch 1.26).

Pour effectuez 100 fois l'instruction CreateItemOnObject( "item", oPlayer ); nous avons trois structures de contrôle qui vont nous permettre de réduire notre code.

La première, c'est l'instruction while, la seconde, l'instruction for et enfin la troisième do ... while.

Voici la syntaxe de while :

while ( condition )
{

  instruction;
}

Ici tant que la condition sera VRAIE alors l'instruction sera effectuée. L'instruction est supposée permettre à la condition d'être fausse à un moment : si tel n'est pas le cas, alors vous créerez une boucle infinie ce qui représente bien entendu un danger.

Voici un exemple de boucle simple :

int i = 0;

while ( i < 10 )
{

  i++;
}

Et un exemple de boucle infinie :

int i = 0;

while ( i == i )
{
  i++;
}

Dans d'autres cas, on peut avoir :

int i = 0;

while ( i != 10 )
{

  i++;

  if ( i == 9 )
    i = 11;
}

Il s'agit d'un autre type de boucle infinie : ici, on teste la condition i différent de 10 et on empêche que i soit égal à 10.

Voici notre exemple réécrit avec la boucle while :

int i = 0;
/* Assurez vous de savoir bien compter : de 0 a 100 il y a 101 nombres, donc vous devrez utiliser la condition i < 100 et non i <= 100 ( a moins que i = 1 )*/
while ( i < 100 )
{

   CreateItemOnObject( "String", oPlayer );
}

Vous voyez ? Notre exemple est tout de suite plus propre. Mais ... nous avons oublié de mettre i++ pour que la boucle puisse se fermer...

int i = 0;
while ( i < 100 )
{

   CreateItemOnObject( "item", oPlayer );
   i++;
}

(Note : on peut mettre i++ avant CreateItemOnObject)

L'instruction while permet de créer des boucles simplement, sans trop s'embêter. Néanmoins, il faudra penser à chaque fois à mettre une instruction permettant d'arrêter la boucle.

L'autre façon de créer des boucles, c'est avec l'instruction for : celle-ci est plus « sécuritaire » puisque dans sa déclaration vous devez indiquez l'état de départ, la condition à vérifier et une instruction qui sera évaluée à chaque itération (une itération = un passage dans la boucle).

Voici la syntaxe :

for ( expression_depart; condition; instruction1 )
{

  instruction2;
}

expression_depart : correspond à l'état initial : cette expression est exécutée lors de la première itération. Le plus souvent, il s'agit de définir la valeur initiale d'un entier : i = 0.

condition : tout comme l'instruction while il vous faut une condition pour que la boucle puisse tourner. Le plus souvent on teste la valeur d'un entier (si celle-ci est inférieure à x par exemple) : i < x;

instruction1 : il s'agit d'une instruction qui est exécutée quoiqu'il arrive. Cette instruction doit permettre de fermer la boucle : par exemple, i++.

instruction2 : instruction à exécuter.

Voici notre exemple réécrit avec la boucle for :

int i;
for ( i = 1; i <= 100; i++ )
{

  CreateItemOnObject( "item", oPlayer );
}

Note : on commence à 1 et on va jusqu'à 100 inclus, ce qui nous fait bien 100 objets de créés.

C'est à peu près tout ce qu'il y a à savoir sur les fonctions. Nous verrons plus loin dans cette section deux autres instructions qui sont très utiles avec les boucles.

Dans notre exemple avec la boucle For nous ne sommes pas forcés de mettre les accolades car notre instruction ne tient que sur une seule ligne.

int i;
for ( i = 1; i <= 100; i++ )
  CreateItemOnObject( "item", oPlayer );

De même, avec la boucle while :

int i = 0;
while ( i++ < 100 )
  CreateItemOnObject( "item", oPlayer );

Ce qui peut s'écrire :

int i = 0;
while ( ++i <= 100 )
  CreateItemOnObject( "item", oPlayer );

Ici on pré incrémente i : ce qui veut dire que lors de la première itération de la boucle, i vaut 1 et pas 0 : c'est pour cela que l'on doit utiliser l'opérateur « inférieur ou égal à ».

Il existe aussi un troisième type de boucle : do ... while. Voici sa syntaxe :

do instructions while ( condition );

Dans ce type de boucle, le code est d'abord exécuté (même si la condition est fausse) et la condition est ensuite vérifiée.

Voici notre exemple :

int i = 0;
do CreateItemOnObject( "item", oPlayer );
while (i++ < 100 );

ou

int i = 0;
do
{
  CreateItemOnObject( "item", oPlayer );
}
while ( i++ < 100 );
c. l'instruction switch.

L'instruction switch est en fait une sorte de if mais imbriqué : vous allez tester la valeur d'un entier (généralement) et en fonction des différents cas, vous utiliserez une instruction switch.

Voici un exemple :

int i = Rand( 3 ); // on donne une valeur aléatoire entre 0 et 2.

if ( i == 0 )
  instruction1;
else if ( i == 1 )
  instruction2;
else
  instruction3;

Avec switch ceci donnerait :

int i = Rand( 3 );
switch ( i )
{
  case 0 :
    instruction1;
  break;
  case 1 :
    instruction1;
  break;
  default :
    instruction3;
  break;
}

Rien de bien compliqué dans cet exemple : cependant, vous remarquerez l'instruction break, dont nous reparlerons plus tard : celle-ci permet de sortir du bloc switch.

Voici un exemple sans ce break :

int i = Rand( 3 );
int j = 0 :
switch ( i )
{
  case 0 :
    j++;
  case 1 :
    j++;
  default :
    j++;
}

Au sortir du bloc switch j aura la valeur suivante : 1 si i = 2, 2 si i = 1, et 3 si i = 0.

d. les instructions break et continue.

Les instructions break (que nous avons entrevue au paragraphe précédent) et continue sont surtout utilisées pour les boucles (sauf pour break, qui est aussi utilisée dans switch) : break va comme son nom le suppose arrêter l'exécution de la boucle (ou de l'instruction switch le cas échéant) tandis que continue va elle passer à l'itération suivante en ignorant le code située après continue.

Reprenons notre exemple de boucle infinie : même si c'est déconseillé, une boucle infinie est parfois souhaitable, il faut juste prévoir une condition inévitable afin que la boucle puisse être interrompue.

int i = 0;

while ( i != 10 )
{
  i++;

  if ( i == 9 )
    i = 11;
}

Dans cet exemple, on ne passait jamais par 10 causant ainsi une boucle infinie. On pourrait bien sûr utiliser la forme suivante :

int i = 0;

while ( i != 10 )
{   i++;
  // Instruction
}

Mais pour bien montrer l'utilisation de break, nous ne ferons que corriger notre exemple :

int i = 0;

while ( i != 10 )
{
  i++;

  if ( i <= 9 ) // i <= 9  ou !( i > 9 )
    i = 11;
  else
    break;
}

Ici, nous avons l'assurance que la boucle ne sera pas infinie : quand i sera supérieur à 9, alors la boucle sera interrompue ainsi que le code qui suit l'instruction break. Par exemple :

int i = 0;

while ( i != 10 )
{
  i++;

  if ( i <= 9 ) // i <= 9  ou !( i > 9 )
    i = 11;
  else
  {
    break;
    i = 100;
  }
}

Lorsqu'on testera la valeur de i, i vaudra 10 mais pas 100 comme le laisse supposer l'exemple. Si vous voulez que i prenne la valeur de 100 : vous devrez placer l'instruction i = 100; avant le break.

L'utilisation de break est strictement la même avec les boucles for, et do while (ainsi que le bloc switch, bien que dans le bloc switch il y ait largement moins de chances d'obtenir une boucle infinie... et pour cause !)

La seconde instruction, continue, va vous permettre de passer à l'itération suivante en ignorant le code suivant « continue ».

Par exemple : vous voulez construire un script qui fait varier la variable i de 1 à 25. Et tout les 5, vous voulez ajouter '+1' à la variable j.

int i, j = 0;

for (i = 1; i <= 25; i++ )
{
  if ( (i % 5) != 0 )
    continue;

  j++;
}

L'exemple est très simple : si le reste de la division entière de i par 5 ne vaut pas 0, on continue la boucle jusqu'à atteindre une valeur de i telle que i % 5 = 0 (i Modulo 5). Quand on atteint cette valeur de i alors on incrémente j.

Ceci vous montre aussi qu'avec l'instruction continue on « part » directement à l'itération suivante sans se soucier du reste.

L'instruction continue fonctionne aussi avec les boucles while et do ... while.

C'est à peu près tout ce qu'il y a savoir pour les structures de contrôle. Sachez juste vous en servir avec parcimonie et préférez la boucle for lorsque vous désirez faire varier un entier d'une valeur de départ x vers une valeur de fin y. Il existe un autre moyen plus rudimentaire de faire des boucles qui consiste à se servir de fonctions : c'est justement ce que nous verrons dans la section suivante.









Navigation rapide:
 
 
Revenir à la page d'accueil du site Ajouter la Bibliothéque de Neverwinter dans vos favoris Afficher une version imprimable de la page
  NeverList - Liste ...
Lyncya 3 - La Gue ...
Sarmates!
Le dernier des fi ...
Bonne année
Joyeux Noël 2010
The Witcher 2 en ...

Archives
Rechercher
 
 
Le Site



NwN 2 - Support des Modules Solos


Groupes
Archives
 

:: design by ghaxir :: coding by baldurien :: la bibliothèque de neverwinter :: tous droits réservés ::