From 2bdd61a6ad6a6b9ace12b335b5423314ebfbb210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?La=C3=ABtitia=20VAL?= Date: Thu, 19 Mar 2026 12:49:45 +0100 Subject: [PATCH] Nettoyage dossier --- game/EtatJeu.java | 64 -- src/src.zip | Bin 64813 -> 0 bytes .../sae/chuzzle/ExampleInstrumentedTest.java | 26 - src/src/main/AndroidManifest.xml | 41 -- src/src/main/java/sae/chuzzle/Controleur.java | 133 ---- src/src/main/java/sae/chuzzle/EtatJeu.java | 598 ------------------ .../java/sae/chuzzle/FinPartieActivity.java | 50 -- .../java/sae/chuzzle/GestionnaireTactile.java | 140 ---- .../main/java/sae/chuzzle/MainActivity.java | 116 ---- .../main/java/sae/chuzzle/MenuActivity.java | 44 -- .../java/sae/chuzzle/OptionsActivity.java | 58 -- .../main/java/sae/chuzzle/SeedActivity.java | 67 -- src/src/main/java/sae/chuzzle/VueGrille.java | 307 --------- .../drawable-v24/ic_launcher_foreground.xml | 30 - .../res/drawable/ic_launcher_background.xml | 170 ----- .../res/drawable/ic_launcher_foreground.xml | 30 - .../main/res/layout/activity_fin_partie.xml | 91 --- src/src/main/res/layout/activity_main.xml | 97 --- src/src/main/res/layout/activity_menu.xml | 38 -- src/src/main/res/layout/activity_options.xml | 78 --- src/src/main/res/layout/activity_seed.xml | 39 -- .../res/mipmap-anydpi-v26/ic_launcher.xml | 6 - .../mipmap-anydpi-v26/ic_launcher_round.xml | 6 - src/src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 1404 -> 0 bytes .../res/mipmap-hdpi/ic_launcher_round.webp | Bin 2898 -> 0 bytes src/src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 982 -> 0 bytes .../res/mipmap-mdpi/ic_launcher_round.webp | Bin 1772 -> 0 bytes .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 1900 -> 0 bytes .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 3918 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 2884 -> 0 bytes .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 5914 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 3844 -> 0 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 7778 -> 0 bytes src/src/main/res/values-night/themes.xml | 4 - src/src/main/res/values/colors.xml | 5 - src/src/main/res/values/strings.xml | 3 - src/src/main/res/values/themes.xml | 4 - src/src/main/res/xml/backup_rules.xml | 13 - .../main/res/xml/data_extraction_rules.xml | 19 - src/src/main/res/xml/preferences.xml | 4 - .../java/sae/chuzzle/ExampleUnitTest.java | 17 - ui/MainActivity.java | 21 - ui/VueGrille.java | 79 --- 43 files changed, 2398 deletions(-) delete mode 100644 game/EtatJeu.java delete mode 100644 src/src.zip delete mode 100644 src/src/androidTest/java/sae/chuzzle/ExampleInstrumentedTest.java delete mode 100644 src/src/main/AndroidManifest.xml delete mode 100644 src/src/main/java/sae/chuzzle/Controleur.java delete mode 100644 src/src/main/java/sae/chuzzle/EtatJeu.java delete mode 100644 src/src/main/java/sae/chuzzle/FinPartieActivity.java delete mode 100644 src/src/main/java/sae/chuzzle/GestionnaireTactile.java delete mode 100644 src/src/main/java/sae/chuzzle/MainActivity.java delete mode 100644 src/src/main/java/sae/chuzzle/MenuActivity.java delete mode 100644 src/src/main/java/sae/chuzzle/OptionsActivity.java delete mode 100644 src/src/main/java/sae/chuzzle/SeedActivity.java delete mode 100644 src/src/main/java/sae/chuzzle/VueGrille.java delete mode 100644 src/src/main/res/drawable-v24/ic_launcher_foreground.xml delete mode 100644 src/src/main/res/drawable/ic_launcher_background.xml delete mode 100644 src/src/main/res/drawable/ic_launcher_foreground.xml delete mode 100644 src/src/main/res/layout/activity_fin_partie.xml delete mode 100644 src/src/main/res/layout/activity_main.xml delete mode 100644 src/src/main/res/layout/activity_menu.xml delete mode 100644 src/src/main/res/layout/activity_options.xml delete mode 100644 src/src/main/res/layout/activity_seed.xml delete mode 100644 src/src/main/res/mipmap-anydpi-v26/ic_launcher.xml delete mode 100644 src/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 src/src/main/res/mipmap-hdpi/ic_launcher.webp delete mode 100644 src/src/main/res/mipmap-hdpi/ic_launcher_round.webp delete mode 100644 src/src/main/res/mipmap-mdpi/ic_launcher.webp delete mode 100644 src/src/main/res/mipmap-mdpi/ic_launcher_round.webp delete mode 100644 src/src/main/res/mipmap-xhdpi/ic_launcher.webp delete mode 100644 src/src/main/res/mipmap-xhdpi/ic_launcher_round.webp delete mode 100644 src/src/main/res/mipmap-xxhdpi/ic_launcher.webp delete mode 100644 src/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp delete mode 100644 src/src/main/res/mipmap-xxxhdpi/ic_launcher.webp delete mode 100644 src/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp delete mode 100644 src/src/main/res/values-night/themes.xml delete mode 100644 src/src/main/res/values/colors.xml delete mode 100644 src/src/main/res/values/strings.xml delete mode 100644 src/src/main/res/values/themes.xml delete mode 100644 src/src/main/res/xml/backup_rules.xml delete mode 100644 src/src/main/res/xml/data_extraction_rules.xml delete mode 100644 src/src/main/res/xml/preferences.xml delete mode 100644 src/src/test/java/sae/chuzzle/ExampleUnitTest.java delete mode 100644 ui/MainActivity.java delete mode 100644 ui/VueGrille.java 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 28b9cec47f0ecfac6bd640289b5538d6b18f86a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 64813 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 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 @@ - - - - - - - -