Un Bug dans la méthode¶
Les objectifs de ce TP sont :
Écrire des méthodes java implémentant des traitements simples.
Les fonctions ou méthodes¶
Les fonctions permettent de décomposer un programme en plusieurs parties. Le comportement d’une fonction est paramétré par un ensemble de variables : les paramètres de la fonction. À la fin de son exécution, une fonction retourne généralement un résultat : sa valeur de retour. Les fonctions permettent de faciliter l’écriture et la (re-)lecture des programmes. Elles permettent également de réutiliser facilement des morceaux de programmes.
Une fonction est définie par :
un nom ;
une liste des paramètres : c’est une liste de variables typées dont la valeur sera renseignée lors de l’utilisation de la fonction ;
un type de retour : c’est le type de la valeur retournée par la fonction à la fin de son exécution ;
le corps de la fonction : c’est le code Java décrivant ce que fait la fonction.
Note
En Java, les fonctions sont aussi appelées des méthodes. Dans le cadre de ce cours d’introduction, nous utiliseront essentiellement des méthodes dites de classe (mot clef static).
Définition d’une fonction¶
En Java, la définition d’une fonction a la forme suivante :
static type_de_retour nom_de_la_fonction(liste des paramètres) {
// corps de la fonction
}
Les fonctions doivent être définies en dehors de toute autre fonction (il n’est pas possible de définir une fonction dans une autre).
Type de retour
Le type de retour de la fonction est le type de la valeur retournée par la fonction. Tous les types usuels (int, float, boolean, etc.) sont possibles. Dans le cas particulier où la fonction ne retourne aucune valeur, on utilisera le mot clef void à la place du type de retour.
Nom de la fonction
Le choix des noms de fonctions suivent les mêmes règles que les noms de variables : le nom doit commencer par une lettre ou un tiret bas (_), et ensuite être composé d’une suite de lettres, de chiffres ou de tirets bas. Il est très fortement conseillé de choisir des noms significatifs, c.-à-d. donnant une indication sur ce que fait la fonction.
Liste des paramètres
Les paramètres sont des variables dont la valeur est renseignée avant d’utiliser la fonction. Ces variables sont données dans la liste des paramètres. Chaque paramètre est défini par son type, suivi de son nom. Lorsqu’une fonction prend plusieurs paramètres, leurs définitions sont séparées par des virgules. Lorsqu’une fonction ne prend aucun paramètre, le nom de la fonction est simplement suivi par une paire de parenthèses vides ().
Note
Les variables définies par les paramètres n’existent que pendant l’exécution de la fonction. Elles sont créées au début de l’exécution de la fonction et disparaissent lorsque la fonction retourne.
Corps de la fonction
Le corps de la fonction est ensuite décrit dans un bloc délimité par des accolades {..}. Le corps de la fonction consiste en une suite d’instructions Java. Comme dans tout bloc d’instructions, il est possible de déclarer des variables qui n’existeront que le temps de l’exécution du bloc.
L’instruction return provoque l’arrêt immédiat de l’exécution de la fonction. Ce mot clef doit être suivi d’une expression dont l’évaluation donnera la valeur retournée par la fonction. Le type de cette expression doit bien évidemment correspondre au type de retour déclaré pour la fonction. Si la fonction ne retourne rien (type de retour void), le mot clef return n’est suivi de rien (hormis le point-virgule terminant l’instruction).
Une instruction return est implicite à la fin de chaque fonction. Il est donc possible de l’omettre pour des fonctions ne retournant rien.
Appel de fonction¶
Lorsqu’une fonction est utilisée, on parle d’appel de fonction. Pour appeler une fonction, il suffit d’écrire son nom suivi d’une liste d’expressions entre parenthèses, séparées par des virgules. Ces expressions donneront les valeurs que prendront les paramètres de la fonction pendant son exécution. Une fonction retournant une valeur peut être utilisée au sein d’une expression.
En Java, les paramètres sont toujours passés par copie. Cela signifie que la fonction reçoit une copie des valeurs passées en paramètre.
Quelques conseils¶
Voici une liste de conseils afin d’utiliser correctement les fonctions :
Le nom de la fonction doit être choisi soigneusement : il doit refléter ce que fait la fonction.
De même que le nom de la fonction, c’est une bonne idée de donner des noms significatifs aux paramètres des fonctions.
Il est conseillé d’essayer de ne mettre qu’une seule instruction return dans une fonction. Il faut parfois retravailler l’algorithme pour y arriver. Ceci n’est cependant pas une règle absolue : l’objectif est d’écrire du code qui soit clair et facile à lire et à comprendre.
Le corps d’une fonction ne doit bien souvent pas dépasser quelques (2 ou 3) dizaines de lignes. Si une fonction devient trop longue, c’est peut-être qu’il faut la décomposer en plusieurs fonctions.
On veillera à indiquer avant chaque fonction, à l’aide d’un commentaire, le rôle de la fonction, une description des
différents paramètres ainsi que de la valeur retournée.
Défi n°1 : L’artiste Bug¶
État initial
|
Résultat attendu
|
|
|
À faire
Récupérer
l'archive du programmeet l’enregistrer dans le dossier du TP.Se placer dans le dossier puis décompresser l’archive :
file-roller --extract-to=. TP_BugMethodes.tar.gzLe programme comprend les classes et fichiers devenus habituels. Se reporter à l’énoncé du premier TP pour les détails et la référence de l’API (en cliquant ici).
Le programme, tel qu’il est fourni, produit des erreurs à la compilation car la définition de la méthode à écrire n’est pas complète.
Déterminer le type de retour approprié pour la méthode
dessineLosange()de la classeBug.Compléter la définition de la méthode et valider son fonctionnement.
Modifier la méthode
enRoute()de sorte à dessiner plus de fleurs (à d’autres endroits).
Note
Penser à positionner la variable
readMazeà false dans le fichierMain.java.
Correction
Défi n°2 : Le Bug chasseur de serpent¶
À faire
Récupérer
le code de la classe Buget l’enregistrer à la place de la précédente version. Le programme, tel qu’il est fourni, se compile mais ne réalise rien.Concevoir et implémenter la méthode
isFaceSnake()qui retourne vrai si le bug fait face à une case verte et faux sinon. Elle doit également retourner faux si le bug fait face à un mur. Enfin, à la fin de l’exécution de cette méthode, ni le bug ni le monde des bugs ne doit avoir été modifié.
Les bugs apprécient aussi bien les limaces et les lézards que les serpents ; mais ces délicieuses proies ne sont pas toutes de la même couleur et la méthode isFaceSnake() ne convient donc pas pour dévorer une belle grosse limace marron ou un lézard orange.
À faire
Modifier la méthode
isFaceSnake()de sorte qu’elle permettre de suivre une piste dont on lui spécifie la couleur. Pour tester le fonctionnement de cette nouvelle version de la méthode, changer la couleur de la proie dans le fichierMain.java(COULEUR_PP) et positionner les cases colorées :final int[][] casesColorees = { {6,0},{6,1},{6,2}, {5,2},{5,4},{5,5},{5,6}, {4,2},{4,3},{4,4},{4,6}, {3,6},{3,7},{3,8}, {2,8}, {1,8} };
Correction
Défi n°3 : Le binary Bug¶
À faire
Récupérer
le code de la classe Mainet l’enregistrer à la place de la précédente version.Récupérer
les positions des biscuitset l’enregistrer.Compléter la méthode
enRoute()de la classeBugpour qu’elle fasse en sorte que le bug suive le ruban (précédemment serpent), repère les biscuits qui symbolisent des états logiques1et construise le mot binaire qu’ils définissent. En fin de Ruban, le bug émettra un message contenant le mot binaire qu’il a lu. On considèrera, pour cette question, que le bug parcourt le ruban en commençant par le bit de poids fort. Cela pourra ressembler à :Bug 0 dit : J'ai lu 1100000010011101
Indication
La méthode
concat()de la classe String pourra s’avérer utile (mais pas indispensable).Concevoir une méthode
binaryString2IntNatural()qui permette maintenant au bug de nous réveler la représentation décimale du mot binaire qu’il a lu précédemment. Elle accepte en paramètre une chaîne de caractères représentant le mot binaire à transcoder et calcule la valeur correspondante avant de la retourner.Indication
Les méthodes
length()etcharAt()de la classe String peuvent rendre ici de grands services.
Cela étant fait, il serait dommage de se priver des nombres entiers négatifs, alors on décide que les mots binaires encodés sur le ruban sont représentés en complément à 2 (C2). Pour rappel la représentation en C2 permet de représenter sous forme binaire les nombres entiers positifs et négatifs et le passage entre la représentation binaire naturelle et le C2 se fait simplement avec le procédé suivant :
SI (bit de poids fort = 0) ALORS il s'agit d'un nombre positif à lire en binaire naturel
SINON
il s'agit d'un nombre négatif := - (valeur du complément à 1 +1)
FIN_SI
Indication
Le complément à 1 d’un nombre est la représentation binaire obtenue en remplaçant chaque 0 par un 1 et inversement.
Concevoir une méthode
binaryString2IntC2()qui retourne la valeur représentée par le mot binaire passé en paramètre, supposé écrit en complément à 2.
Il s’avère aussi que le ruban peut présenter une longueur différente de 16. On choisit alors d’appliquer la politique de lecture suivante :
si le ruban comporte moins de 16 cases, on compléte la représentation par des
0.si le ruban comporte plus de 16 cases, on arrête la lecture dès que l’on a lu 16 digits.
Indication
Dans l’exemple de l’illustration, la valeur représentée est -16227.
Cependant, cela n’a de sens que si la lecture s’effectue en commençant par le bit de poids faible, de sorte que les éventuels 0 ajoutés ne soient pas significatifs.
Enfin, on veut rendre ce programme capable de décoder des nombres sous des formats différents de 16 bits.
Modifier le code de la classe Bug pour refléter les modifications décrites ci-desus. On limitera les tests à des formats inférieurs à 16 bits pour des raisons de taille de grille.
Indication
Il est nécessaire de modifier la méthode
enRoute()et vraisemblablement la méthodebinaryString2IntC2()de sorte à ce que le format devienne un paramètre de la méthode.Un ruban plus petit pourrait être défini par
final int[][] casesColorees = { {5,2},{5,4},{5,5},{5,6}, {4,2},{4,3},{4,4},{4,6}, {3,6},{3,7},{3,8}, {2,8}, {1,8} };
Il faut alors penser à supprimer les 2 premières lignes du fichier de positionement des biscuits binaryData.txt.
Un ruban plus grand pourrait être défini par
final int[][] casesColorees = { {9,0},{8,0},{7,0}, {6,0},{6,1},{6,2}, {5,2},{5,4},{5,5},{5,6}, {4,2},{4,3},{4,4},{4,6}, {3,6},{3,7},{3,8}, {2,8}, {1,8} };
Correction
Bug.java. ATTENTION, la méthode isFaceSnake() est remplacée par hasNextSnake(), conçue différemment, dans cette version, pour varier.





