NUMERIQUE ET SCIENCES INFORMATIQUES

Niveau : 1ère générale, enseignement de spécialité NSI

 

D
É
C
O
N
N
E
C
T
É

Chapitre 10 : Projet jeu 2048

But du jeu:

Cliquez sur l'image ci-dessous pour jouer

2048

Algorithme du jeu :

Début
    1. Initialiser le jeu 2. Afficher la grille du jeu 3. Détecter l'état des touches directionnelles 4. Déplacer les tuiles dans le sens choisi 5. Additionner les tuiles voisines ayant le même chiffre 6. Déplacer les tuiles une nouvelle fois 7. Vérifier si 2048 a été atteint ou si la grille est complète et que les tuiles ne peuvent plus se déplacer 8. Placer aléatoirement une nouvelle tuile portant le chiffre 2 ou 4 dans la grille (2 a plus de probabilité de sortir que 4) 9. Reprendre à partir du point 2 tant que la partie n'est pas terminée 10. Sinon reprendre au point 1 si le joueur décide de recommencer
Fin

Codage des fonctions du jeu en javascript :

On choisira de séparer le code javascript du fichier html pour plus de lisibilité

1. Initialisation

La variable grille contient les chiffres de chaque case de la grille c'est un tableau à 2 dimensions dont le format est format :
var grille = [[val1,val2,..],[val5,..],[...],[...]];

Dans la zone texte, initialisez la variable grille qui se trouvera dans le code javascript, en mettant un 0 dans chaque case


2. Page html du jeu 2048 :

Il s'agit de créer un tableau vide, contenant 4 lignes et 4 colonnes et de les identifier comme suit :

id="0"
id="1"
id="2"
id="3"
id="4" id="5" id="6" id="7"
id="8" id="9" id="10" id="11"
id="12" id="13" id="14" id="15"

Ecrire ci-dessous le code HTML permettant d'afficher le tableau ci-dessus avec les bons identifiants :

Rappel : pour identifier une colonne d'une table, on utilise le code suivant <td id="xyz"> où "xyz" est son identifiant.


3. Afficher la grille du jeu

Algorithme

fonction dessine_grille()
    pour la variable y variant de 0 à 3
      pour la vaiable x variant de 0 à 3
        c ← String(grille[x][y]) dest ← document.getElementById(String(y*4+x)) dest.innerHTML ← "<img src='img/"+c+".png' alt='"+c+"'>"
Fin de la fonction

Instruction for en javascript :

Exemple :

function somme(n){
	// permet de faire la somme des n premiers entiers non nuls
	// le résultat doit donner s = n(n+1)/2
	s=0;
	for (i=1;i<=n;i++){
		s+=i;
	}
	return(s);
}

console.log(somme(10));
55

Pour vérifier si le code ne comporte pas d'erreurs, appuyez sur F12 du clavier et afficher la console

Résultat :

Modifier la variable grille en y stockant des 2, 4, 8 ou 16 ... puis testez une nouvelle fois pour vérifier le fonctionnement

3. Lire l'état des touches directionnelles du clavier

Copier-coller le code javascript suivant dans la fenêtre ci-dessous pour activer la prise et traiter les évènement du clavier :

window.addEventListener("keydown", function(event) {detection_touches(event);}, true);
function detection_touches(event){
	// Traite les touches de direction enfoncées
	// Appelle les fonctions du jeu et contrôle la fin de la partie	
	  var x = event.key;
	  //event.preventDefault()    // à n'enlever qu'à la fin du TP !!
	  var direction={'ArrowLeft':0,'ArrowRight':2,'ArrowDown':1,'ArrowUp':3};
	  console.log(direction[x]);
}

Enregistrez le code javascript, puis appuyer sur F12 et sélectionner console. Cliquer sur la page html pour donner le "focus", puis appuyer sur les touches directionnelles pour vérifier le fonctionnement

Expliquer pourquoi la console affiche des chiffres. Pour vous aider vous pouvez insérer une commande console.log(x)


4. Déplacement des tuiles

Il s'agit de la fonction centrale du jeu

Déplacement vers la gauche des tuiles

Prenons un exemple, la grille se trouve dans l'état suivant : grille=[[2,2,0,4],[4,2,0,2],[4,0,0,8],[0,4,4,0]], imaginons qu'on appuie sur la flèche de gauche

Etat avant

2204
4202
4008
0440

Etat après

4400
4400
4800
8000

 

La méthode est de traiter les données ligne par ligne : prenons la 1ère ligne [2,2,0,4]

Algorithme de la fonction decale_zeros(ligne)
fonction decale_zeros(ligne)
	
	paramètre d'entrée :  une ligne de la grille
	paramètre de sortie:  la variable ligne
	
	début
		pour n variant de 2 à 0 faire
			si ligne[n]==0 alors					
				enlever cet élément de la ligne		
				ajouter 0 à la fin de la ligne	
			fin si
		fin pour
		retourne ligne
	fin
				

Exemple

var n=2;
var tab=[1,2,3,4];
if (tab[n]==3){
	ligne.splice(n,1);
	console.log(tab);
	ligne.push(3);
	console.log(tab);
}
1,2,4
1,2,4,3

Au début de la page mettre la variable var grille=[[2,2,0,4],[4,2,0,2],[4,0,0,8],[0,4,4,0]]; un peu plus bas cliquer sur "enregistrer les codes" puis tester la fonction decale_zeros





Algoritme de la fonction addition(ligne)
fonction addition(ligne)
	
	paramètre d'entrée :  une ligne de la grille avec les zéros décalés à droite
	paramètre de sortie:  la variable ligne
	
	début
		pour n variant de 0 à 2 faire
			si ligne[n]==ligne[n+1] alors
				ligne[n] ← ligne[n]+ligne[n+1]
				ligne[n+1] ← 0
			fin si
		fin pour
	retourne ligne
	fin



