Forums Développement Multimédia

Les formations Mediabox
Les formations Mediabox

Exercice pratique : le BEJEWELED

Compatible ActionScript 3. Cliquer pour en savoir plus sur les compatibilités.Par Monsieur Spi, le 01 août 2013

Bonjour,

Aujourd'hui on s'attaque au Bejeweled.

Tout d'abord le résultat :

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.

Les sources sont disponibles en fin d'exercice

Les pré-requis

Etude préliminaire

Tout d'abord le BEJEWELED c'est quoi ?

Ce jeu a porté de nombreux noms mais à la base il s'agit d'un jeu vidéo sur navigateur web développé par PopCap Games et sorti en 2001. Son but est ultra simple, dans un plateau composé de colonnes et de lignes, vous devez aligner verticalement ou horizontalement plus de deux pièces de même type pour les faire disparaître. Toutes les pièces se trouvant au dessus venant combler le trou laissé par les pièces retirées, et de nouvelles pièces étant générées pour combler le vide ainsi laissé par les pièces descendues. La base du jeu est donc extrêmement simple et s'agrémente de nouvelles fonctionnalités selon les versions.

Préparation

Comme d'habitude dans les exercices, on va commencer par préparer le travail, et pour ce jeu on va travailler avec l'IDE car le code est court, que j'ai la flemme de structurer ça avec des classes et que ça va le rendre accessible à tout le monde.

Ouvrez un nouveau projet Flash, créez un MovieClip “Marqueur” et un MovieClip “Piece” représentant respectivement le marqueur du jeu et les différentes pièces qui vont composer le jeu. Pour les pièces, placez un type de pièce différent par frame dans le MovieClip.

Créez également un MovieClip nommé “Hud”, ce sera l'interface du jeu avec notamment le score, et placez-y un champ texte dynamique nommé “score”.

Puis exportez les trois clips pour AS, n'oubliez pas d'intégrer la police du texte.

Pour la préparation c'est tout, passons au code.

Code

Sur la première frame de votre projet tapez le code suivant.

 
var T:int = 45;
var i:int;
var j:int;
var C:int;
var L:int;
var score:int;
var p:Piece;
var choix:Piece;
var rendu:Sprite;
var stock:Array;
var marqueur:Marqueur;
var hud:Hud;
 
init()
 
// préparer le jeu
function init():void{
	hud = new Hud();
	marqueur = new Marqueur();
	marqueur.visible = false;
	marqueur.mouseEnabled = false;
	score = 0;
	stock = [];
	for(i=0; i<8; i++) stock.push([]);
	while(true){
		rendu = new Sprite();
		for (i=0; i<8*8; i++) creePiece(i%8,int(i/8));
		if (chercheCombis().length != 0) continue;
		if (!solutions()) continue;
		break;
	}
	rendu.x = 60;
	rendu.y = 60;
	addChild(hud);
	addChild(rendu);
	addChild(marqueur);
	addEventListener(Event.ENTER_FRAME,main);
}
 
// créer des pièces
function creePiece(C:int,L:int):Piece{
	p = new Piece();
	p.x = C*T;
	p.y = L*T-T*5;
	p.C = C;
	p.L = L;
	p.type = int(Math.random()*7)+1;
	p.gotoAndStop(p.type);
	rendu.addChild(p);
	stock[C][L] = p;
	p.addEventListener(MouseEvent.CLICK,clickPiece);
	return p;
}
 
// déplacer les pièces
function main(e:Event):void{
	var M:Boolean = false;
	for (i=0; i<8*8; i++){
		p = stock[i%8][int(i/8)];
		if (p != null)	{
			if (p.y < p.L*T) p.y +=  15, M = true;
			if (p.y > p.L*T) p.y -=  15, M = true;
			if (p.x < p.C*T) p.x +=  15, M = true;
			if (p.x > p.C*T) p.x -=  15, M = true;
		}
	}
	if(!M) changePieces();
}
 
// changer les pieces
function changePieces():void{
	var c:Array = chercheCombis();
	for (i=0; i<c.length; i++){
		for (j=0; j<c[i].length; j++){
			p = c[i][j];
			if (rendu.contains(p)){
				hud.score.text = String(score+=(c[i].length-1)*50);
				rendu.removeChild(p);
				p.removeEventListener(MouseEvent.CLICK,clickPiece);
				stock[p.C][p.L] = null;
				for (L=p.L-1; L>=0; L--){
					if (stock[p.C][L] != null){
						stock[p.C][L].L++;
						stock[p.C][L+1] = stock[p.C][L];
						stock[p.C][L] = null;
					}
				}
			}
		}
	}
	for (C=0; C<8; C++){
		for (L=7; L>=0; L--) {
			if (stock[C][L] == null) {
				p = creePiece(C,L);
			}
		}
	}
	if (c.length == 0 && !solutions()) finPartie();
}
 
