Files
DEV/SAE21_2024/code_source/Grille.java

207 lines
6.4 KiB
Java
Raw Normal View History

import java.util.Random;
/**
* La classe <code>Grille</code> représente la logique du jeu SameGame.
* Elle gère la création aléatoire des blocs, la détection et suppression de groupes,
* lapplication de la gravité et le décalage des colonnes.
*
* @author Emmanuel Srivastava-Tiamzon & Wael ATIK
* @version 1.8
*/
public class Grille {
private static final int LIGNES = 10;
private static final int COLONNES = 15;
private final char[][] grille;
private Score score;
/**
* Constructeur : initialise la grille avec des blocs aléatoires.
*/
public Grille() {
this.grille = new char[LIGNES][COLONNES];
this.score = new Score();
this.score.setScore(0);
char[] couleurs = {'R', 'V', 'B'};
Random rand = new Random();
for (int i = 0; i < LIGNES; i++) {
for (int j = 0; j < COLONNES; j++) {
grille[i][j] = couleurs[rand.nextInt(couleurs.length)];
}
}
}
/**
* Par polymorphisme on adapte le constructeur pour que l'on puisse jouer avec une grille préféfini.
*/
public Grille(char[][] grille) {
this.grille = grille;
this.score = new Score();
this.score.setScore(0);
}
/**
* Vérifie si un groupe de blocs de même couleur existe à une position donnée.
*
* @param ligne ligne de la case
* @param colonne colonne de la case
* @return true si un groupe valide (taille > 1) existe
*/
public boolean estGroupe(int ligne, int colonne) {
char couleur = grille[ligne][colonne];
if (couleur == ' ') return false;
boolean[][] visite = new boolean[LIGNES][COLONNES];
return tailleGroupe(ligne, colonne, couleur, visite) > 1;
}
/**
* Supprime un groupe de blocs si sa taille est supérieure à 1 et applique la gravité et le décalage.
*
* @param ligne ligne de départ
* @param colonne colonne de départ
*/
public void supprimerGroupe(int ligne, int colonne) {
char couleur = grille[ligne][colonne];
if (couleur == ' ') return;
boolean[][] visite = new boolean[LIGNES][COLONNES];
int taille = tailleGroupe(ligne, colonne, couleur, visite);
if (taille > 1) {
this.score.addToScore((taille - 2) * (taille - 2));
supprimerRec(ligne, colonne, couleur, new boolean[LIGNES][COLONNES]);
appliquerGravite();
appliquerDecalageGauche();
}
}
/**
* Calcule la taille dun groupe avec un parcours en largeur.
*/
private int tailleGroupe(int i, int j, char couleur, boolean[][] visite) {
if (i < 0 || i >= this.LIGNES || j < 0 || j >= this.COLONNES) return 0;
if (visite[i][j] || this.grille[i][j] != couleur) return 0;
visite[i][j] = true;
return 1
+ tailleGroupe(i + 1, j, couleur, visite)
+ tailleGroupe(i - 1, j, couleur, visite)
+ tailleGroupe(i, j + 1, couleur, visite)
+ tailleGroupe(i, j - 1, couleur, visite);
}
/**
* Supprime récursivement un groupe avec un parcours en largeur.
*/
private void supprimerRec(int i, int j, char couleur, boolean[][] visite) {
if (i < 0 || i >= this.LIGNES || j < 0 || j >= this.COLONNES) return;
if (visite[i][j] || this.grille[i][j] != couleur) return;
visite[i][j] = true;
this.grille[i][j] = ' ';
supprimerRec(i + 1, j, couleur, visite);
supprimerRec(i - 1, j, couleur, visite);
supprimerRec(i, j + 1, couleur, visite);
supprimerRec(i, j - 1, couleur, visite);
}
/**
* Applique la gravité : fait tomber les blocs vers le bas.
*/
private void appliquerGravite() {
for (int col = 0; col < this.COLONNES; col++) {
int ligneVide = this.LIGNES - 1;
for (int i = this.LIGNES - 1; i >= 0; i--) {
if (this.grille[i][col] != ' ') {
this.grille[ligneVide][col] = this.grille[i][col];
if (ligneVide != i) this.grille[i][col] = ' ';
ligneVide--;
}
}
}
}
/**
* Décale les colonnes vers la gauche si elles sont vides.
*/
private void appliquerDecalageGauche() {
int colDestination = 0;
for (int colSource = 0; colSource < this.COLONNES; colSource++) {
boolean colonneVide = true;
for (int i = 0; i < this.LIGNES; i++) {
if (this.grille[i][colSource] != ' ') {
colonneVide = false;
break;
}
}
if (!colonneVide) {
if (colDestination != colSource) {
for (int i = 0; i < this.LIGNES; i++) {
this.grille[i][colDestination] = this.grille[i][colSource];
this.grille[i][colSource] = ' ';
}
}
colDestination++;
}
}
}
/**
* Marque toutes les cases dun groupe à partir dune position donnée.
*
* @param couleur couleur du bloc de départ
* @param i ligne de départ
* @param j colonne de départ
* @param surbrillance tableau marquer les blocs du groupe
*/
public void marquerGroupe(char couleur, int i, int j, boolean[][] surbrillance) {
if (i < 0 || i >= this.LIGNES || j < 0 || j >= this.COLONNES) return;
if (surbrillance[i][j] || this.grille[i][j] != couleur) return;
surbrillance[i][j] = true;
marquerGroupe(couleur, i + 1, j, surbrillance);
marquerGroupe(couleur, i - 1, j, surbrillance);
marquerGroupe(couleur, i, j + 1, surbrillance);
marquerGroupe(couleur, i, j - 1, surbrillance);
}
/**
Vérifie sil reste des groupes de blocs valides
@return true si le jeu est terminé, false sinon*/
public boolean jeuFini() {
for (int i = 0; i < this.LIGNES; i++) {
for (int j = 0; j < this.COLONNES; j++) {
char bloc = this.grille[i][j];
if (bloc != ' ' && estGroupe(i, j)) {
return false;
}
}
}
return true;
}
public char getCase(int i, int j) {
return this.grille[i][j];
}
public char[][] getGrille() {
return this.grille;
}
public int getLignes() {
return this.LIGNES;
}
public int getColonnes() {
return this.COLONNES;
}
}