Remarque : Si on clique plusieurs fois sur le bouton Tester, on remarque que le la ligne du tableau grille[0] change et est remplacé par le contenu de la variable ligne. La variable ligne utilisée dans la fonction pointe directement vers les adresses mémoire de grille[0].
On peut le mettre en évidence en ajoutant deux lignes console.log(String(grille[0])); juste avant les lignes for et return et afficher la console F12
On pourrait presque se passer du return, mais laissez-le à cause des tests qui les utilisent

Déplacement vers le bas des tuiles

Pour éviter de faire une nouvelle fonction on peut imaginer de faire une rotation de la matrice grille de -90° puis appliquer l'algorithme précédent permettant de décaler les tuiles vers la gauche

Exemple

Etat initial :

2204
4202
4008
0440

Rotation de -90° :

0442
4022
4000
0824

Décalage à gauche

8200
4400
4000
8240

Rotation de 90° (ou -270°)

0000
0004
2402
8448

 

Cas général pour les déplacements :

Afin d'utiliser qu'une seule fonction de rotation de -90°, on procède de la manière suivante :

Ce qui justifie l'attibution du chiffre :

Ecrire en javascript la fonction constituée de 2 boucles "pour" permettant de faire pivoter la matrice de -90°

Algorithme :

fonction rotation_matrice
matrice ← [[],[],[],[]] pour x variant de 0 à 3 pour y variant de 0 à 3 matrice[?][?] ← grille[x][y] fin pour fin pour retourne matrice
fin de la fonction

Traduire l'algorithme en JavaScript et remplacer les ? par les variables x ou y ou par une soustraction




Algorithme complet de la fonction deplace_tuille(direction)

Après avoir détecté la touche directionnelle du clavier, appelle la fonction deplace_tuiles en passant le chiffre correspondant à la touche enfoncée en paramètre.

Algorithme
Fonction deplace_tuiles(direction)

paramètre d'entrée :  le chiffre représentant la direction (0, 1, 2 ou 3)

début
	si direction >0 alors
		pour i variant de 0 à direction
			grille ← rotation_matrice
		fin pour
	fin si
	pour i variant de 0 à 3
		ligne ← decale_zeros de grille[i]
		grille[i] ← additionner grille[i]
		ligne ← decale_zeros de grille[i]
	fin pour
	si direction >0 alors
		pour i variant de 0 à (4-direction)
			grille ← rotation_matrice
		fin pour
	fin si
fin de la fonction



Recherche du nombre maxi de la grille

Algorithme
Fonction maximum()
début
	max ←2
	parcourir toutes les cases de la grille avec 2 boucle pour
		si max < valeur de la tuile sélectionnée alors
			max = valeur de la tuile
	retourne max		
fin de la fonction





Placer une tuile aléatoirement

Code Javascript
function place_tuile_aleatoire(){
    //Permet de placer une nouvelle tuile de manière aléatoire
    var occupe= true;
    var choix=[2,2,2,2,4];

    while (occupe){
        x=(Math.random()*3).toFixed(0);
        y=(Math.random()*3).toFixed(0);
        if (grille[x][y]==0){
            grille[x][y]=choix[(Math.random()*4).toFixed(0)];
            occupe=false
		}
	}
}

Justifier l'emploi des variables choix=[2,2,2,2,4] et occupe


Code javascript de la vérification de la fin du jeu

Code Javascript
function verifie_fin(){
	//boucle 1
	for (var ligne=0;ligne<4;ligne++){                              
		for (var col=0;col<3;col++){
			if (grille[ligne][col]==grille[ligne][col+1]){      
				return (false);
			}
		}
	}		
	//boucle 2
	for (var col=0;col<4;col++){                                
		for (var ligne=0;ligne<3;ligne++){
			if (grille[ligne][col]==grille[ligne+1][col]){      
				return (false);
			}
		}
	}
	//boucle 3
	for (var i=0;i<4;i++){                                   
	var rangee=grille[i];
		for (var j=0;j<4;j++){
			if (rangee[j]==0){
				return (false);
			}
		}
	}
	return (true)
}

Le script ci-dessus permet de vérifier horizontalement et verticalement si deux tuiles sont égales et vérifier s'il reste des cases contenant des zéros.
Indiquer quelle boucle réalise les fonctions citées ci-dessus


Ecrire la fonction que permet de commencer le jeu

algorithme:

fonction commence_jeu()
	Placer des zéross dans la variable grille
	placer 2 tuiles aléatoires
	dessiner la grille
fin 
Appeler la fonction commence_jeu

Voir le résultat en cliquant ici

Appel des fonctions

Il ne reste plus qu'à appeler les fonctions dans la fonction de détection des touches, vérifier la fin de la partie et un déplacement impossible. Remplacer la ligne console.log(direction[x]); le code suivant:

  grille_avant=String(grille);
  deplace_tuiles(direction[x]);
  if (verifie_fin()==true){
	if (confirm('Tu as perdu, essaye encore')){
	  commence_jeu();
	}
  }
  if (grille_avant!=String(grille)){
	place_tuile_aleatoire()
  }
  dessine_grille()     
  if (maximum()==2048){
	if (confirm('Tu as gagné, recommence une nouvelle partie ?')){
	  commence_jeu();
	}
  }    

Répondre aux questions suivantes :

Remplacer la ligne de code console.log(direction[x]) ici

Les touches directionnelles haut et bas du clavier font défiler la page, ce qui n'est pas agréable pour jouer. C'est le moment d'enlever les 2 "/" du début de la ligne //event.preventDefault() // à n'enlever qu'à la fin du TP !! de la fonction detection_touches

Fond : Texte : Tables :