// choisir une pièce
function clickPiece(e:MouseEvent):void{
	p = Piece(e.currentTarget);
	marqueur.visible = false;
	if (choix == null){
		marqueur.x = p.x+rendu.x;
		marqueur.y = p.y+rendu.y;
		marqueur.visible = true;
		choix = p;
	} else {
		if (choix == p) permute(choix,p);
		else if (choix.L == p.L && Math.abs(choix.C-p.C) == 1) permute(choix,p);
		else if (choix.C == p.C && Math.abs(choix.L-p.L) == 1) permute(choix,p);
		else {
			marqueur.x = p.x+rendu.x;
			marqueur.y = p.y+rendu.y;
			marqueur.visible = true;
			choix = p;
		}
	}
}
 
// permuter les pièces
function permute(p1:Piece,p2:Piece):void{
	choix = null;
	permutePieces(p1,p2);
	if (chercheCombis().length == 0) permutePieces(p1,p2);
}
 
function permutePieces(p1:Piece,p2:Piece):void{
	C = p1.C;
	L = p1.L;
	p1.C = p2.C;
	p1.L = p2.L;
	p2.C = C;
	p2.L = L;
	stock[p1.C][p1.L] = p1;
	stock[p2.C][p2.L] = p2;
}
 
// cherche les combinaisons
function chercheCombis():Array{
	var liste:Array = [];
	var combi:Array;
	for (L=0; L<8; L++){
		for (C=0; C<8; C++){
			combi = verifLignes(C,L);
			if (combi.length > 2){
				liste.push(combi);
				C += combi.length-1;
			}
			combi = verifColonnes(C,L);
			if (combi.length > 2){
				liste.push(combi);
				L += combi.length-1;
			}
		}
	}
	return liste;
}
 
// vérifie les lignes
function verifLignes(C:int,L:int):Array{
	var combi:Array = [stock[C][L]];
	for (i=1; i+C<8; i++)	{
		if (stock[C][L].type == stock[C+i][L].type)	combi.push(stock[C+i][L]);
		else return combi;
	}
	return combi;
}
 
// vérifie les Connes
function verifColonnes(C:int,L:int):Array{
	var combi:Array = [stock[C][L]];
	for (i=1; i+L<8; i++) {
		if (stock[C][L].type == stock[C][L+i].type) combi.push(stock[C][L+i]);
		else return combi;
	}
	return combi;
}
 
// cherche une solution
function solutions() {
	for (C=0; C<8; C++){
		for (L=0; L<8; L++){
			if (trouveCombis(C, L, [1,0], [[-2,0],[-1,-1],[-1,1],[2,-1],[2,1],[3,0]])) return true;// horizontal deux + un
			if (trouveCombis(C, L, [2,0], [[1,-1],[1,1]])) return true;// horizontal milieu
			if (trouveCombis(C, L, [0,1], [[0,-2],[-1,-1],[1,-1],[-1,2],[1,2],[0,3]])) return true;// vertical deux + un
			if (trouveCombis(C, L, [0,2], [[-1,1],[1,1]])) return true;// vertical milieu
		}
	}
	trace("pas de solution")
	return false;// pas de solution
}
 
function trouveCombis(C:int,L:int, obligatoire:Array, complement:Array) {
 
	var type:int = stock[C][L].type;
 
	// y a t'il la pièce obligatoire pour créer une combi
	if (!compareType(C+obligatoire[0], L+obligatoire[1], type)) return false; 
 
	// et au moins une pièce pour faire le complément
	for(i=0;i<complement.length;i++) {
		if (compareType(C+complement[i][0], L+complement[i][1], type)) return true;
	}
	return false;
}
 
function compareType(C:int,L:int,type:int):Boolean{
	if (C<0 || C>7 || L<0 || L>7) return false;
	return (stock[C][L].type == type);
}
 
function finPartie():void{
	stock = null;
	removeChild(rendu);
	rendu = null;
	removeEventListener(Event.ENTER_FRAME,main);
	trace("gameover");
}

Etude du programme

Si vous avez fait les exercices précédent vous avez l'habitude de ce genre de chose.

