diff --git a/game/EtatJeu.java b/game/EtatJeu.java deleted file mode 100644 index f75e077..0000000 --- a/game/EtatJeu.java +++ /dev/null @@ -1,64 +0,0 @@ -package game; - -import java.util.Random; - -public class EtatJeu { - - public static final int NB_LIGNES = 6; - public static final int NB_COLONNES = 6; - public static final int NB_TYPES = 7; - - private final int[][] grille = new int[NB_LIGNES][NB_COLONNES]; - private final Random aleatoire; - - public EtatJeu() { - aleatoire = new Random(); - initialiserGrilleSansTriples(); - } - - // --- Lecture / écriture --- - public int obtenirCase(int ligne, int colonne) { - return grille[ligne][colonne]; - } - - public void definirCase(int ligne, int colonne, int valeur) { - grille[ligne][colonne] = valeur; - } - - // --- Initialisation de la grille sans séries de 3 --- - private void initialiserGrilleSansTriples() { - for (int ligne = 0; ligne < NB_LIGNES; ligne++) { - for (int colonne = 0; colonne < NB_COLONNES; colonne++) { - - int valeur; - do { - valeur = aleatoire.nextInt(NB_TYPES); // 0..6 - } while (creeTriple(ligne, colonne, valeur)); - - grille[ligne][colonne] = valeur; - } - } - } - - // Renvoie true si mettre "valeur" à (ligne, colonne) créerait une série de 3 - private boolean creeTriple(int ligne, int colonne, int valeur) { - - // Test horizontal : XXX à gauche - if (colonne >= 2) { - if (grille[ligne][colonne - 1] == valeur && - grille[ligne][colonne - 2] == valeur) { - return true; - } - } - - // Test vertical : XXX au-dessus - if (ligne >= 2) { - if (grille[ligne - 1][colonne] == valeur && - grille[ligne - 2][colonne] == valeur) { - return true; - } - } - - return false; - } -} \ No newline at end of file diff --git a/src/src.zip b/src/src.zip deleted file mode 100644 index 28b9cec..0000000 Binary files a/src/src.zip and /dev/null differ diff --git a/src/src/androidTest/java/sae/chuzzle/ExampleInstrumentedTest.java b/src/src/androidTest/java/sae/chuzzle/ExampleInstrumentedTest.java deleted file mode 100644 index dc7075e..0000000 --- a/src/src/androidTest/java/sae/chuzzle/ExampleInstrumentedTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package sae.chuzzle; - -import android.content.Context; - -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.ext.junit.runners.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -/** - * Instrumented test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); - assertEquals("sae.chuzzle", appContext.getPackageName()); - } -} \ No newline at end of file diff --git a/src/src/main/AndroidManifest.xml b/src/src/main/AndroidManifest.xml deleted file mode 100644 index 34cdb93..0000000 --- a/src/src/main/AndroidManifest.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/src/main/java/sae/chuzzle/Controleur.java b/src/src/main/java/sae/chuzzle/Controleur.java deleted file mode 100644 index 62d5650..0000000 --- a/src/src/main/java/sae/chuzzle/Controleur.java +++ /dev/null @@ -1,133 +0,0 @@ -package sae.chuzzle; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.RadioButton; -import android.widget.Spinner; -import android.widget.TextView; -import android.widget.Toast; - -import java.util.List; - -public class Controleur { - - private final Activity activite; - private final EtatJeu etatJeu; - private final VueGrille vueGrille; - private final long graine; - - private final TextView tvScore; - private final TextView tvCoups; - private final RadioButton rbLigne; - private final RadioButton rbDroite; - private final Spinner spinnerIndex; - private final Button btnJouer; - - // Hard Mode - private final boolean hardMode; - - // - - // CONSTRUCTEUR - - - public Controleur(Activity activite, EtatJeu etatJeu, VueGrille vueGrille, - long graine, - TextView tvScore, TextView tvCoups, - RadioButton rbLigne, RadioButton rbDroite, - Spinner spinnerIndex, Button btnJouer, - boolean hardMode) { - - this.activite = activite; - this.etatJeu = etatJeu; - this.vueGrille = vueGrille; - this.graine = graine; - this.tvScore = tvScore; - this.tvCoups = tvCoups; - this.rbLigne = rbLigne; - this.rbDroite = rbDroite; - this.spinnerIndex = spinnerIndex; - this.btnJouer = btnJouer; - this.hardMode = hardMode; - - initialiserSpinner(); - rafraichirAffichage(); - } - - // - - // INITIALISATION - - - private void initialiserSpinner() { - String[] indices = {"0", "1", "2", "3", "4", "5"}; - ArrayAdapter adaptateur = new ArrayAdapter<>( - activite, - android.R.layout.simple_spinner_item, - indices - ); - adaptateur.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - spinnerIndex.setAdapter(adaptateur); - } - - // - - // GESTION DU COUP - - - public void gererCoupJoueur() { - boolean estLigne = rbLigne.isChecked(); - int index = spinnerIndex.getSelectedItemPosition(); - - int sens; - if (rbDroite.isChecked()) { - sens = +1; - } else { - sens = -1; - } - - boolean accepte = etatJeu.appliquerCoup(estLigne, index, sens); - - if (!accepte) { - Toast.makeText(activite, "Coup invalide !", Toast.LENGTH_SHORT).show(); - return; - } - - Toast.makeText(activite, "Coup valide !", Toast.LENGTH_SHORT).show(); - rafraichirAffichage(); - verifierFinDePartie(); - } - - // - - // FIN DE PARTIE - - - public void verifierFinDePartie() { - if (etatJeu.estTerminee()) { - Intent intent = new Intent(activite, FinPartieActivity.class); - intent.putExtra("score", etatJeu.obtenirScore()); - intent.putExtra("nbCoups", etatJeu.obtenirNbCoups()); - intent.putExtra("graine", graine); - activite.startActivity(intent); - } - } - - // - - // MISE A JOUR DE LA VUE - - - public void rafraichirAffichage() { - tvScore.setText("Score : " + etatJeu.obtenirScore()); - tvCoups.setText("Coups : " + etatJeu.obtenirNbCoups()); - vueGrille.definirGrille(etatJeu.obtenirGrille()); - vueGrille.definirVerrous(etatJeu.obtenirVerrous()); - - if (etatJeu.estTerminee()) { - btnJouer.setEnabled(false); - } - } - - public void sauvegarderEtat(Bundle out) { - // Nettoyé de la logique d'objectifs - } -} \ No newline at end of file diff --git a/src/src/main/java/sae/chuzzle/EtatJeu.java b/src/src/main/java/sae/chuzzle/EtatJeu.java deleted file mode 100644 index 4d5f670..0000000 --- a/src/src/main/java/sae/chuzzle/EtatJeu.java +++ /dev/null @@ -1,598 +0,0 @@ -package sae.chuzzle; - -import android.os.Bundle; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -public class EtatJeu { - - public static final int NB_LIGNES = 6; - public static final int NB_COLONNES = 6; - public static final int NB_TYPES = 7; - - private final int[][] grille = new int[NB_LIGNES][NB_COLONNES]; - private final boolean[][] verrous = new boolean[NB_LIGNES][NB_COLONNES]; - private final Random aleatoire; - - private int score = 0; - private int nbCoups = 0; - private boolean partieTerminee = false; - private boolean hardMode = false; - - //- - // CONSTRUCTEURS - - - public EtatJeu() { - aleatoire = new Random(); - initialiserGrilleSansTriples(); - } - - public EtatJeu(long graine, boolean hardMode) { - aleatoire = new Random(graine); - this.hardMode = hardMode; - initialiserGrilleSansTriples(); - } - - // - - // GETTERS - - - public int obtenirScore() { - return score; - } - - public int obtenirNbCoups() { - return nbCoups; - } - - public boolean estTerminee() { - return partieTerminee; - } - - // - - // SAUVEGARDE ET RESTAURATION - - public void sauvegarderEtat(Bundle bundle) { - int[] flatGrille = new int[NB_LIGNES * NB_COLONNES]; - boolean[] flatVerrous = new boolean[NB_LIGNES * NB_COLONNES]; - - for (int l = 0; l < NB_LIGNES; l++) { - for (int c = 0; c < NB_COLONNES; c++) { - flatGrille[l * NB_COLONNES + c] = grille[l][c]; - flatVerrous[l * NB_COLONNES + c] = verrous[l][c]; - } - } - - bundle.putIntArray("grille", flatGrille); - bundle.putBooleanArray("verrous", flatVerrous); - bundle.putInt("score", score); - bundle.putInt("nbCoups", nbCoups); - bundle.putBoolean("partieTerminee", partieTerminee); - } - - public void restaurerEtat(Bundle bundle) { - if (!bundle.containsKey("grille")) return; - - int[] flatGrille = bundle.getIntArray("grille"); - boolean[] flatVerrous = bundle.getBooleanArray("verrous"); - - if (flatGrille != null && flatVerrous != null) { - for (int l = 0; l < NB_LIGNES; l++) { - for (int c = 0; c < NB_COLONNES; c++) { - grille[l][c] = flatGrille[l * NB_COLONNES + c]; - verrous[l][c] = flatVerrous[l * NB_COLONNES + c]; - } - } - } - - score = bundle.getInt("score"); - nbCoups = bundle.getInt("nbCoups"); - partieTerminee = bundle.getBoolean("partieTerminee"); - } - - public int obtenirCase(int ligne, int colonne) { - return grille[ligne][colonne]; - } - - public int[][] obtenirGrille() { - int[][] copie = new int[NB_LIGNES][NB_COLONNES]; - - for (int l = 0; l < NB_LIGNES; l++) { - System.arraycopy(grille[l], 0, copie[l], 0, NB_COLONNES); - } - - return copie; - } - - public boolean[][] obtenirVerrous() { - boolean[][] copie = new boolean[NB_LIGNES][NB_COLONNES]; - - for (int l = 0; l < NB_LIGNES; l++) { - System.arraycopy(verrous[l], 0, copie[l], 0, NB_COLONNES); - } - - return copie; - } - - // - - // INITIALISATION SANS TRIPLES - // - - private void initialiserGrilleSansTriples() { - for (int ligne = 0; ligne < NB_LIGNES; ligne++) { - for (int colonne = 0; colonne < NB_COLONNES; colonne++) { - - int valeur; - do { - valeur = aleatoire.nextInt(NB_TYPES); - } while (creeTriple(ligne, colonne, valeur)); - - grille[ligne][colonne] = valeur; - } - } - } - - private boolean creeTriple(int ligne, int colonne, int valeur) { - - if (colonne >= 2) { - if (grille[ligne][colonne - 1] == valeur && - grille[ligne][colonne - 2] == valeur) { - return true; - } - } - - if (ligne >= 2) { - if (grille[ligne - 1][colonne] == valeur && - grille[ligne - 2][colonne] == valeur) { - return true; - } - } - - return false; - } - - // - - // DECALAGE CIRCULAIRE - - - public void decalerLigne(int ligne, int sens) { - int s = ((sens % NB_COLONNES) + NB_COLONNES) % NB_COLONNES; - - for (int etape = 0; etape < s; etape++) { - int tmp = grille[ligne][NB_COLONNES - 1]; - - for (int c = NB_COLONNES - 1; c > 0; c--) { - grille[ligne][c] = grille[ligne][c - 1]; - } - - grille[ligne][0] = tmp; - } - } - - public void decalerColonne(int colonne, int sens) { - int s = ((sens % NB_LIGNES) + NB_LIGNES) % NB_LIGNES; - - for (int etape = 0; etape < s; etape++) { - int tmp = grille[NB_LIGNES - 1][colonne]; - - for (int l = NB_LIGNES - 1; l > 0; l--) { - grille[l][colonne] = grille[l - 1][colonne]; - } - - grille[0][colonne] = tmp; - } - } - - // - - // APPLIQUER UN COUP - - - public boolean appliquerCoup(boolean estLigne, int index, int sens) { - if (partieTerminee) { - return false; - } - - // Les verrous bloquent toujours, quel que soit le mode - if (estBloque(estLigne, index)) { - return false; - } - - int[][] sauvegarde = copierGrille(); - - if (estLigne) { - decalerLigne(index, sens); - } else { - decalerColonne(index, sens); - } - - if (trouverSeries().isEmpty()) { - restaurerGrille(sauvegarde); - return false; - } - - nbCoups++; - score += resoudreEtRemplir(); - - // Verrou après chaque coup ; 2 verrous en hard mode (plus difficile) - ajouterVerrou(); - if (hardMode) { - ajouterVerrou(); - } - - if (!aUnCoupValide()) { - partieTerminee = true; - } - - return true; - } - - // - - // TROUVER LES SERIES - - - public List trouverSeries() { - boolean[][] aSupprimer = new boolean[NB_LIGNES][NB_COLONNES]; - - for (int l = 0; l < NB_LIGNES; l++) { - int c = 0; - - while (c < NB_COLONNES) { - int type = grille[l][c]; - int fin = c + 1; - - while (fin < NB_COLONNES && grille[l][fin] == type) { - fin++; - } - - if (fin - c >= 3) { - for (int k = c; k < fin; k++) { - aSupprimer[l][k] = true; - } - } - - c = fin; - } - } - - for (int col = 0; col < NB_COLONNES; col++) { - int l = 0; - - while (l < NB_LIGNES) { - int type = grille[l][col]; - int fin = l + 1; - - while (fin < NB_LIGNES && grille[fin][col] == type) { - fin++; - } - - if (fin - l >= 3) { - for (int k = l; k < fin; k++) { - aSupprimer[k][col] = true; - } - } - - l = fin; - } - } - - List positions = new ArrayList<>(); - - for (int l = 0; l < NB_LIGNES; l++) { - for (int col = 0; col < NB_COLONNES; col++) { - if (aSupprimer[l][col]) { - positions.add(new int[]{l, col}); - } - } - } - - return positions; - } - - // - - // RESOLUTION AVEC CASCADE - - - public int resoudreEtRemplir() { - int baseTotal = 0; - int nbSeries = 0; - - List series = trouverSeries(); - - while (!series.isEmpty()) { - - // Accumuler les points de base et le nombre de séries sur toutes les vagues - baseTotal += calculerPointsBase(series); - nbSeries += compterNbSeries(series); - - boolean[][] aSupprimer = new boolean[NB_LIGNES][NB_COLONNES]; - - for (int[] pos : series) { - aSupprimer[pos[0]][pos[1]] = true; - } - - // Libérer les verrous des cases supprimées - libererVerrous(aSupprimer); - - for (int col = 0; col < NB_COLONNES; col++) { - - List survivants = new ArrayList<>(); - - for (int l = NB_LIGNES - 1; l >= 0; l--) { - if (!aSupprimer[l][col]) { - survivants.add(grille[l][col]); - } - } - - int li = NB_LIGNES - 1; - - for (int val : survivants) { - grille[li][col] = val; - li--; - } - - while (li >= 0) { - grille[li][col] = aleatoire.nextInt(NB_TYPES); - li--; - } - } - - series = trouverSeries(); - } - - if (nbSeries == 0) return 0; - - // Bonus : +50% par série supplémentaire après la première (spec SAÉ) - double bonus = 1.0 + (nbSeries - 1) * 0.5; - return (int) (baseTotal * bonus); - } - - private int calculerPointsBase(List series) { - boolean[][] masque = new boolean[NB_LIGNES][NB_COLONNES]; - - for (int[] pos : series) { - masque[pos[0]][pos[1]] = true; - } - - int total = 0; - - for (int l = 0; l < NB_LIGNES; l++) { - int c = 0; - - while (c < NB_COLONNES) { - if (masque[l][c]) { - int fin = c + 1; - - while (fin < NB_COLONNES && masque[l][fin]) { - fin++; - } - - total += pointsPourLongueur(fin - c); - c = fin; - } else { - c++; - } - } - } - - for (int col = 0; col < NB_COLONNES; col++) { - int l = 0; - - while (l < NB_LIGNES) { - if (masque[l][col]) { - int fin = l + 1; - - while (fin < NB_LIGNES && masque[fin][col]) { - fin++; - } - - total += pointsPourLongueur(fin - l); - l = fin; - } else { - l++; - } - } - } - - return total; - } - - private int compterNbSeries(List series) { - boolean[][] masque = new boolean[NB_LIGNES][NB_COLONNES]; - - for (int[] pos : series) { - masque[pos[0]][pos[1]] = true; - } - - int count = 0; - - // Séries horizontales - for (int l = 0; l < NB_LIGNES; l++) { - int c = 0; - - while (c < NB_COLONNES) { - if (masque[l][c]) { - int fin = c + 1; - - while (fin < NB_COLONNES && masque[l][fin]) { - fin++; - } - - count++; - c = fin; - } else { - c++; - } - } - } - - // Séries verticales - for (int col = 0; col < NB_COLONNES; col++) { - int l = 0; - - while (l < NB_LIGNES) { - if (masque[l][col]) { - int fin = l + 1; - - while (fin < NB_LIGNES && masque[fin][col]) { - fin++; - } - - count++; - l = fin; - } else { - l++; - } - } - } - - return count; - } - - private int pointsPourLongueur(int longueur) { - if (longueur == 3) { - return 8; - } else if (longueur == 4) { - return 16; - } else if (longueur == 5) { - return 32; - } else { - return 64; - } - } - - // - - // VERROUS (hard mode) - - - private boolean estBloque(boolean estLigne, int index) { - if (estLigne) { - for (int col = 0; col < NB_COLONNES; col++) { - if (verrous[index][col]) { - return true; - } - } - } else { - for (int lig = 0; lig < NB_LIGNES; lig++) { - if (verrous[lig][index]) { - return true; - } - } - } - - return false; - } - - private void ajouterVerrou() { - int intervalle = Math.max(1, 5 - nbCoups / 10); - - if (nbCoups % intervalle != 0) { - return; - } - - List casesLibres = new ArrayList<>(); - - for (int l = 0; l < NB_LIGNES; l++) { - for (int col = 0; col < NB_COLONNES; col++) { - if (!verrous[l][col]) { - casesLibres.add(new int[]{l, col}); - } - } - } - - if (casesLibres.isEmpty()) { - return; - } - - int[] caseChoisie = casesLibres.get(aleatoire.nextInt(casesLibres.size())); - verrous[caseChoisie[0]][caseChoisie[1]] = true; - } - - private void libererVerrous(boolean[][] aSupprimer) { - for (int l = 0; l < NB_LIGNES; l++) { - for (int col = 0; col < NB_COLONNES; col++) { - if (aSupprimer[l][col]) { - verrous[l][col] = false; - } - } - } - } - - // - - // DETECTION FIN DE PARTIE - - - public boolean aUnCoupValide() { - // Teste tous les décalages possibles (1 à N-1) pour les lignes - for (int i = 0; i < NB_LIGNES; i++) { - - // AJOUT : Si la ligne est bloquée par un verrou, on ne peut pas la bouger - if (estBloque(true, i)) continue; - - for (int s = 1; s < NB_COLONNES; s++) { - if (coupCreeSerie(true, i, s)) { - return true; - } - } - } - - // Teste tous les décalages possibles (1 à N-1) pour les colonnes - for (int j = 0; j < NB_COLONNES; j++) { - - // AJOUT : Si la colonne est bloquée par un verrou, on ne peut pas la bouger - if (estBloque(false, j)) continue; - - for (int s = 1; s < NB_LIGNES; s++) { - if (coupCreeSerie(false, j, s)) { - return true; - } - } - } - - return false; - } - - public void forcerFinDePartie() { - this.partieTerminee = true; - } - - private boolean coupCreeSerie(boolean estLigne, int index, int sens) { - int[][] sauvegarde = copierGrille(); - - if (estLigne) { - decalerLigne(index, sens); - } else { - decalerColonne(index, sens); - } - - boolean resultat = !trouverSeries().isEmpty(); - - restaurerGrille(sauvegarde); - - return resultat; - } - - // - - // UTILITAIRES PRIVES - - - private int[][] copierGrille() { - int[][] copie = new int[NB_LIGNES][NB_COLONNES]; - - for (int l = 0; l < NB_LIGNES; l++) { - System.arraycopy(grille[l], 0, copie[l], 0, NB_COLONNES); - } - - return copie; - } - - private void restaurerGrille(int[][] sauvegarde) { - for (int l = 0; l < NB_LIGNES; l++) { - System.arraycopy(sauvegarde[l], 0, grille[l], 0, NB_COLONNES); - } - } - - -} diff --git a/src/src/main/java/sae/chuzzle/FinPartieActivity.java b/src/src/main/java/sae/chuzzle/FinPartieActivity.java deleted file mode 100644 index e6fe906..0000000 --- a/src/src/main/java/sae/chuzzle/FinPartieActivity.java +++ /dev/null @@ -1,50 +0,0 @@ -package sae.chuzzle; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.widget.Button; -import android.widget.TextView; - -public class FinPartieActivity extends Activity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_fin_partie); - - // Récupérer les données passées par le Controleur - int score = getIntent().getIntExtra("score", 0); - int nbCoups = getIntent().getIntExtra("nbCoups", 0); - long graine = getIntent().getLongExtra("graine", 0L); - - // Afficher les données - TextView tvScore = findViewById(R.id.tvFinScore); - TextView tvCoups = findViewById(R.id.tvFinCoups); - TextView tvGraine = findViewById(R.id.tvFinGraine); - - tvScore.setText(String.valueOf(score)); - tvCoups.setText(String.valueOf(nbCoups)); - tvGraine.setText(String.valueOf(graine)); - - // Bouton retour au menu - Button btnMenu = findViewById(R.id.btnFinMenu); - btnMenu.setOnClickListener(v -> { - Intent intent = new Intent(this, MenuActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - startActivity(intent); - finish(); - }); - } - - // - - // RETOUR ARRIERE = menu principal - - @Override - public void onBackPressed() { - Intent intent = new Intent(this, MenuActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - startActivity(intent); - finish(); - } -} diff --git a/src/src/main/java/sae/chuzzle/GestionnaireTactile.java b/src/src/main/java/sae/chuzzle/GestionnaireTactile.java deleted file mode 100644 index 3f9fecf..0000000 --- a/src/src/main/java/sae/chuzzle/GestionnaireTactile.java +++ /dev/null @@ -1,140 +0,0 @@ -package sae.chuzzle; - -import android.view.MotionEvent; -import android.view.View; - -public class GestionnaireTactile implements View.OnTouchListener { - - private static final int NB_LIGNES = EtatJeu.NB_LIGNES; - private static final int NB_COLONNES = EtatJeu.NB_COLONNES; - private static final float SEUIL_DIRECTION_PX = 10f; - - private final VueGrille vueGrille; - private final EtatJeu etatJeu; - private final Controleur controleur; - - private float touchDebutX, touchDebutY; - private int ligneTouchee, colonneTouchee; - private Boolean estLigne; - private int indexGlissement; - private float decalagePx; - private float tailleCase; - - public GestionnaireTactile(VueGrille vueGrille, - EtatJeu etatJeu, - Controleur controleur) { - this.vueGrille = vueGrille; - this.etatJeu = etatJeu; - this.controleur = controleur; - } - - @Override - public boolean onTouch(View v, MotionEvent event) { - - if (etatJeu.estTerminee()) { - return false; - } - - switch (event.getAction()) { - - case MotionEvent.ACTION_DOWN: - tailleCase = calculerTailleCase(); - gererDebut(event); - return true; - - case MotionEvent.ACTION_MOVE: - gererMouvement(event); - return true; - - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - gererFin(event.getAction() == MotionEvent.ACTION_UP); - return true; - } - - return false; - } - - private void gererDebut(MotionEvent event) { - touchDebutX = event.getX(); - touchDebutY = event.getY(); - estLigne = null; - decalagePx = 0f; - - float margeGauche = (vueGrille.getWidth() - tailleCase * NB_COLONNES) / 2f; - float margeHaut = (vueGrille.getHeight() - tailleCase * NB_LIGNES) / 2f; - - ligneTouchee = (int) ((touchDebutY - margeHaut) / tailleCase); - colonneTouchee = (int) ((touchDebutX - margeGauche) / tailleCase); - - ligneTouchee = Math.max(0, Math.min(NB_LIGNES - 1, ligneTouchee)); - colonneTouchee = Math.max(0, Math.min(NB_COLONNES - 1, colonneTouchee)); - } - - private void gererMouvement(MotionEvent event) { - float dx = event.getX() - touchDebutX; - float dy = event.getY() - touchDebutY; - - if (estLigne == null) { - if (Math.abs(dx) > SEUIL_DIRECTION_PX || Math.abs(dy) > SEUIL_DIRECTION_PX) { - estLigne = Math.abs(dx) >= Math.abs(dy); - - if (estLigne) { - indexGlissement = ligneTouchee; - } else { - indexGlissement = colonneTouchee; - } - } else { - return; - } - } - - if (estLigne) { - decalagePx = dx; - } else { - decalagePx = dy; - } - - // Affiche le glissement réel du doigt (permet la rotation multi-cases) - vueGrille.definirGlissement(estLigne, indexGlissement, decalagePx); - } - - private void gererFin(boolean estRelachement) { - - if (estLigne == null) { - vueGrille.annulerGlissement(); - return; - } - - if (tailleCase <= 1f) { - vueGrille.annulerGlissement(); - estLigne = null; - return; - } - - // Arrondi au nombre de cases le plus proche (permet ±1, ±2, ±3…) - int nbCases = (int) Math.round(decalagePx / tailleCase); - - if (nbCases != 0 && estRelachement) { - boolean accepte = etatJeu.appliquerCoup(estLigne, indexGlissement, nbCases); - if (accepte) { - controleur.rafraichirAffichage(); - controleur.verifierFinDePartie(); - } - } - - vueGrille.annulerGlissement(); - estLigne = null; - } - - private float calculerTailleCase() { - float l = vueGrille.getWidth(); - float h = vueGrille.getHeight(); - - if (l == 0 || h == 0) { - return 1f; - } - - return Math.min(l / NB_COLONNES, h / NB_LIGNES); - } -} \ No newline at end of file diff --git a/src/src/main/java/sae/chuzzle/MainActivity.java b/src/src/main/java/sae/chuzzle/MainActivity.java deleted file mode 100644 index 1e48cd3..0000000 --- a/src/src/main/java/sae/chuzzle/MainActivity.java +++ /dev/null @@ -1,116 +0,0 @@ -package sae.chuzzle; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.view.View; -import android.widget.Button; -import android.widget.RadioButton; -import android.widget.Spinner; -import android.widget.TextView; - -public class MainActivity extends Activity implements View.OnClickListener { - - - - private Controleur controleur; - private Button btnJouer; - private Button btnMenu; - - - private boolean hardMode; - private EtatJeu etatJeu; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - - // --- Modèle --- - long graine = getIntent().getLongExtra("graine", System.currentTimeMillis()); - hardMode = getSharedPreferences("chuzzle_prefs", MODE_PRIVATE) - .getBoolean("hard_mode", false); - boolean daltonien = getSharedPreferences("chuzzle_prefs", MODE_PRIVATE) - .getBoolean("daltonien", false); - - etatJeu = new EtatJeu(graine, hardMode); - - // --- Restauration si retour de pause --- - if (savedInstanceState != null) { - etatJeu.restaurerEtat(savedInstanceState); - } - - // --- Vue --- - VueGrille vueGrille = findViewById(R.id.vueGrille); - vueGrille.definirModeDaltonien(daltonien); - - - - // --- Controleur --- - btnJouer = findViewById(R.id.btnJouer); - btnJouer.setOnClickListener(this); - - btnMenu = findViewById(R.id.btnMenu); - btnMenu.setOnClickListener(this); - - - controleur = new Controleur( - this, - etatJeu, - vueGrille, - graine, - (TextView) findViewById(R.id.tvScore), - (TextView) findViewById(R.id.tvCoups), - (RadioButton) findViewById(R.id.rbLigne), - (RadioButton) findViewById(R.id.rbDroite), - (Spinner) findViewById(R.id.spinnerIndex), - btnJouer, - hardMode - ); - - // --- Gestion tactile --- - GestionnaireTactile gestionnaireTactile = - new GestionnaireTactile(vueGrille, etatJeu, controleur); - vueGrille.setOnTouchListener(gestionnaireTactile); - - // --- Logique Hard mode --- - if (hardMode) { - // TODO: Ajouter la nouvelle fonctionnalité pour le hard mode ici (en remplacement du timer) - } - } - - // - - // - - // - - // CYCLE DE VIE - - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - if (etatJeu != null) { - etatJeu.sauvegarderEtat(outState); - } - if (controleur != null) { - controleur.sauvegarderEtat(outState); - } - } - - @Override - protected void onDestroy() { - super.onDestroy(); - - } - - @Override - public void onClick(View v) { - if (v == btnJouer) { - controleur.gererCoupJoueur(); - } - if (v == btnMenu) { - etatJeu.forcerFinDePartie(); - Intent intent = new Intent(this, MenuActivity.class); - startActivity(intent); - } - } -} diff --git a/src/src/main/java/sae/chuzzle/MenuActivity.java b/src/src/main/java/sae/chuzzle/MenuActivity.java deleted file mode 100644 index a4bd5f5..0000000 --- a/src/src/main/java/sae/chuzzle/MenuActivity.java +++ /dev/null @@ -1,44 +0,0 @@ -package sae.chuzzle; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.view.View; -import android.widget.Button; - -public class MenuActivity extends Activity implements View.OnClickListener { - - private Button btnNouvellePartie; - private Button btnPartieGraine; - private Button btnOptions; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_menu); - - btnNouvellePartie = findViewById(R.id.btnNouvellePartie); - btnPartieGraine = findViewById(R.id.btnPartieGraine); - btnOptions = findViewById(R.id.btnOptions); - - btnNouvellePartie.setOnClickListener(this); - btnPartieGraine.setOnClickListener(this); - btnOptions.setOnClickListener(this); - } - - @Override - public void onClick(View v) { - if (v == btnNouvellePartie) { - long graine = System.currentTimeMillis(); - Intent intent = new Intent(this, MainActivity.class); - intent.putExtra("graine", graine); - startActivity(intent); - } else if (v == btnPartieGraine) { - Intent intent = new Intent(this, SeedActivity.class); - startActivity(intent); - } else if (v == btnOptions) { - Intent intent = new Intent(this, OptionsActivity.class); - startActivity(intent); - } - } -} \ No newline at end of file diff --git a/src/src/main/java/sae/chuzzle/OptionsActivity.java b/src/src/main/java/sae/chuzzle/OptionsActivity.java deleted file mode 100644 index 9d0bf7d..0000000 --- a/src/src/main/java/sae/chuzzle/OptionsActivity.java +++ /dev/null @@ -1,58 +0,0 @@ -package sae.chuzzle; - -import android.app.Activity; -import android.content.Intent; -import android.content.SharedPreferences; -import android.os.Bundle; -import android.view.View; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.CompoundButton; - -public class OptionsActivity extends Activity - implements CompoundButton.OnCheckedChangeListener, View.OnClickListener { - - private SharedPreferences prefs; - private CheckBox checkDaltonien; - private CheckBox checkHard; - - private Button btnRetour; - - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_options); - - prefs = getSharedPreferences("chuzzle_prefs", MODE_PRIVATE); - - checkDaltonien = findViewById(R.id.checkDaltonien); - checkHard = findViewById(R.id.checkHard); - btnRetour = findViewById(R.id.btnBack); - - checkDaltonien.setChecked(prefs.getBoolean("daltonien", false)); - checkHard.setChecked(prefs.getBoolean("hard_mode", false)); - - checkDaltonien.setOnCheckedChangeListener(this); - checkHard.setOnCheckedChangeListener(this); - btnRetour.setOnClickListener(this); - } - - @Override - public void onCheckedChanged(CompoundButton bouton, boolean estCoche) { - if (bouton == checkDaltonien) { - prefs.edit().putBoolean("daltonien", estCoche).apply(); - } else if (bouton == checkHard) { - prefs.edit().putBoolean("hard_mode", estCoche).apply(); - } - } - - @Override - public void onClick(View v) { - if (v == btnRetour) { - Intent intent = new Intent(this, MenuActivity.class); - startActivity(intent); - } - - } -} diff --git a/src/src/main/java/sae/chuzzle/SeedActivity.java b/src/src/main/java/sae/chuzzle/SeedActivity.java deleted file mode 100644 index 50c1639..0000000 --- a/src/src/main/java/sae/chuzzle/SeedActivity.java +++ /dev/null @@ -1,67 +0,0 @@ -package sae.chuzzle; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.view.View; -import android.widget.Button; -import android.widget.EditText; -import android.widget.Toast; - -public class SeedActivity extends Activity implements View.OnClickListener { - - private EditText etGraine; - private Button btnJouer; - - private Button btnRetour; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_seed); - - etGraine = findViewById(R.id.etGraine); - btnJouer = findViewById(R.id.btnJouer); - btnRetour = findViewById(R.id.btnBack); - - btnRetour.setOnClickListener(this); - - btnJouer.setOnClickListener(this); - } - - @Override - public void onClick(View v) { - if (v == btnJouer) { - lancerPartieAvecGraine(); - } - if (v == btnRetour) { - Intent intent = new Intent(this, MenuActivity.class); - startActivity(intent); - } - } - - private void lancerPartieAvecGraine() { - String texte = etGraine.getText().toString().trim(); - - if (texte.isEmpty()) { - Toast.makeText( - this, - "Veuillez entrer une graine.", - Toast.LENGTH_SHORT - ).show(); - return; - } - - long graine; - - try { - graine = Long.parseLong(texte); - } catch (NumberFormatException e) { - graine = texte.hashCode(); - } - - Intent intent = new Intent(this, MainActivity.class); - intent.putExtra("graine", graine); - startActivity(intent); - } -} \ No newline at end of file diff --git a/src/src/main/java/sae/chuzzle/VueGrille.java b/src/src/main/java/sae/chuzzle/VueGrille.java deleted file mode 100644 index 8768302..0000000 --- a/src/src/main/java/sae/chuzzle/VueGrille.java +++ /dev/null @@ -1,307 +0,0 @@ -package sae.chuzzle; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.util.AttributeSet; -import android.view.View; - -import androidx.annotation.NonNull; - -public class VueGrille extends View { - - // ========================================================= - // Constantes - // ========================================================= - - private static final int NB_LIGNES = 6; - private static final int NB_COLONNES = 6; - private static final int NB_TYPES = 7; - - /** Symboles pour le mode daltonien, un par type. */ - private static final String[] SYMBOLES = {"●", "■", "▲", "✚", "★", "♦", "✿"}; - - // ========================================================= - // Données métier - // ========================================================= - - /** Grille reçue depuis MainActivity (tableau brut). */ - private int[][] grille = new int[NB_LIGNES][NB_COLONNES]; - - /** Verrous reçus depuis MainActivity. */ - private boolean[][] verrous = new boolean[NB_LIGNES][NB_COLONNES]; - - private boolean modeDaltonien = false; - - // ========================================================= - // État de l'animation de glissement - // ========================================================= - - /** - * true = on anime une ligne, - * false = on anime une colonne, - * null = pas d'animation en cours. - */ - private Boolean animEstLigne = null; - - /** Index de la ligne ou colonne en cours de glissement. */ - private int animIndex = 0; - - /** - * Décalage courant en pixels (positif = droite/bas, - * négatif = gauche/haut). - */ - private float animDecalagePx = 0f; - - // ========================================================= - // Outils de dessin - // ========================================================= - - private final Paint pinceauCase = new Paint(); - private final Paint pinceauSymbole = new Paint(); - - // ========================================================= - // Constructeurs - // ========================================================= - - public VueGrille(Context contexte) { - super(contexte); - initPinceaux(); - } - - public VueGrille(Context context, AttributeSet attrs) { - super(context, attrs); - initPinceaux(); - } - - private void initPinceaux() { - pinceauCase.setAntiAlias(true); - pinceauCase.setStyle(Paint.Style.FILL); - - pinceauSymbole.setAntiAlias(true); - pinceauSymbole.setColor(0xFF000000); - pinceauSymbole.setTextAlign(Paint.Align.CENTER); - } - - // ========================================================= - // API publique - // ========================================================= - - /** - * Reçoit une copie de la grille depuis MainActivity. - * VueGrille ne sait pas d'où viennent ces données, - * elle sait juste les dessiner. - */ - public void definirGrille(int[][] nouvelleGrille) { - for (int l = 0; l < NB_LIGNES; l++) { - System.arraycopy(nouvelleGrille[l], 0, grille[l], 0, NB_COLONNES); - } - invalidate(); - } - - public void definirModeDaltonien(boolean actif) { - this.modeDaltonien = actif; - invalidate(); - } - - public void definirVerrous(boolean[][] nouveauxVerrous) { - for (int l = 0; l < NB_LIGNES; l++) { - System.arraycopy(nouveauxVerrous[l], 0, verrous[l], 0, NB_COLONNES); - } - invalidate(); - } - - // ========================================================= - // API animation de glissement (appelée par GestionnaireTactile) - // ========================================================= - - /** - * Déclenche l'animation de glissement en temps réel. - * - * @param estLigne true = on déplace une ligne, false = une colonne - * @param index index de la ligne ou colonne (0-based) - * @param decalagePx décalage courant en pixels (peut être négatif) - */ - public void definirGlissement(boolean estLigne, int index, float decalagePx) { - this.animEstLigne = estLigne; - this.animIndex = index; - this.animDecalagePx = decalagePx; - invalidate(); - } - - /** - * Annule l'animation de glissement et revient à l'affichage normal. - */ - public void annulerGlissement() { - this.animEstLigne = null; - invalidate(); - } - - // ========================================================= - // Dessin - // ========================================================= - - @Override - protected void onDraw(@NonNull Canvas canvas) { - super.onDraw(canvas); - - int largeur = getWidth(); - int hauteur = getHeight(); - - float tailleCase = Math.min( - largeur / (float) NB_COLONNES, - hauteur / (float) NB_LIGNES - ); - - float margeGauche = (largeur - tailleCase * NB_COLONNES) / 2f; - float margeHaut = (hauteur - tailleCase * NB_LIGNES) / 2f; - - pinceauSymbole.setTextSize(tailleCase * 0.4f); - - for (int ligne = 0; ligne < NB_LIGNES; ligne++) { - for (int colonne = 0; colonne < NB_COLONNES; colonne++) { - - // -------------------------------------------------- - // Calcul de l'offset d'animation pour cette case - // -------------------------------------------------- - float offsetX = 0f; - float offsetY = 0f; - - if (animEstLigne != null) { - if (animEstLigne && ligne == animIndex) { - // Décalage horizontal de toute la ligne - offsetX = animDecalagePx; - } else if (!animEstLigne && colonne == animIndex) { - // Décalage vertical de toute la colonne - offsetY = animDecalagePx; - } - } - - // -------------------------------------------------- - // Position de base de la case - // -------------------------------------------------- - float x1 = margeGauche + colonne * tailleCase + 6 + offsetX; - float y1 = margeHaut + ligne * tailleCase + 6 + offsetY; - float x2 = margeGauche + (colonne + 1) * tailleCase - 6 + offsetX; - float y2 = margeHaut + (ligne + 1) * tailleCase - 6 + offsetY; - - // -------------------------------------------------- - // Dessin avec wrap-around (la case qui sort d'un - // côté réapparaît de l'autre côté) - // -------------------------------------------------- - dessinerCase(canvas, ligne, colonne, x1, y1, x2, y2, - tailleCase, margeGauche, margeHaut, offsetX, offsetY); - } - } - } - - /** - * Dessine une case à la position donnée. - * Si la case sort des bords (wrap-around), elle est aussi dessinée - * du côté opposé de la grille. - */ - private void dessinerCase(Canvas canvas, - int ligne, int colonne, - float x1, float y1, float x2, float y2, - float tailleCase, - float margeGauche, float margeHaut, - float offsetX, float offsetY) { - - int type = grille[ligne][colonne]; - - // Bornage de la grille (en pixels) - float borneGaucheGrille = margeGauche; - float bordDroiteGrille = margeGauche + NB_COLONNES * tailleCase; - float borneHautGrille = margeHaut; - float bordBasGrille = margeHaut + NB_LIGNES * tailleCase; - - // Largeur totale de la ligne / hauteur totale de la colonne en pixels - float largeurGrille = NB_COLONNES * tailleCase; - float hauteurGrille = NB_LIGNES * tailleCase; - - // Dessine la case principale - dessinerRectCase(canvas, type, ligne, colonne, x1, y1, x2, y2); - - // Wrap-around horizontal (pour les lignes) - if (offsetX != 0f) { - float wrapX1 = x1, wrapX2 = x2; - - if (x2 > bordDroiteGrille) { - // La case déborde à droite → réapparaît à gauche - wrapX1 = x1 - largeurGrille; - wrapX2 = x2 - largeurGrille; - dessinerRectCase(canvas, type, ligne, colonne, wrapX1, y1, wrapX2, y2); - } else if (x1 < borneGaucheGrille) { - // La case déborde à gauche → réapparaît à droite - wrapX1 = x1 + largeurGrille; - wrapX2 = x2 + largeurGrille; - dessinerRectCase(canvas, type, ligne, colonne, wrapX1, y1, wrapX2, y2); - } - } - - // Wrap-around vertical (pour les colonnes) - if (offsetY != 0f) { - float wrapY1 = y1, wrapY2 = y2; - - if (y2 > bordBasGrille) { - // La case déborde en bas → réapparaît en haut - wrapY1 = y1 - hauteurGrille; - wrapY2 = y2 - hauteurGrille; - dessinerRectCase(canvas, type, ligne, colonne, x1, wrapY1, x2, wrapY2); - } else if (y1 < borneHautGrille) { - // La case déborde en haut → réapparaît en bas - wrapY1 = y1 + hauteurGrille; - wrapY2 = y2 + hauteurGrille; - dessinerRectCase(canvas, type, ligne, colonne, x1, wrapY1, x2, wrapY2); - } - } - } - - /** - * Dessine le rectangle coloré d'une case + verrou + symbole daltonien. - */ - private void dessinerRectCase(Canvas canvas, int type, - int ligne, int colonne, - float x1, float y1, float x2, float y2) { - - // Couleur de fond - definirCouleur(type); - canvas.drawRoundRect(x1, y1, x2, y2, 20, 20, pinceauCase); - - // Assombrir si verrouillée - if (verrous[ligne][colonne]) { - pinceauCase.setARGB(120, 0, 0, 0); - canvas.drawRoundRect(x1, y1, x2, y2, 20, 20, pinceauCase); - } - - float cx = (x1 + x2) / 2f; - float cy = (y1 + y2) / 2f - - (pinceauSymbole.descent() + pinceauSymbole.ascent()) / 2f; - - // Symbole daltonien - if (modeDaltonien) { - canvas.drawText(SYMBOLES[type % NB_TYPES], cx, cy, pinceauSymbole); - } - - // Cadenas par-dessus si verrouillée - if (verrous[ligne][colonne]) { - canvas.drawText("🔒", cx, cy, pinceauSymbole); - } - } - - // ========================================================= - // Utilitaire privé - // ========================================================= - - private void definirCouleur(int type) { - switch (type % NB_TYPES) { - case 0: pinceauCase.setARGB(255, 200, 200, 200); break; - case 1: pinceauCase.setARGB(255, 255, 105, 180); break; - case 2: pinceauCase.setARGB(255, 90, 230, 200); break; - case 3: pinceauCase.setARGB(255, 100, 170, 255); break; - case 4: pinceauCase.setARGB(255, 255, 220, 90); break; - case 5: pinceauCase.setARGB(255, 255, 140, 90); break; - case 6: pinceauCase.setARGB(255, 255, 90, 90); break; - } - } -} \ No newline at end of file diff --git a/src/src/main/res/drawable-v24/ic_launcher_foreground.xml b/src/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index 2b068d1..0000000 --- a/src/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/src/src/main/res/drawable/ic_launcher_background.xml b/src/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 07d5da9..0000000 --- a/src/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/src/main/res/drawable/ic_launcher_foreground.xml b/src/src/main/res/drawable/ic_launcher_foreground.xml deleted file mode 100644 index 2b068d1..0000000 --- a/src/src/main/res/drawable/ic_launcher_foreground.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/src/src/main/res/layout/activity_fin_partie.xml b/src/src/main/res/layout/activity_fin_partie.xml deleted file mode 100644 index bca6399..0000000 --- a/src/src/main/res/layout/activity_fin_partie.xml +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/src/main/res/layout/activity_seed.xml b/src/src/main/res/layout/activity_seed.xml deleted file mode 100644 index 7ac4c4a..0000000 --- a/src/src/main/res/layout/activity_seed.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - -