Voir le résultat Retour à la page du projet
Afficher/Masquer les commentaires
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8"/>
<title>Jeu de bataille navale</title>
<meta name="description" content="Un jeu de bataille navale programmé en JavaScript."/>
<style>
Tous les éléments td
de la table du jeu sont de classe caseBataille
.
Cela permet d'uniformiser les dimensions de toutes les cases.
Le réglage text-align:center
est utilisé pour que les nombres et lettres affichées
sur la première ligne et la première colonne du tableau soient centrés dans les cases.
.caseBataille{
width:20px;
height:20px;
text-align:center;
}
</style>
</head>
<body>
Voici l'élément table
du jeu. L'attribut border="1"
indique que les bordures des
éléments du tableau doivent être affichées.
<table id="plateau" border="1">
L'élément table
contient des éléments tr
qui représentent les lignes. Chaque élément tr
contient des éléments td
qui représentent les différentes cases de la ligne. Comme nous l'avons
déjà dit tous les éléments td
sont de classe caseBataille
ce qui entraîne que la règle
CSS vue plus haut s'applique.
<tr>
<td></td>
<td class="caseBataille">A</td>
<td class="caseBataille">B</td>
<td class="caseBataille">C</td>
<td class="caseBataille">D</td>
<td class="caseBataille">E</td>
<td class="caseBataille">F</td>
<td class="caseBataille">G</td>
<td class="caseBataille">H</td>
<td class="caseBataille">I</td>
<td class="caseBataille">J</td>
</tr>
<tr>
<td class="caseBataille">1</td>
Les éléments td
des cases du jeu sont identifiés par leur position selon le système de repérage utilisé
à la bataille navale : lettre de la colonne suivie du numéro de la ligne.
<td class="caseBataille" id="A1"></td>
<td class="caseBataille" id="B1"></td>
<td class="caseBataille" id="C1"></td>
<td class="caseBataille" id="D1"></td>
<td class="caseBataille" id="E1"></td>
<td class="caseBataille" id="F1"></td>
<td class="caseBataille" id="G1"></td>
<td class="caseBataille" id="H1"></td>
<td class="caseBataille" id="I1"></td>
<td class="caseBataille" id="J1"></td>
</tr>
<tr>
<td class="caseBataille">2</td>
<td class="caseBataille" id="A2"></td>
<td class="caseBataille" id="B2"></td>
<td class="caseBataille" id="C2"></td>
<td class="caseBataille" id="D2"></td>
<td class="caseBataille" id="E2"></td>
<td class="caseBataille" id="F2"></td>
<td class="caseBataille" id="G2"></td>
<td class="caseBataille" id="H2"></td>
<td class="caseBataille" id="I2"></td>
<td class="caseBataille" id="J2"></td>
</tr>
<tr>
<td class="caseBataille">3</td>
<td class="caseBataille" id="A3"></td>
<td class="caseBataille" id="B3"></td>
<td class="caseBataille" id="C3"></td>
<td class="caseBataille" id="D3"></td>
<td class="caseBataille" id="E3"></td>
<td class="caseBataille" id="F3"></td>
<td class="caseBataille" id="G3"></td>
<td class="caseBataille" id="H3"></td>
<td class="caseBataille" id="I3"></td>
<td class="caseBataille" id="J3"></td>
</tr>
<tr>
<td class="caseBataille">4</td>
<td class="caseBataille" id="A4"></td>
<td class="caseBataille" id="B4"></td>
<td class="caseBataille" id="C4"></td>
<td class="caseBataille" id="D4"></td>
<td class="caseBataille" id="E4"></td>
<td class="caseBataille" id="F4"></td>
<td class="caseBataille" id="G4"></td>
<td class="caseBataille" id="H4"></td>
<td class="caseBataille" id="I4"></td>
<td class="caseBataille" id="J4"></td>
</tr>
<tr>
<td class="caseBataille">5</td>
<td class="caseBataille" id="A5"></td>
<td class="caseBataille" id="B5"></td>
<td class="caseBataille" id="C5"></td>
<td class="caseBataille" id="D5"></td>
<td class="caseBataille" id="E5"></td>
<td class="caseBataille" id="F5"></td>
<td class="caseBataille" id="G5"></td>
<td class="caseBataille" id="H5"></td>
<td class="caseBataille" id="I5"></td>
<td class="caseBataille" id="J5"></td>
</tr>
<tr>
<td class="caseBataille">6</td>
<td class="caseBataille" id="A6"></td>
<td class="caseBataille" id="B6"></td>
<td class="caseBataille" id="C6"></td>
<td class="caseBataille" id="D6"></td>
<td class="caseBataille" id="E6"></td>
<td class="caseBataille" id="F6"></td>
<td class="caseBataille" id="G6"></td>
<td class="caseBataille" id="H6"></td>
<td class="caseBataille" id="I6"></td>
<td class="caseBataille" id="J6"></td>
</tr>
<tr>
<td class="caseBataille">7</td>
<td class="caseBataille" id="A7"></td>
<td class="caseBataille" id="B7"></td>
<td class="caseBataille" id="C7"></td>
<td class="caseBataille" id="D7"></td>
<td class="caseBataille" id="E7"></td>
<td class="caseBataille" id="F7"></td>
<td class="caseBataille" id="G7"></td>
<td class="caseBataille" id="H7"></td>
<td class="caseBataille" id="I7"></td>
<td class="caseBataille" id="J7"></td>
</tr>
<tr>
<td class="caseBataille">8</td>
<td class="caseBataille" id="A8"></td>
<td class="caseBataille" id="B8"></td>
<td class="caseBataille" id="C8"></td>
<td class="caseBataille" id="D8"></td>
<td class="caseBataille" id="E8"></td>
<td class="caseBataille" id="F8"></td>
<td class="caseBataille" id="G8"></td>
<td class="caseBataille" id="H8"></td>
<td class="caseBataille" id="I8"></td>
<td class="caseBataille" id="J8"></td>
</tr>
<tr>
<td class="caseBataille">9</td>
<td class="caseBataille" id="A9"></td>
<td class="caseBataille" id="B9"></td>
<td class="caseBataille" id="C9"></td>
<td class="caseBataille" id="D9"></td>
<td class="caseBataille" id="E9"></td>
<td class="caseBataille" id="F9"></td>
<td class="caseBataille" id="G9"></td>
<td class="caseBataille" id="H9"></td>
<td class="caseBataille" id="I9"></td>
<td class="caseBataille" id="J9"></td>
</tr>
<tr>
<td class="caseBataille">10</td>
<td class="caseBataille" id="A10"></td>
<td class="caseBataille" id="B10"></td>
<td class="caseBataille" id="C10"></td>
<td class="caseBataille" id="D10"></td>
<td class="caseBataille" id="E10"></td>
<td class="caseBataille" id="F10"></td>
<td class="caseBataille" id="G10"></td>
<td class="caseBataille" id="H10"></td>
<td class="caseBataille" id="I10"></td>
<td class="caseBataille" id="J10"></td>
</tr>
</table>
<br/>
Ici nous avons la zone de saisie et le bouton.
<input type="text" id="coup" /><input type="button" id="jouer" value="Valider"/>
Le code JavaScript du programme figure dans le fichier séparé : bataille.js
<script src="bataille.js"></script>
</body>
</html>
Afficher/Masquer les commentaires
C'est le tableau plateau
qui contient l'état des cases du jeu. Le codage est le suivant :
0 : case eau,
1 : case de porte-avions,
2 : case de croiseur,
3 : case de contre-torpilleur,
4 : case de sous-marin,
5 : case torpilleur.
En outre une case déjà jouée est codée par un nombre négatif : -1 pour le porte-avions, -2 pour le croiseur, etc.
Une case eau jouée est codée -6.
Le contenu initial est généré de façon aléatoire en appelant la fonction placeBateaux
.
var plateau=[];
placeBateaux();
Le tableau navires
contient le nombre de cases restantes à découvrir pour chacun des bateaux.
navires[0]
: ne sert à rien,
navires[1]
: 5 cases pour le porte-avion,
navires[2]
: 4 cases pour le croiseur,
navires[3]
: 3 cases pour le contre-torpilleur,
navires[4]
: 3 cases pour le sous-marin,
navires[5]
: 2 cases pour le torpilleur.
var navires=[0,5,4,3,3,2];
Nombre total de cases de navires trouvées par le joueur, pour gagner il doit découvrir les 17 cases de bateaux.
var touches=0;
La variable finPartie
est mise à la valeur true
lorsque la partie est terminée.
La variable nbCoups
, comme son nom l'indique, compte le nombre de coups joués.
var finPartie=false;
var nbCoups=0;
Le tableau message
contient tous les messages possibles selon les différentes situations.
var message=[];
message[0]="A l'eau !";
message[1]="Porte-avion touché !";
message[2]="Croiseur touché !";
message[3]="Contre-torpilleur touché !";
message[4]="Sous-marin touché !";
message[5]="Torpilleur touché !";
message[6]="Case déjà jouée !";
message[11]="Porte-avion coulé !";
message[12]="Croiseur coulé !";
message[13]="Contre-torpilleur coulé !";
message[14]="Sous-marin coulé !";
message[15]="Torpilleur coulé !";
Les lignes qui suivent mettent en place le dispositif d'interaction du joueur avec le programme.
le coup proposé par le joueur (saisi dans la zone de texte) est joué en appelant jouerCoup
,
cela peut être déclenché soit en appuyant sur le bouton, soit en appuyant sur la touche "entrée".
la fonction attenteCoup
remet l'interface utilisateur prête à recevoir une nouvelle
proposition du joueur : la zone de saisie est vidée et elle reçoit le curseur.
var coup=document.getElementById("coup");
var jouer=document.getElementById("jouer");
jouer.onclick=function(){
jouerCoup(coup.value);
attenteCoup();
}
coup.onkeypress=function(event){
if(event.keyCode==13){
jouer.onclick(); //entrée c'est l'équivalent d'un clic sur le bouton
}
}
function attenteCoup(){
coup.value="";
coup.focus();
}
conversion(position)
Fonction pour convertir une position au format "bataille navale" en position au format
numéros de ligne/colonne du tableau plateau
.
Paramètre : une chaine de caractères qui doit contenir une position au format "bataille navale" comme par exemple A1, C5, etc.
Retour : un objet contenant deux propriétés colonne
et ligne
qui indiquent
la position correspondante dans le tableau plateau
.
function conversion(position){
La lettre de colonne est précisée par le premier caractère de position
, l'instruction charCodeAt(0)
retourne le code ASCII de cette lettre (en position 0 dans la chaîne). Le code de A est 65, de B est 66 etc., du coup en retranchant
65 on obtient le numéro de colonne de 0 à 9.
var colonne=position.charCodeAt(0)-65;
Le numéro de ligne figure dans position
à partir du caractère numéroté 1, l'instruction
slice(1)
donne cette partie de la chaîne de caractères ; avec le parseInt
nous la convertissons
en nombre entier. A la bataille navale le premier numéro de ligne est 1, par contre
dans le tableau la numérotation commence à 0, donc nous retranchons 1 pour terminer
la conversion.
var ligne=parseInt(position.slice(1))-1;
Nous retournons un objet avec les deux propriétés colonne
et ligne
.
return {colonne:colonne, ligne:ligne};
}
getCodeCase(position)
Fonction pour connaître le code de l'état d'une case du jeu.
Paramètre :
position
: position d'une case au format "bataille navale".
Retour : code de l'état de la case obtenu depuis le tableau plateau
.
function getCodeCase(position){
var c=conversion(position);
return plateau[c.ligne][c.colonne];
}
setCodeCase(position,valeur)
Fonction pour définir le code de l'état d'une case du jeu.
Paramètres :
position
: position d'une case au format "bataille navale".
valeur
: code de l'état à attribuer à cette case (dans le tableau plateau
).
function setCodeCase(position,valeur){
var c=conversion(position);
plateau[c.ligne][c.colonne]=valeur;
}
majVueJeu(position,situation)
Fonction pour mettre à jour l'affichage du jeu et informer le joueur.
Paramètres :
position
: position de la case qui doit être mise à jour à l'affichage
(au format "bataille navale").
situation
: numéro de la situation de jeu (les différentes situations sont numérotées entre 0 et 15).
function majVueJeu(position,situation){
Lorsque la partie est terminée finPartie
vaut true
et le joueur est informé par un ajout
au message. Le joueur peut alors rejouer grâce à l'instruction location.reload()
qui recharge tout simplement la page.
Dans le cas contraire seul le message de situation est affiché.
if(finPartie){
alert(message[situation]+"\nVous avez coulé tous les navires en "+nbCoups+" coups");
location.reload();
}else{
alert(message[situation]);
}
Par défaut la nouvelle couleur de la case est rouge, sauf si le code de la case vaut -6 ("à l'eau") où elle est bleue claire.
var couleur="#FF0000";
if (getCodeCase(position)==-6){couleur="#BBBBFF";}
document.getElementById(position).style.backgroundColor=couleur;
}
jouerCoup(position)
Fonction qui contient la logique du jeu. Cette fonction est exécutée chaque fois que le joueur fait une proposition.
Paramètre :
position
: position de la case proposée par le joueur au format "bataille navale".
function jouerCoup(position){
nbCoups++;
var codeCase=getCodeCase(position);
Par défaut le numéro de situation prend la valeur du code de l'état de la case.
var situation=codeCase;
si la case est à l'état 0 : c'est de l'eau, elle devient une case "à l'eau" (codée -6),
si la case est celle d'un navire (états 1 à 5), c'est touché :
le navire perd un élément,
si le nombre d'éléments du navire tombe à 0, le numéro de situation est augmenté de 10 : en effet les messages qui indiquent qu'un navire est coulé sont numérotés de 11 à 15,
le code de l'état de la case est opposé,
le nombre total de cases "touché" est incrémenté,
si les 17 éléments de bateau ont été trouvés la variable finPartie
prend la valeur true
.
autrement, le joueur a proposé une case déjà jouée, ce qui correspond à la situation numérotée 6.
switch(codeCase){
case 0:
setCodeCase(position,-6);
break;
case 1: case 2: case 3: case 4: case 5:
navires[codeCase]--;
if(navires[codeCase]==0){situation+=10;}
setCodeCase(position,-codeCase);
touches++;
if(touches==17){finPartie=true;}
break;
default:
situation=6;
}
Une fois les données du jeu mises à jour et le numéro de situation déterminé,
nous appelons la fonction majVueJeu
pour communiquer au joueur le résultat de son action
via l'interface utilisateur.
majVueJeu(position,situation);
}
placeBateau(ligneDepart,colonneDepart,vertical,code,longueur)
Fonction qui tente de placer dans le tableau plateau
les codes de cases associés à un bateau.
Paramètres :
ligneDepart
,colonneDepart
: position de départ du bateau dans le tableau.
vertical
: si ce paramètre vaut true
le bateau est placé verticalement, s'il vaut
false
il est placé horizontalemment.
code
: code du bateau (1 pour le porte-avions, 2 pour le croiseur, etc.)
longueur
: nombre de cases occupées par le bateau (5 pour le porte-avions, 4 pour le croiseur, etc.)
Retour : true
ou false
selon que le placement a réussi ou non.
function placeBateau(ligneDepart,colonneDepart,vertical,code,longueur){
var incrementLigne,incrementColonne;
var succes=true;
Définition des incréments en ligne et en colonne pour calculer les différentes positions des éléments du bateau à partir de la position de départ et selon qu'il est placé verticalement ou horizontalement.
if(vertical){
incrementLigne=1;
incrementColonne=0;
}else{
incrementLigne=0;
incrementColonne=1;
}
Boucle pour tester si toutes les cases où doit prendre place le bateau son disponibles.
Si une case est déjà occupée, nous sortons immédiatement
de la boucle avec succes
qui vaut false
pour indiquer l'échec.
for(var i=0;i<longueur;i++){
if(plateau[ligneDepart+i*incrementLigne][colonneDepart+i*incrementColonne]!=0){
succes=false;
break;
}
}
En cas de succès le tableau plateau
est réellement modifié avec le code du
navire aux emplacements qui sont donc libres.
if(succes){
for(var i=0;i<longueur;i++){
plateau[ligneDepart+i*incrementLigne][colonneDepart+i*incrementColonne]=code;
}
}
return succes;
}
positionHasardBateau(code,longueur)
Fonction qui positionne au hasard un navire dans le tableau plateau
.
Cette fonction est appelée par la fonction placeBateaux
pour positionner aléatoirement
les 5 navires au début de la partie.
Paramètres :
code
: code des cases du navire à placer : 1 pour le porte-avions, 2 pour un croiseur, etc.
longueur
: nombre de cases du navire : 5 pour le porte-avions, 4 pour le croiseur, etc.
function positionHasardBateau(code,longueur){
var departLimite,depart;
var succes=false;
La position de départ du bateau est tirée au sort, mais il n'est pas toujours possible de le placer
car il ne faut pas qu'une des cases se superpose avec une case d'un autre bateau
déjà placé. La fonction placeBateau
tente de placer le navire et retourne true
ou false
selon
que le placement a réussi ou non.
La boucle while
permet de tirer de nouvelles positions pour le bateau jusqu'à ce qu'il puisse
être placé.
while(!succes){
La variable departLimite
tient compte de la longueur du bateau dans le tirage aléatoire,
par exemple si le bateau occupe 3 cases, departLimite
sera un nombre entier au hasard entre 0 et 7 :
horizontalement ou verticalement le bateau ne peut pas être placé à moins de 3 cases du bord.
departLimite=Math.floor(Math.random()*(11-longueur));
depart=Math.floor(Math.random()*10);
Equiprobablement, nous tentons de placer le bateau horizontalement ou verticalement.
if(Math.random()<0.5){
succes=placeBateau(departLimite,depart,true,code,longueur);
}else{
succes=placeBateau(depart,departLimite,false,code,longueur);
}
}
}
placeBateaux()
Fonction qui initialise le tableau des cases du jeu (tableau plateau
)
en positionnant au hasard les 5 navires.
function placeBateaux(){
Tableau rempli de 0.
for(var ligne=0;ligne<=9;ligne++){
plateau[ligne]=[0,0,0,0,0,0,0,0,0,0];
}
Placement au hasard des 5 bateaux.
positionHasardBateau(5,2);
positionHasardBateau(3,3);
positionHasardBateau(4,3);
positionHasardBateau(2,4);
positionHasardBateau(1,5);
}
Fonction appelée au chargement de la page pour donner le curseur à la zone de saisie.
attenteCoup();