var T:int = 45;
var i:int;
var j:int;
var C:int;
var L:int;
var score:int;
var p:Piece;
var choix:Piece;
var rendu:Sprite;
var stock:Array;
var marqueur:Marqueur;
var hud:Hud;
 
init();

Je déclare mes variables globales et mes objets utiles pendant le jeu, puis je lance l'initialisation du programme.

// préparer le jeu
function init():void{
	hud = new Hud();
	marqueur = new Marqueur();
	marqueur.visible = false;
	marqueur.mouseEnabled = false;
	score = 0;
	stock = [];
	for(i=0; i<8; i++) stock.push([]);
	while(true){
		rendu = new Sprite();
		for (i=0; i<8*8; i++) creePiece(i%8,int(i/8));
		if (chercheCombis().length != 0) continue;
		if (!solutions()) continue;
		break;
	}
	rendu.x = 60;
	rendu.y = 60;
	addChild(hud);
	addChild(rendu);
	addChild(marqueur);
	addEventListener(Event.ENTER_FRAME,bougePieces);
}

Je crée le “hud” qui sert à afficher le score, le “marqueur” qui indique quelle pièce est sélectionnée, ce marqueur est insensible aux événements souris et invisible au départ. Le score est passé à zéro, le stock des pièces est vidé, puis chaque ligne du stock est remplie par un tableau vide. Vous noterez ici que je vais utiliser un tableau à deux dimensions et non une simple liste comme j'ai l'habitude de le faire, ceci va me permettre de simplifier un peu les différents calculs mais ça pourrait très bien fonctionner avec une simple liste si on le souhaite.

On arrive à une nouvelle astuce qui n'a pas été abordée dans les exercices précédents, je crée une boucle infinie avec l'instruction “while” et le paramètre “true”, l'expression “tant que vrai” semble incongrue, mais en fait elle permet de boucler tant que rien ne permet de sortir de la boucle. Et dans cette boucle je vais créer le sprite de rendu, boucler sur toutes les pièces du plateau de jeu et créer chaque pièce à sa position, puis vérifier si une combinaison existe, si c'est le cas on ne cherche pas à lire la suite de la boucle et on recommence, c'est qu'il existe des pièces déjà positionnées pour former une combinaison, et on ne commence pas le jeu avec une combinaison existante. Si aucune combinaison n'existe, je vais rechercher les solutions possibles, c'est à dire si en déplaçant une pièce le joueur peut former une combinaison, si aucune solution n'est trouvée alors le joueur ne pourra pas jouer et le plateau est invalide, du coup là aussi on ne cherche pas à lire la suite et on recommence la boucle. Une fois qu'on à trouver une disposition où il n'existe pas de combinaison mais qu'une solution est possible on stoppe la boucle avec l'instruction “break” et notre plateau de jeu est prêt.

Nous reviendrons plus tard sur la manière de trouver les combinaisons et les solutions, pour le moment terminons de préparer le jeu.

On place le plateau de jeu (“rendu”) et on ajoute tous les objets à la liste d'affichage, puis on lance la fonction principale du programme qui boucle sur un ENTER_FRAME.

// créer des pièces
function creePiece(C:int,L:int):Piece{
	p = new Piece();
	p.x = C*T;
	p.y = L*T-T*5;
	p.C = C;
	p.L = L;
	p.type = int(Math.random()*7)+1;
	p.gotoAndStop(p.type);
	rendu.addChild(p);
	stock[C][L] = p;
	p.addEventListener(MouseEvent.CLICK,clickPiece);
	return p;
}

Un grand classique quand on utilise pas de classes pour les objets, ici on crée les pièces du plateau, pour chacune on va indiquer sa position de départ (sur Y au dessus du plateau), la Colonne et la Ligne où elle se trouve dans la grille du plateau, son type pour la distinguer des autres, on l'affiche au passage, on l'ajoute au plateau de jeu, on l'ajoute au stock, on lui ajoute un écouteur au clic de la souris, puis on retourne la pièce nouvellement créée.

// déplacer les pièces
function main(e:Event):void{
	var M:Boolean = false;
	for (i=0; i<8*8; i++){
		p = stock[i%8][int(i/8)];
		if (p != null)	{
			if (p.y < p.L*T) p.y +=  15, M = true;
			if (p.y > p.L*T) p.y -=  15, M = true;
			if (p.x < p.C*T) p.x +=  15, M = true;
			if (p.x > p.C*T) p.x -=  15, M = true;
		}
	}
	if(!M) changePieces();
}

