IX. Chapitre 7. L'applet Morpion▲
Quand tu es en ligne sur ton site web favori, il y a des chances pour que certains des jeux et autres programmes qui te sont proposés soient écrits en Java à l'aide de ce qu'on appelle des applets ou, parfois, des appliquettes. Ces applications spéciales existent et s'exécutent dans la fenêtre du navigateur web. Les navigateurs web comprennent un langage simple appelé HTML, qui te permet d'insérer des marques spéciales, ou balises (tags), dans les fichiers texte, afin de leur donner une apparence agréable lorsqu'ils sont affichés par les navigateurs. En plus du texte, tu peux inclure dans un fichier HTML la balise <applet>, qui indique au navigateur où trouver une applet Java et comment l'afficher.
Les applets Java sont téléchargées sur ton ordinateur depuis Internet en tant que parties d'une page web. Le navigateur est suffisamment malin pour lancer son propre Java afin de les exécuter.
Dans ce chapitre, tu vas apprendre comment créer des applets sur ton ordinateur. L'annexe C explique comment publier tes pages web sur Internet pour que d'autres personnes puissent les utiliser.
Les gens naviguent sur Internet sans savoir si les pages web contiennent des applets Java ou pas, mais veulent être certains que leurs ordinateurs sont à l'abri des dégâts que pourraient causer des personnes malintentionnées en incorporant à une page une applet nuisible. C'est pourquoi les applets ont été conçues avec les limitations suivantes :
- Les applets ne peuvent pas accéder aux fichiers de ton disque dur, à moins que tu n'aies sur ton disque un fichier spécial, appelé certificat, qui leur en donne l'autorisation.
- Les applets ne peuvent se connecter qu'à l'ordinateur duquel elles ont été téléchargées.
- Les applets ne peuvent démarrer aucun des programmes situés sur ton disque dur.
Pour exécuter une applet, il te faut une classe Java écrite d'une certaine manière, un fichier texte HTML contenant la balise <applet> pointant sur cette classe et un navigateur web qui supporte Java. Tu peux aussi tester les applets dans Eclipse ou à l'aide d'un programme spécial appelé visualisateur d'applet (appletviewer). Mais avant d'apprendre à créer des applets, prenons 15 minutes pour nous familiariser avec quelques balises HTML.
IX-A. Apprendre HTML en 15 minutes▲
Imagine un instant que tu aies écrit et compilé une applet de jeu appelée Morpion. Tu dois maintenant créer le fichier HTML contenant les informations la concernant. Crée tout d'abord le fichier texte Morpion.html (à propos, Eclipse peut aussi créer des fichiers texte). Les fichiers HTML ont des noms terminés soit par .html soit par .htm. Ils contiennent en général les sections header (en-tête) et body (corps). La plupart des balises HTML ont une balise fermante correspondante, commençant par une barre oblique. Par exemple : <Head> et </Head>. Voici à quoi pourrait ressembler le fichier Morpion.html :
<HTML>
<Head>
<Title>Ma première page web</Title>
</Head>
<BODY>
Mon jeu de morpion va bientôt arriver…
</BODY>
</HTML>
Les balises peuvent être placées soit sur la même ligne, comme nous l'avons fait avec les balises <Title> et </Title>, soit sur des lignes distinctes. Ouvre ce fichier avec ton navigateur web à l'aide des menus Fichier et Ouvrir. La barre de titre bleue de la fenêtre affiche "Ma première page web" et à l'intérieur de la page sont affichés les mots "Mon jeu de morpion va bientôt arriver…" :
Modifie maintenant ce fichier en ajoutant la balise pour l'applet Morpion :
<HTML>
<Head>
<Title>Ma première page web</Title>
</Head>
<BODY>
Voici mon jeu de morpion :
<p><APPLET code
=
"Morpion.class"
width
=
300
height
=
250>
</APPLET>
</BODY>
</HTML>
L'écran n'a plus la même apparence :
Evidemment, puisque le navigateur web ne peut pas trouver Morpion.class, il affiche simplement un rectangle vide. Nous créerons cette classe un peu plus loin dans ce chapitre.
Les balises HTML sont entourées par des signes inférieur (<) et supérieur (>). Certaines balises peuvent avoir des attributs supplémentaires. La balise <APPLET> de notre exemple utilise les attributs suivants :
- code : nom de la classe Java de l'applet.
- width : largeur en pixels de la surface rectangulaire de l'écran qui sera occupée par l'applet.
- height : hauteur de la surface occupée par l'applet.
Si une applet Java est constituée de plusieurs classes, rassemble-les dans un fichier archive à l'aide du programme jar fourni avec J2SDK. Dans ce cas, l'attribut archive doit préciser le nom de cette archive. L'annexe A propose des lectures relatives aux jars.
IX-B. Choix de la librairie AWT pour écrire des applets▲
Pourquoi utiliser AWT pour écrire des applets si la librairie Swing est meilleure ? Est-il possible d'écrire des applets à l'aide de classes Swing ? Oui, c'est possible ; mais il faut savoir ceci.
Les navigateurs web sont fournis avec leur propre Java, qui supporte AWT, mais pas nécessairement les classes Swing incluses dans ton applet. Bien sûr, les utilisateurs peuvent télécharger et installer le dernier Java et il existe des convertisseurs HTML spéciaux permettant de modifier le fichier HTML pour faire pointer les navigateurs vers ce nouveau Java ; mais souhaites-tu vraiment demander aux utilisateurs de faire tout ça ? Une fois ta page web publiée sur Internet, tu ne sais pas qui peut l'utiliser. Imagine un vieux type, quelque part dans un désert avec un ordinateur vieux de 10 ans ; il laissera simplement tomber ta page, plutôt que de se lancer dans tous ces soucis d'installation. Imagine que notre applet aide à vendre des jeux en ligne et que nous ne voulions pas abandonner cette personne : elle pourrait être un client potentiel (les gens vivant dans le désert ont aussi des cartes de crédit). :
Utilise AWT si tu n'es pas sûr du type de navigateur web de tes utilisateurs.
En réalité, l'autre option consiste à demander aux utilisateurs de télécharger un plugin (module d'extension) Java spécial et de configurer leur navigateur pour utiliser ce plugin à la place du Java fourni avec leur navigateur. Tu trouveras plus d'explications à ce sujet sur ce site :
IX-C. Comment écrire des applets AWT ▲
Les applets Java AWT doivent hériter de la classe java.applet.Applet. Par exemple :
class
Morpion extends
java.applet.Applet {
}
Contrairement aux applications Java, les applets n'ont pas besoin de méthode main() car le navigateur web les télécharge et les exécute dès qu'il rencontre la balise <applet> dans une page web. Le navigateur envoie aussi des signaux aux applets quand des événements importants se produisent, par exemple quand l'applet est lancée, est repeinte, etc. Pour être sûr que l'applet réagisse à ces événements, tu dois programmer des méthodes de rappel (callback methods) spéciales : init() (initialiser), start() (démarrer), paint() (peindre), stop() (arrêter) et destroy() (détruire). Le Java du navigateur appelle ces méthodes dans les cas suivants :
- init() est appelée quand l'applet est chargée par le navigateur. Elle n'est appelée qu'une fois : elle joue donc un rôle similaire à celui des constructeurs des classes Java normales.
- start() est appelée juste après init(). Elle est aussi appelée si l'utilisateur revient à une page web après avoir visité une autre page.
- paint() est appelée quand la fenêtre de l'applet a besoin d'être affichée ou rafraîchie après une activité quelconque sur l'écran. Par exemple, l'applet a été recouverte par une autre fenêtre et le navigateur a besoin de la repeindre.
- stop() est appelée quand l'utilisateur quitte la page web contenant l'applet.
- destroy() est appelée quand le navigateur détruit l'applet. Tu n'as besoin d'écrire du code pour cette méthode que si l'applet utilise d'autres ressources, par exemple quand elle maintient une connexion avec l'ordinateur duquel elle a été téléchargée.
Même s'il n'est pas nécessaire de programmer toutes ces méthodes, chaque applet doit définir au moins init() et paint(). Voici le code d'une applet qui affiche les mots "Bonjour Monde !". Cette applet ne contient que la méthode paint(), qui reçoit une instance de l'objet Graphics du Java du navigateur. Cet objet dispose d'un tas de méthodes graphiques. L'exemple suivant utilise la méthode drawString() (dessiner une chaîne de caractères) pour dessiner le texte "Bonjour Monde !".
public
class
AppletBonjour extends
java.applet.Applet {
public
void
paint
(
java.awt.Graphics contexteGraphique) {
contexteGraphique.drawString
(
"Bonjour Monde !"
, 70
, 40
);
}
}
Crée cette classe dans Eclipse. Ensuite, dans la fenêtre Exécuter, sélectionne Applet Java dans le coin supérieur gauche, appuie sur le bouton Créer et entre AppletBonjour dans le champ Applet.
Pour tester cette applet dans le navigateur web, crée le fichier Bonjour.html dans le dossier où est enregistrée ton applet.
<HTML>
<BODY>
Voici ma première applet :<P>
<APPLET code
=
AppletBonjour.class width
=
200 height
=
100>
</APPLET>
</BODY>
</HTML>
Ouvre maintenant le fichier Bonjour.html à l'aide des menus Fichier et Ouvrir de ton navigateur.
L'écran devrait ressembler à ceci :
Crois-tu qu'après ce simple exemple nous soyons prêts pour écrire un programme de jeu ? Tu m'étonnes ! Boucle juste ta ceinture…
IX-D. Ecriture d'un jeu de morpion▲
IX-D-1. Stratégie▲
Tous les jeux utilisent un algorithme - un ensemble de règles ou une stratégie à appliquer en fonction des actions du joueur. Pour un même jeu, il peut y avoir des algorithmes simples ou très compliqués. Quand on dit que le champion du monde d'échecs Gary Kasparov joue contre un ordinateur, il joue en fait contre un programme. Des équipes d'experts essaient d'inventer des algorithmes sophistiqués pour le battre. Le jeu de morpion peut aussi être programmé selon différentes stratégies ; nous allons en utiliser la plus simple :
- Nous utilisons un plateau 3 x 3.
- L'utilisateur joue avec le symbole X et l'ordinateur avec le O.
- Pour gagner, il faut avoir complété une ligne, une colonne ou une diagonale avec le même symbole.
- Après chaque coup, le programme vérifie s'il y a un gagnant.
- S'il y a un gagnant, la combinaison gagnante est mise en surbrillance et la partie se termine.
- La partie se termine aussi s'il n'y a plus de cases libres.
- Pour faire une nouvelle partie, le joueur appuie sur le bouton Nouvelle partie.
- Quand l'ordinateur décide où placer le prochain O, il essaie de trouver une ligne, une colonne ou une diagonale où se trouvent déjà deux O pour la compléter.
- S'il n'y pas deux O alignés, l'ordinateur essaie de trouver deux X alignés afin de parer un coup gagnant du joueur en plaçant un O.
- Si aucun coup gagnant ou bloquant n'a été trouvé, l'ordinateur essaie d'occuper la case centrale, ou choisit la prochaine case vide au hasard.
IX-D-2. Code▲
Je vais juste te donner ici une brève description du programme car le code de l'applet contient de nombreux commentaires qui t'aideront à comprendre comment il fonctionne.
L'applet utilise un gestionnaire de disposition BorderLayout. La zone nord de la fenêtre contient le bouton Nouvelle partie. La zone centrale affiche neuf boutons représentant les cases et la zone sud affiche les messages :
Tous les composants de la fenêtre sont créés par la méthode init() de l'applet. Tous les événements sont traités par le récepteur ActionListener dans la méthode actionPerformed(). La méthode chercherUnGagnant() est appelée après chaque coup pour vérifier si la partie est terminée.
Les règles 8, 9 et 10 de notre stratégie sont codées dans la méthode coupOrdinateur(), qui peut avoir besoin de générer un nombre aléatoire (random number). On utilise pour cela la classe Java Math et sa méthode random().
Tu rencontreras aussi une syntaxe assez inhabituelle où plusieurs appels de méthodes sont effectués en une seule expression, comme dans cet exemple :
if
(
cases[0
].getLabel
(
).equals
(
cases[1
].getLabel
(
))){&
#8230
;}
Cette ligne raccourcit le code car elle effectue en fait les mêmes actions que l'ensemble des lignes suivantes :
String label0 =
cases[0
].getLabel
(
);
String label1 =
cases[1
].getLabel
(
);
if
(
label0.equals
(
label1)){&
#8230
;}
Dans les expressions complexes, Java évalue le code entre parenthèses avant d'effectuer d'autres calculs. La version courte de ce code cherche d'abord le résultat de l'expression entre parenthèses, puis l'utilise comme argument de la méthode equals(), qui est appliquée au résultat du premier appel à getLabel().
Même si le code du jeu occupe plusieurs pages, il n'est pas très difficile à comprendre. Lis simplement tous les commentaires qui s'y trouvent.
/**
* Un jeu de morpion sur un plateau 3x3
*/
import
java.awt.*;
import
java.awt.event.*;
import
java.applet.Applet;
public
class
Morpion extends
Applet implements
ActionListener {
Button cases[];
Button boutonNouvellePartie;
Label score;
int
casesLibresRestantes =
9
;
/**
* La méthode init est comme un constructeur pour l'applet
*/
public
void
init
(
) {
// Affecte le gestionnaire de disposition et la couleur
// de l'applet
this
.setLayout
(
new
BorderLayout
(
));
this
.setBackground
(
Color.CYAN);
// Passe la police de l'applet en style gras et taille 20
Font policeApplet =
new
Font
(
"Monospaced"
, Font.BOLD, 20
);
this
.setFont
(
policeApplet);
// Crée le bouton Nouvelle partie et enregistre
// le récepteur d'actions auprès de lui
boutonNouvellePartie =
new
Button
(
"Nouvelle partie"
);
boutonNouvellePartie.addActionListener
(
this
);
// Crée deux panneaux et un label et les agence en
// utilisant le border layout
Panel panneauSupérieur =
new
Panel
(
);
panneauSupérieur.add
(
boutonNouvellePartie);
this
.add
(
panneauSupérieur, "North"
);
Panel panneauCentral =
new
Panel
(
);
panneauCentral.setLayout
(
new
GridLayout
(
3
, 3
));
this
.add
(
panneauCentral, "Center"
);
score =
new
Label
(
"A vous de jouer !"
);
this
.add
(
score, "South"
);
// Crée un tableau pour stocker les références des
// 9 boutons
cases =
new
Button[9
];
// Instancie les boutons, stocke leurs références dans le
// tableau, enregistre le récepteur auprès d'eux, peint
// les boutons en orange et les ajoute au panneau central
for
(
int
i =
0
; i <
9
; i++
) {
cases[i]=
new
Button
(
);
cases[i].addActionListener
(
this
);
cases[i].setBackground
(
Color.ORANGE);
panneauCentral.add
(
cases[i]);
}
}
/**
* Cette méthode traite tous les événements d'action
*
@param
événement
l'événement à traiter
*/
public
void
actionPerformed
(
ActionEvent événement) {
Button leBouton =
(
Button) événement.getSource
(
);
// S'agit-il du bouton Nouvelle partie ?
if
(
leBouton ==
boutonNouvellePartie) {
for
(
int
i =
0
; i <
9
; i++
) {
cases[i].setEnabled
(
true
);
cases[i].setLabel
(
""
);
cases[i].setBackground
(
Color.ORANGE);
}
casesLibresRestantes =
9
;
score.setText
(
"A vous de jouer !"
);
boutonNouvellePartie.setEnabled
(
false
);
return
; // Sort de la méthode
}
String gagnant =
""
;
// S'agit-il de l'une des cases ?
for
(
int
i =
0
; i <
9
; i++
) {
if
(
leBouton ==
cases[i]) {
cases[i].setLabel
(
"X"
);
gagnant =
chercherUnGagnant
(
);
if
(!
""
.equals
(
gagnant)) {
terminerLaPartie
(
);
}
else
{
coupOrdinateur
(
);
gagnant =
chercherUnGagnant
(
);
if
(!
""
.equals
(
gagnant)) {
terminerLaPartie
(
);
}
}
break
;
}
}
// Fin de la boucle for
if
(
gagnant.equals
(
"X"
)) {
score.setText
(
"Vous avez gagné !"
);
}
else
if
(
gagnant.equals
(
"O"
)) {
score.setText
(
"Vous avez perdu !"
);
}
else
if
(
gagnant.equals
(
"T"
)) {
score.setText
(
"Partie nulle !"
);
}
}
// Fin de actionPerformed
/**
* Cette méthode est appelée après chaque coup joué pour
* voir s'il y a un gagnant. Elle vérifie pour chaque ligne,
* colonne et diagonale, s'il y a trois symboles identiques
*
@return
"X", "O", "T" (terminé, partie nulle) ou "" (pas
* fini)
*/
String chercherUnGagnant
(
) {
String leGagnant =
""
;
casesLibresRestantes--
;
// Vérifie la ligne 1 - éléments 0, 1 et 2 du tableau
if
(!
cases[0
].getLabel
(
).equals
(
""
) &&
cases[0
].getLabel
(
).equals
(
cases[1
].getLabel
(
)) &&
cases[0
].getLabel
(
).equals
(
cases[2
].getLabel
(
))) {
leGagnant =
cases[0
].getLabel
(
);
montrerGagnant
(
0
, 1
, 2
);
// Vérifie la ligne 2 - éléments 3, 4 et 5 du tableau
}
else
if
(!
cases[3
].getLabel
(
).equals
(
""
) &&
cases[3
].getLabel
(
).equals
(
cases[4
].getLabel
(
)) &&
cases[3
].getLabel
(
).equals
(
cases[5
].getLabel
(
))) {
leGagnant =
cases[3
].getLabel
(
);
montrerGagnant
(
3
, 4
, 5
);
// Vérifie la ligne 3 - éléments 6, 7 et 8 du tableau
}
else
if
(!
cases[6
].getLabel
(
).equals
(
""
) &&
cases[6
].getLabel
(
).equals
(
cases[7
].getLabel
(
)) &&
cases[6
].getLabel
(
).equals
(
cases[8
].getLabel
(
))) {
leGagnant =
cases[6
].getLabel
(
);
montrerGagnant
(
6
, 7
, 8
);
// Vérifie la colonne 1 - éléments 0, 3 et 6 du tableau
}
else
if
(!
cases[0
].getLabel
(
).equals
(
""
) &&
cases[0
].getLabel
(
).equals
(
cases[3
].getLabel
(
)) &&
cases[0
].getLabel
(
).equals
(
cases[6
].getLabel
(
))) {
leGagnant =
cases[0
].getLabel
(
);
montrerGagnant
(
0
, 3
, 6
);
// Vérifie la colonne 2 - éléments 1, 4 et 7 du tableau
}
else
if
(!
cases[1
].getLabel
(
).equals
(
""
) &&
cases[1
].getLabel
(
).equals
(
cases[4
].getLabel
(
)) &&
cases[1
].getLabel
(
).equals
(
cases[7
].getLabel
(
))) {
leGagnant =
cases[1
].getLabel
(
);
montrerGagnant
(
1
, 4
, 7
);
// Vérifie la colonne 3 - éléments 2, 5 et 8 du tableau
}
else
if
(!
cases[2
].getLabel
(
).equals
(
""
) &&
cases[2
].getLabel
(
).equals
(
cases[5
].getLabel
(
)) &&
cases[2
].getLabel
(
).equals
(
cases[8
].getLabel
(
))) {
leGagnant =
cases[2
].getLabel
(
);
montrerGagnant
(
2
, 5
, 8
);
// Vérifie la première diagonale - éléments 0, 4 et 8
}
else
if
(!
cases[0
].getLabel
(
).equals
(
""
) &&
cases[0
].getLabel
(
).equals
(
cases[4
].getLabel
(
)) &&
cases[0
].getLabel
(
).equals
(
cases[8
].getLabel
(
))) {
leGagnant =
cases[0
].getLabel
(
);
montrerGagnant
(
0
, 4
, 8
);
// Vérifie la seconde diagonale - éléments 2, 4 et 6
}
else
if
(!
cases[2
].getLabel
(
).equals
(
""
) &&
cases[2
].getLabel
(
).equals
(
cases[4
].getLabel
(
)) &&
cases[2
].getLabel
(
).equals
(
cases[6
].getLabel
(
))) {
leGagnant =
cases[2
].getLabel
(
);
montrerGagnant
(
2
, 4
, 6
);
}
else
if
(
casesLibresRestantes ==
0
) {
return
"T"
; // Partie nulle
}
return
leGagnant;
}
/**
* Cette méthode applique un ensemble de règles afin de
* trouver le meilleur coup pour l'ordinateur. Si un bon
* coup ne peut être trouvé, elle choisit une case au
* hasard.
*/
void
coupOrdinateur
(
) {
int
caseSélectionnée;
// L'ordinateur essaie d'abord de trouver une case
// vide près de deux case marquées "O" pour gagner
caseSélectionnée =
trouverCaseVide
(
"O"
);
// S'il n'y a pas deux "O" alignés, essaie au moins
// d'empêcher l'adversaire d'aligner trois "X" en
// plaçant un "O" près de deux "X"
if
(
caseSélectionnée ==
-
1
) {
caseSélectionnée =
trouverCaseVide
(
"X"
);
}
// Si caseSélectionnée vaut toujours -1, essaie d'occuper
// la case centrale
if
((
caseSélectionnée ==
-
1
)
&&
(
cases[4
].getLabel
(
).equals
(
""
))) {
caseSélectionnée =
4
;
}
// Pas de chance avec la case centrale non plus...
// Choisit une case au hasard
if
(
caseSélectionnée ==
-
1
) {
caseSélectionnée =
choisirCaseAuHasard
(
);
}
cases[caseSélectionnée].setLabel
(
"O"
);
}
/**
* Cette méthode examine chaque ligne, colonne et diagonale
* pour voir si elle contient deux cases avec le même label
* et une case vide.
*
@param
joueur
"X" pour l'utilisateur ou "O" pour
* l'ordinateur
*
@return
numéro de la case vide à utiliser ou le nombre
* négatif -1 si la recherche est infructueuse
*/
int
trouverCaseVide
(
String joueur) {
int
poids[] =
new
int
[9
];
for
(
int
i =
0
; i <
9
; i++
) {
if
(
cases[i].getLabel
(
).equals
(
"O"
))
poids[i] =
-
1
;
else
if
(
cases[i].getLabel
(
).equals
(
"X"
))
poids[i] =
1
;
else
poids[i] =
0
;
}
int
deuxPoids =
joueur.equals
(
"O"
) ? -
2
: 2
;
// Regarde si la ligne 1 a 2 cases identiques et une vide
if
(
poids[0
] +
poids[1
] +
poids[2
] ==
deuxPoids) {
if
(
poids[0
] ==
0
)
return
0
;
else
if
(
poids[1
] ==
0
)
return
1
;
else
return
2
;
}
// Regarde si la ligne 2 a 2 cases identiques et une vide
if
(
poids[3
] +
poids[4
] +
poids[5
] ==
deuxPoids) {
if
(
poids[3
] ==
0
)
return
3
;
else
if
(
poids[4
] ==
0
)
return
4
;
else
return
5
;
}
// Regarde si la ligne 3 a 2 cases identiques et une vide
if
(
poids[6
] +
poids[7
] +
poids[8
] ==
deuxPoids) {
if
(
poids[6
] ==
0
)
return
6
;
else
if
(
poids[7
] ==
0
)
return
7
;
else
return
8
;
}
// Regarde si la colonne 1 a 2 cases identiques et une vide
if
(
poids[0
] +
poids[3
] +
poids[6
] ==
deuxPoids) {
if
(
poids[0
] ==
0
)
return
0
;
else
if
(
poids[3
] ==
0
)
return
3
;
else
return
6
;
}
// Regarde si la colonne 2 a 2 cases identiques et une vide
if
(
poids[1
] +
poids[4
] +
poids[7
] ==
deuxPoids) {
if
(
poids[1
] ==
0
)
return
1
;
else
if
(
poids[4
] ==
0
)
return
4
;
else
return
7
;
}
// Regarde si la colonne 3 a 2 cases identiques et une vide
if
(
poids[2
] +
poids[5
] +
poids[8
] ==
deuxPoids) {
if
(
poids[2
] ==
0
)
return
2
;
else
if
(
poids[5
] ==
0
)
return
5
;
else
return
8
;
}
// Regarde si la diagonale 1 a 2 cases identiques et une
// vide
if
(
poids[0
] +
poids[4
] +
poids[8
] ==
deuxPoids) {
if
(
poids[0
] ==
0
)
return
0
;
else
if
(
poids[4
] ==
0
)
return
4
;
else
return
8
;
}
// Regarde si la diagonale 2 a 2 cases identiques et une
// vide
if
(
poids[2
] +
poids[4
] +
poids[6
] ==
deuxPoids) {
if
(
poids[2
] ==
0
)
return
2
;
else
if
(
poids[4
] ==
0
)
return
4
;
else
return
6
;
}
// Il n'y a pas de cases alignées identiques
return
-
1
;
}
// Fin de trouverCaseVide()
/**
* Cette méthode sélectionne une case vide quelconque.
*
@return
un numéro de case choisi au hasard
*/
int
choisirCaseAuHasard
(
) {
boolean
caseVideTrouvée =
false
;
int
caseSélectionnée =
-
1
;
do
{
caseSélectionnée =
(
int
) (
Math.random
(
) *
9
);
if
(
cases[caseSélectionnée].getLabel
(
).equals
(
""
)) {
caseVideTrouvée =
true
; // Pour terminer la boucle
}
}
while
(!
caseVideTrouvée);
return
caseSélectionnée;
}
// Fin de choisirCaseAuHasard()
/**
* Cette méthode affiche la ligne gagnante en surbrillance.
*
@param
gagnante1
première case à montrer.
*
@param
gagnante2
deuxième case à montrer.
*
@param
gagnante3
troisième case à montrer.
*/
void
montrerGagnant
(
int
gagnante1, int
gagnante2, int
gagnante3) {
cases[gagnante1].setBackground
(
Color.CYAN);
cases[gagnante2].setBackground
(
Color.CYAN);
cases[gagnante3].setBackground
(
Color.CYAN);
}
// Désactive les cases et active le bouton Nouvelle partie
void
terminerLaPartie
(
) {
boutonNouvellePartie.setEnabled
(
true
);
for
(
int
i =
0
; i <
9
; i++
) {
cases[i].setEnabled
(
false
);
}
}
}
// Fin de la classe
Félicitations ! Tu as terminé ton premier jeu en Java.
Tu peux exécuter cette applet directement depuis Eclipse ou en ouvrant le fichier Morpion.html que nous avons créé au début de ce chapitre (copie simplement les fichiers Morpion.html et Morpion.class dans le même répertoire). Notre classe Morpion a un petit bogue (bug) - tu pourrais même ne pas t'en apercevoir, mais je suis sûr qu'il sera corrigé lorsque tu auras terminé le deuxième exercice ci-dessous.
Notre classe Morpion utilise une stratégie simple parce que notre objectif est juste d'apprendre à programmer. Mais si tu souhaites améliorer ce jeu, applique l'algorithme appelé minimax qui te permet de choisir le meilleur coup pour l'ordinateur. La description de cette stratégie n'est pas du ressort de ce livre, mais tu peux facilement la trouver sur le web.
IX-E. Autres lectures▲
Applets Java : http://java.sun.com/docs/books/tutorial/applet/ Classe Java Math |
IX-F. Exercices ▲
IX-G. Exercices pour les petits malins▲
1. Réécris le Morpion en remplaçant le tableau à une dimension qui stocke les neuf boutons : JButton cases[] par un tableau à deux dimensions 3 x 3 : JButton cases[][] Va sur le web pour t'informer à propos des tableaux multidimensionnels. |