Cette fonction à pour seul objectif de déplacer les pièces quand elles en ont besoin, c'est à dire à tout moment à partir du moment où une pièce n'est pas à sa place définitive. On commence par déclarer que les pièces peuvent plus bouger à l'aide du Boolean “M”. Puis on boucle sur toutes les pièces du plateau, si la pièce existe on vérifie chaque position sur chaque axe, si la position de la pièce est différente de la colonne ou de la ligne qu'elle doit occuper, on la déplace de 15 pixels et on indique au programme que la pièce est en train de se déplacer. Lorsque toutes les pièces ont fini de se déplacer, il faut vérifier si de nouvelles combinaison sont apparues.

// changer les pieces
function changePieces():void{
	var c:Array = chercheCombis();
	for (i=0; i<c.length; i++){
		for (j=0; j<c[i].length; j++){
			p = c[i][j];
			if (rendu.contains(p)){
				hud.score.text = String(score+=(c[i].length-1)*50);
				rendu.removeChild(p);
				p.removeEventListener(MouseEvent.CLICK,clickPiece);
				stock[p.C][p.L] = null;
				for (L=p.L-1; L>=0; L--){
					if (stock[p.C][L] != null){
						stock[p.C][L].L++;
						stock[p.C][L+1] = stock[p.C][L];
						stock[p.C][L] = null;
					}
				}
			}
		}
	}
	for (C=0; C<8; C++){
		for (L=7; L>=0; L--) {
			if (stock[C][L] == null) {
				p = creePiece(C,L);
			}
		}
	}
	if (c.length == 0 && !solutions()) finPartie();
}

Nous venons d'en parler, lorsque les pièces ont bougé, quelle que soit la cause de ce mouvement, il faut vérifier si la nouvelle disposition engendre des combinaisons et auquel cas modifier le plateau de jeu en conséquence.

Je commence donc par regarder si une combinaison existe, si c'est le cas je boucle sur les pièces qui forment cette combinaison, je vérifie que le plateau de jeu contient bien les pièces impactées par la combinaison, je met à jour le score (50 point par pièce), puis je retire du plateau de jeu et du stock chaque pièce qui compose la combinaison, notez que je ne retire pas l'emplacement de la pièce du stock, ce dernier est invariable, j'indique simplement que cet emplacement est désormais vide (null), pensez également à retirer l'écouteur sur la pièce que vous supprimez.

Une fois la pièce retirée du plateau, je regarde si des pièces existent juste au dessus, si c'est le cas les pièces descendent, on met à jour le stock et les références des pièces.

Lorsque toutes les pièces ont été déplacées, supprimées et nettoyées, on se charge de recréer les nouvelles pièces, pour cela on boucle sur toutes les colonnes du plateau de jeu, on part de la ligne la plus basse de chaque colonne, on regarde si on trouve un emplacement vide pour cette case dans le stock et si c'est le cas on recrée une nouvelle pièce pour l'emplacement vide (qui se place automatiquement au dessus du plateau de jeu et donc descend immédiatement à son nouvel emplacement).

Que les pièces aient bougé ou pas, si il n'existe pas de combinaison ni de solution, le plateau ne propose plus de possibilité de jeu et la partie est terminée (ou le plateau est réinitialisé si vous préférez gérer le jeu ainsi).

Avant d'étudier la méthode pour trouver des combinaisons ou des solutions, continuons à nous pencher sur les actions possibles sur les pièces, et notamment lorsque le joueur essayes de permuter deux pièces pour former une combinaison.

// choisir une pièce
function clickPiece(e:MouseEvent):void{
	p = Piece(e.currentTarget);
	marqueur.visible = false;
	if (choix == null){
		marqueur.x = p.x+rendu.x;
		marqueur.y = p.y+rendu.y;
		marqueur.visible = true;
		choix = p;
	} else {
		if (choix == p) permute(choix,p);
		else if (choix.L == p.L && Math.abs(choix.C-p.C) == 1) permute(choix,p);
		else if (choix.C == p.C && Math.abs(choix.L-p.L) == 1) permute(choix,p);
		else {
			marqueur.x = p.x+rendu.x;
			marqueur.y = p.y+rendu.y;
			marqueur.visible = true;
			choix = p;
		}
	}
}

A ce stade le joueur vient de cliquer sur une pièce pour la sélectionner, on récupère la pièce cliquée, on masque le marqueur puis on vérifie que le “choix” n'est pas “null”, la variable “choix” indique si le joueur à déjà sélectionné une pièce auquel cas la pièce cliquée est celle avec laquelle permuter la première, sinon c'est la première pièce. Si il s'agit de la première pièce sur laquelle le joueur clique, on place le marqueur sur la pièce et on l'affiche, puis on enregistre la pièce sélectionnée. Si il s'agit de la seconde pièce sur laquelle le joueur clique, si il s'agit de la même pièce on permute la pièce sur elle même (vous verrez pourquoi par la suite), sinon on regarde si les pièces sont à côté l'une de l'autre et sur la même ligne ou la même colonne, auquel cas on permute les deux pièces. Dernière option, le joueur a choisi une première pièce et clique sur une seconde pièce qui ne se trouve pas à côté, le coup n'est pas réglementaire, on choisi donc de conserver la dernière pièce choisie comme première pièce.

// permuter les pièces
function permute(p1:Piece,p2:Piece):void{
	choix = null;
	permutePieces(p1,p2);
	if (chercheCombis().length == 0) permutePieces(p1,p2);
}
 
function permutePieces(p1:Piece,p2:Piece):void{
	C = p1.C;
	L = p1.L;
	p1.C = p2.C;
	p1.L = p2.L;
	p2.C = C;
	p2.L = L;
	stock[p1.C][p1.L] = p1;
	stock[p2.C][p2.L] = p2;
}

Voici deux petites fonction qui permettent de permuter les pièces lorsque le joueur a fait son choix et que le coup est régulier. Le première fonction vide le choix de la pièce en cours, permute les deux pièces choisies et vérifie si la nouvelle disposition permet de faire une combinaison, si ce n'est pas le cas on permute à nouveau les pièces pour les remettre à leur position d'origine.

La seconde fonction a pour rôle de réellement permuter les pièces, pour cela on échange simplement les références des pièces (colonne et ligne) et leur position dans le stock.

Bien, toutes les interactions des pièces sont faites, reste à présent à s'occuper des combinaisons et des solutions possible, on commence par regarder comment trouver une combinaison.

// cherche les combinaisons
function chercheCombis():Array{
	var liste:Array = [];
	var combi:Array;
	for (L=0; L<8; L++){
		for (C=0; C<8; C++){
			combi = verifLignes(C,L);
			if (combi.length > 2){
				liste.push(combi);
				C += combi.length-1;
			}
			combi = verifColonnes(C,L);
			if (combi.length > 2){
				liste.push(combi);
				L += combi.length-1;
			}
		}
	}
	return liste;
}

Pour trouver une combinaison valable, on va vérifier toutes les cases du plateau de jeu, pour chaque case on va vérifier si pour la ligne entière il existe plus de deux pièces de même type alignées, si c'est le cas on enregistre la combinaison dans la liste puis on passe tout de suite aux colonnes se trouvant après la combinaison et on continue la boucle. On fait la même chose avec toutes les lignes, puis lorsque toutes les lignes et colonnes ont été vérifiées, on se retrouve avec une liste de combinaisons réunissant au moins trois pièces chacune, on sait donc à présent quelles sont les pièces à retirer du plateau.

Voyons comment chaque ligne et chaque colonne est vérifiée pour trouver des combinaisons.

// vérifie les lignes
function verifLignes(C:int,L:int):Array{
	var combi:Array = [stock[C][L]];
	for (i=1; i+C<8; i++)	{
		if (stock[C][L].type == stock[C+i][L].type) combi.push(stock[C+i][L]);
		else return combi;
	}
	return combi;
}
 
// vérifie les Colonnes
function verifColonnes(C:int,L:int):Array{
	var combi:Array = [stock[C][L]];
	for (i=1; i+L<8; i++) {
		if (stock[C][L].type == stock[C][L+i].type) combi.push(stock[C][L+i]);
		else return combi;
	}
	return combi;
}

Ces deux fonctions sont identiques, l'une vérifie les colonnes et l'autres les lignes, je ne vais donc en détailler qu'une seule. Lorsque je veux vérifier une ligne par exemple, je crée un tableau provisoire dans lequel je stocke la pièce à partir de la quelle je veux commencer les tests, rappelez-vous que la fonction “chercheCombis” va commencer la vérification à partir de la colonne 0. Je vérifie une ligne, donc je dois en fait vérifier chaque colonne de la ligne, je fais donc une boucle sur toutes les colonnes de la ligne, en partant de la pièce actuellement testée. Dans cette boucle, je compare le type de la pièce de référence avec celui de la pièce se trouvant dans la colonne suivante, si les deux concordent j'ajoute la nouvelle pièce à la combinaison, sinon je renvoie la combinaison et je stoppe en même temps la boucle. Dans tous les cas, lorsque la vérification de toute la colonne est terminée, je renvoie la combinaison trouvée.

Voyons à présent comment vérifier si une solution existe.

// cherche une solution
function solutions() {
	for (C=0; C<8; C++){
		for (L=0; L<8; L++){
			if (trouveCombis(C, L, [1,0], [[-2,0],[-1,-1],[-1,1],[2,-1],[2,1],[3,0]])) return true;// horizontal deux + un
			if (trouveCombis(C, L, [2,0], [[1,-1],[1,1]])) return true;// horizontal milieu
			if (trouveCombis(C, L, [0,1], [[0,-2],[-1,-1],[1,-1],[-1,2],[1,2],[0,3]])) return true;// vertical deux + un
			if (trouveCombis(C, L, [0,2], [[-1,1],[1,1]])) return true;// vertical milieu
		}
	}
	return false;// pas de solution
}
 
function trouveCombis(C:int,L:int, obligatoire:Array, complement:Array) {
 
	var type:int = stock[C][L].type;
 
	// y a t'il la pièce obligatoire pour créer une combi
	if (!compareType(C+obligatoire[0], L+obligatoire[1], type)) return false; 
 
	// et au moins une pièce pour faire le complément
	for(i=0;i<complement.length;i++) {
		if (compareType(C+complement[i][0], L+complement[i][1], type)) return true;
	}
	return false;
}
 
function compareType(C:int,L:int,type:int):Boolean{
	if (C<0 || C>7 || L<0 || L>7) return false;
	return (stock[C][L].type == type);
}

Trois petites fonctions qui travaillent ensemble, la première effectue une boucle sur toutes les cases du plateau de jeu et cherche si une combinaison est possible entre le pièce actuellement testée et deux autres, une obligatoire et une complémentaire. La pièce obligatoire est toujours sur la case adjacente ou à une case d'écart, quand aux pièces complémentaires elles doivent se trouver en complément du début de série trouvé. Pour être clair, si je trouve deux cases collées identiques, je vérifie les deux cases se trouvant à une case ou deux de la première ou la dernière du début de série. Si je trouve deux cases de même type espacées par une case de type différent, je teste si la case au dessus ou au dessous de la case de type différent est de même type que le début de la combinaison, etc….

La seconde fonction se charge de tester les cases pour trouver les combinaisons, et la troisième teste l'égalité des types des cases qu'elle renvoie à la seconde fonction, qui elle même renvoie les combinaisons trouvée à la première.

function finPartie():void{
	stock = null;
	removeChild(rendu);
	rendu = null;
	removeEventListener(Event.ENTER_FRAME,main);
	trace("gameover");
}

C'est la fin de la partie, ou la réinitialisation du plateau de jeu lorsqu'il n'y a plus de possibilités ni de déplacer une pièce, ni de faire de combinaisons. D'ordinaire dans les exercices je vous fait ça bien avec un panneau pour lancer le jeu, un autre lorsque le jeu est terminé, et une possibilité de relancer le tout via un bouton, si vous avez fait les exercices précédents cela ne devrait pas vous poser de problème et comme ce n'est pas ce qui nous intéresse ici je préfères aller doit au but, les exercices vont être de plus en plus long alors on ne va plus s'encombrer avec ce genres de petites choses.

Conclusion

Contrairement à ce que l'on pourrait penser, “Bejeweled” est très simple à coder, ce jeu permet néanmoins de mettre en pratique quelques algorithmes sympas pour retrouver des combinaisons ou des solutions sans un plateau de jeu. Pour ce coup là j'ai choisi de travailler avec des tableaux à deux dimensions et de ne pas forcément pousser le nettoyage et la compression du code en utilisant des raccourcis, le programme est assez court et cela vous évite des manipulations et des formules inutiles à ce stade, et utiliser une liste ou un tableau 2D n'a que peu d'influence sur le comportement du programme et son optimisation. Bien sur vous n'avez qu'une base, comme toujours, à vous de l'agrémenter avec tout un tas d'effets, de bonus, de multiplicateurs en fonction du nombre de pièces dans une combinaison, d'inverseurs, d'indicateurs de combinaisons si le joueur met trop de temps, de pièces spéciales comme des bombes, etc…

Les sources

bejeweled_mb_1.fla version CS6