diff --git a/src/Algorithmes.java b/src/Algorithmes.java index d4e2558ac7e9e5012bf56352c484217da4dd7be9..a289128f5455563224972845e92575c53630c499 100644 --- a/src/Algorithmes.java +++ b/src/Algorithmes.java @@ -123,7 +123,8 @@ public class Algorithmes { // nous sommes le bot qui joue double scoremax = Double.NEGATIVE_INFINITY; for(Etat s : S) { - scoremax = Math.max(scoremax, eval(s, nousNoir, c-1, eval0)); + scoremax = Math.max(scoremax, evaluationAB(s, nousNoir, c-1, alpha, beta, eval0)); + if(scoremax >= beta) { return scoremax; } @@ -133,7 +134,7 @@ public class Algorithmes { } else { double scoremin = Double.POSITIVE_INFINITY; for(Etat s : S) { - scoremin = Math.min(scoremin, eval(s, nousNoir, c-1, eval0)); + scoremin = Math.min(scoremin, evaluationAB(s, nousNoir, c-1,alpha, beta, eval0)); if(scoremin <= alpha) { return scoremin; } diff --git a/src/Bot.java b/src/Bot.java index 3fc7e5ece832e88677fa8df88a3ac2f31e38ebf6..3d3c4a03b82cef1eee1f65410efd22390ffc67fb 100644 --- a/src/Bot.java +++ b/src/Bot.java @@ -40,30 +40,42 @@ public class Bot extends Joueur { /** * Appelle Algorithmes.minmax pour obtenir le meilleur successeur, puis compare l'ancien etat et l'etat de minmax pour trouver les coordonnees proposées par minmax. + * * @return un tableau {x, y} pour la case jouée. */ private int[] chercherMeilleurCoup() { - // On récupère le meilleur successeur de minmax boolean nousNoir = etatCourant.joueurCourantEstNoir; Etat meilleur; if (utiliserElagageAB) { - meilleur = algo.minimaxElagageAB(etatCourant, etatCourant.joueurCourantEstNoir, profondeur, evalIndex); + meilleur = algo.minimaxElagageAB(etatCourant, nousNoir, profondeur, evalIndex); } else { - meilleur = algo.minmax(etatCourant, etatCourant.joueurCourantEstNoir, profondeur, evalIndex); + meilleur = algo.minmax(etatCourant, nousNoir, profondeur, evalIndex); } - - // On cherche la case jouée en comparant les deux tableaux Pion[][] avant = etatCourant.getTableau(); Pion[][] apres = meilleur.getTableau(); for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { - if (avant[x][y] == null && apres[x][y] != null) { // On ignore les ancienne cases avec des valeurs, on prend juste les cases en plus du tableau "apres" + if (avant[x][y] == null && apres[x][y] != null) { return new int[]{ x, y }; } } } - // Par défaut à cause du if - return new int[]{ 0, 0 }; + // Si le coup n'a pas été trouvé par comparaison directe des tableaux + System.out.println("Aucun meilleur coup détecté par algo, tentative via successeurs"); + + for (Etat succ : etatCourant.successeurs()) { + Pion[][] before = etatCourant.getTableau(); + Pion[][] after = succ.getTableau(); + + for (int x = 0; x < 8; x++) { + for (int y = 0; y < 8; y++) { + if (before[x][y] == null && after[x][y] != null) { + return new int[]{x, y}; + } + } + } + } + throw new IllegalStateException("Aucun coup trouvé entre l'état courant et le meilleur successeur, même parmi les successeurs explicites"); } } diff --git a/src/ComparaisonEval.java b/src/ComparaisonEval.java index 5ecbab3fa2517b7e988bb37b0c7b2f18571760eb..cf0bcf87f7aeb320e077450b1c10dfcf40a4375f 100644 --- a/src/ComparaisonEval.java +++ b/src/ComparaisonEval.java @@ -7,165 +7,139 @@ public class ComparaisonEval { int eval1 = sc.nextInt(); int eval2 = sc.nextInt(); int profondeur = sc.nextInt(); + System.out.println("Souhaitez-vous faire avec élagage (0) ou sans élagage (1)"); - int choice = sc.nextInt();//J'aurais surement pu utiliser sc.nextboolean mais pas certain de comment ça fonctionne et j'ai plus le temps .-. - long startTime = System.nanoTime(); //On commence à compter le temps que prennent les eval après qu'on ait sélectionné les paramètres - boolean utiliserElagageAB = true; - switch(choice){ - case 0 : - utiliserElagageAB = true; - break; - case 1 : - utiliserElagageAB = false; - break; - default : - System.out.println("Choix non conforme, elagage sera activé par défaut"); - break; + int choice = sc.nextInt(); + boolean utiliserElagageAB = (choice == 0); - } sc.close(); + long startTime = System.nanoTime(); int resultat = 0; - int scoren = 0; - int scoreb = 0; - int nbMatches = 1; - - // Phase 1 : eval1 commence (Noir = eval1, Blanc = eval2) - for (int i = 0; i < nbMatches; i++) {// On simule nbmatches fois fois - Etat etat = new Etat(); - Bot botNoir = new Bot(true, eval1, profondeur, utiliserElagageAB); - Bot botBlanc = new Bot(false, eval2, profondeur, utiliserElagageAB); - etat.setJoueurNoir(botNoir); - etat.setJoueurBlanc(botBlanc); - // Simulation d'une partie - int passes = 0; - while (passes < 2 && etat.getNbPion() < 64) { - - // Aucun coup pour le joueur courant, il passe - if (etat.successeurs().isEmpty()) { - passes++; - etat.changeCurrentPlayer(); - continue; - } + int scoren = 0; + int scoreb = 0; + + // ---------- Phase 1 ---------- + Etat etat = new Etat(); + Bot botNoir = new Bot(true, eval1, profondeur, utiliserElagageAB); + Bot botBlanc = new Bot(false, eval2, profondeur, utiliserElagageAB); + etat.setJoueurNoir(botNoir); + etat.setJoueurBlanc(botBlanc); + + int passes = 0; + while (passes < 2 && etat.getNbPion() < 64) { + botNoir.setEtat(etat); + botBlanc.setEtat(etat); + + if (etat.successeurs().isEmpty()) { + passes++; + etat.changeCurrentPlayer(); + System.out.println("un joueur passe"); + continue; + } - passes = 0; - System.out.println(etat); + passes = 0; + System.out.println(etat); + + Joueur courant = etat.getJoueurCourant(); + int x, y; + if (courant.estBot()) { + Bot b = (Bot) courant; + x = b.getCoupX(); + y = b.getCoupY(); + } else { + throw new IllegalStateException("Pas de JoueurHumain attendu"); + } - Joueur courant = etat.getJoueurCourant(); - botNoir.setEtat(etat); - botBlanc.setEtat(etat); + etat = etat.successeur(x, y); + } - int x, y; - if (courant.estBot()) { - Bot b = (Bot) courant; - x = b.getCoupX(); - y = b.getCoupY(); - } else { - throw new IllegalStateException("Pas de JoueurHumain attendu"); - } + System.out.println("Plateau final :"); + System.out.println(etat); - // On applique le coup (ajouterPion inverse déjà le joueur courant) - etat = etat.successeur(x, y); - } - Etat etatFinal = etat.copier(); - System.out.println("Plateau final :"); - System.out.println(etatFinal); - - int black = 0, white = 0; - for (Pion[] ligne : etatFinal.getTableau()) { - for (Pion p : ligne) { - if (p != null) { - if (p.isNoir()) black++; - else white++; - } + int black = 0, white = 0; + for (Pion[] ligne : etat.getTableau()) { + for (Pion p : ligne) { + if (p != null) { + if (p.isNoir()) black++; + else white++; } } - System.out.println("Fin de manche : " + black + " pions noirs, " + white + " pions blancs"); + } + System.out.println("Fin de manche : " + black + " pions noirs, " + white + " pions blancs"); - // mise à jour des scores - if (black > white) { - resultat += 1; - scoren += 1; - } - if (black < white) { - resultat -= 1; - scoreb += 1; - } - System.out.println("Score Actuel : Noir " + scoren + " - Blanc " + scoreb); + if (black > white) { + resultat += 1; + scoren += 1; + } else if (black < white) { + resultat -= 1; + scoreb += 1; } + System.out.println("Score Actuel : Noir " + scoren + " - Blanc " + scoreb); + // ---------- Phase 2 ---------- System.out.println("Changement de premier joueur"); + etat = new Etat(); + botNoir = new Bot(true, eval2, profondeur, utiliserElagageAB); + botBlanc = new Bot(false, eval1, profondeur, utiliserElagageAB); + etat.setJoueurNoir(botNoir); + etat.setJoueurBlanc(botBlanc); + + passes = 0; + while (passes < 2 && etat.getNbPion() < 64) { + botNoir.setEtat(etat); + botBlanc.setEtat(etat); + + if (etat.successeurs().isEmpty()) { + passes++; + etat.changeCurrentPlayer(); + continue; + } - // Phase 2 : eval2 commence (Noir = eval2, Blanc = eval1) - for (int i = 0; i < nbMatches; i++) { - Etat etat = new Etat(); - Bot botNoir = new Bot(true, eval2, profondeur, utiliserElagageAB); - Bot botBlanc = new Bot(false, eval1, profondeur, utiliserElagageAB); - etat.setJoueurNoir(botNoir); - etat.setJoueurBlanc(botBlanc); - - int passes = 0; - while (passes < 2 && etat.getNbPion() < 64) { - - // Aucun coup pour le joueur courant, il passe - if (etat.successeurs().isEmpty()) { - passes++; - etat.changeCurrentPlayer(); - continue; - } - System.out.println(etat); - - passes = 0; + passes = 0; + System.out.println(etat); + + Joueur courant = etat.getJoueurCourant(); + int x, y; + if (courant.estBot()) { + Bot b = (Bot) courant; + x = b.getCoupX(); + y = b.getCoupY(); + } else { + throw new IllegalStateException("Pas de JoueurHumain attendu"); + } - Joueur courant = etat.getJoueurCourant(); - botNoir.setEtat(etat); - botBlanc.setEtat(etat); + etat = etat.successeur(x, y); + } - int x, y; - if (courant.estBot()) { - Bot b = (Bot) courant; - x = b.getCoupX(); - y = b.getCoupY(); - } else { - throw new IllegalStateException("Pas de JoueurHumain attendu"); - } + System.out.println("Plateau final :"); + System.out.println(etat); - // On applique le coup (ajouterPion inverse déjà le joueur courant) - etat = etat.successeur(x, y); - } - Etat etatFinal = etat.copier(); - System.out.println("Plateau final :"); - System.out.println(etatFinal); - - // comptage - int black = 0, white = 0; - for (Pion[] ligne : etatFinal.getTableau()) { - for (Pion p : ligne) { - if (p != null) { - if (p.isNoir()) black++; - else white++; - } + black = 0; + white = 0; + for (Pion[] ligne : etat.getTableau()) { + for (Pion p : ligne) { + if (p != null) { + if (p.isNoir()) black++; + else white++; } } + } - System.out.println("Fin de manche : " + black + " pions noirs, " + white + " pions blancs"); - + System.out.println("Fin de manche : " + black + " pions noirs, " + white + " pions blancs"); - // mise à jour des scores (on inverse le signe car eval2 commençait) - if (black > white) { - resultat -= 1; - scoren += 1; - } - if (black < white) { - resultat += 1; - scoreb += 1; - } - System.out.println("Score Actuel : Noir " + scoren + " - Blanc " + scoreb); + if (black > white) { + resultat -= 1; + scoren += 1; + } else if (black < white) { + resultat += 1; + scoreb += 1; } + System.out.println("Score Actuel : Noir " + scoren + " - Blanc " + scoreb); - // C kiki le meilleur ? - long endTime = System.nanoTime(); // On arrete le chrono + // ---------- Résultat final ---------- + long endTime = System.nanoTime(); if (resultat > 0) { System.out.println("Eval " + eval1 + " est meilleur (résultat = " + resultat + ")."); } else if (resultat < 0) { @@ -173,9 +147,8 @@ public class ComparaisonEval { } else { System.out.println("Indécidable (égalité)."); } + System.out.println("Temps total de la comparaison : " + (endTime - startTime) / 1_000_000_000 + " s"); - } } - diff --git a/src/ComparaisonPasbien.java b/src/ComparaisonPasbien.java deleted file mode 100644 index d9c99d2b51ce86b7df68fa8182a8615f8a43b5e9..0000000000000000000000000000000000000000 --- a/src/ComparaisonPasbien.java +++ /dev/null @@ -1,64 +0,0 @@ -import java.util.Scanner; -import java.util.List; - -public class ComparaisonPasbien { - public static void main(String[] args) { - Scanner sc = new Scanner(System.in); - System.out.println("Deux eval puis profondeur (ex : 0 1 3) :"); - int eval1 = sc.nextInt(); - int eval2 = sc.nextInt(); - int profondeur = sc.nextInt(); - sc.close(); - - // Initialisation de l’état et des bots - Etat etat = new Etat(); - Bot botNoir = new Bot(true, eval1, profondeur); - Bot botBlanc = new Bot(false, eval2, profondeur); - etat.setJoueurNoir(botNoir); - etat.setJoueurBlanc(botBlanc); - // (le constructeur de Etat démarre toujours avec Noir) - - // Boucle de la partie : on s’arrête après deux passes consécutives - int passesConsecutives = 0; - while (passesConsecutives < 2) { - List<Etat> succ = etat.successeurs(); - if (succ.isEmpty()) { - // passe - passesConsecutives++; - etat.changeCurrentPlayer(); - } else { - // coup joué - passesConsecutives = 0; - Bot actif = (Bot) etat.getJoueurCourant(); - actif.setEtat(etat); - int x = actif.getCoupX(); - int y = actif.getCoupY(); - etat = etat.successeur(x, y); - } - System.out.println(etat); - } - - // Comptage final des pions - int black = 0, white = 0; - for (Pion[] ligne : etat.getTableau()) { - for (Pion p : ligne) { - if (p != null) { - if (p.isNoir()) black++; - else white++; - } - } - } - - // Affichage du résultat - System.out.println("=== Résultat final ==="); - System.out.println("Noir : " + black); - System.out.println("Blanc : " + white); - if (black > white) { - System.out.println("Gagnant : Noir (éval " + eval1 + ")"); - } else if (white > black) { - System.out.println("Gagnant : Blanc (éval " + eval2 + ")"); - } else { - System.out.println("Match nul"); - } - } -} diff --git a/src/Etat.java b/src/Etat.java index 34c8e8105d03003c49e0f720f408dfaf504eaff2..7ac049d4e4693cf215d30c2f15fc72194ee162dd 100644 --- a/src/Etat.java +++ b/src/Etat.java @@ -368,6 +368,7 @@ public class Etat { etat.joueurCourantEstNoir = this.joueurCourantEstNoir; etat.jNoir = this.jNoir; etat.jBlanc = this.jBlanc; + return etat; } @@ -388,30 +389,6 @@ public class Etat { return nbPion; } - public Etat copier() { - Etat copie = new Etat(); - - // Copier le tableau de pions - Pion[][] nouveauTab = new Pion[8][8]; - for (int i = 0; i < 8; i++) { - for (int j = 0; j < 8; j++) { - if (this.tableau[i][j] != null) { - nouveauTab[i][j] = new Pion(this.tableau[i][j]); - } - } - } - copie.tableau = nouveauTab; - - // Copier tous les champs nécessaires - copie.nbPion = this.nbPion; - copie.estEchec = this.estEchec; - copie.joueurCourantEstNoir = this.joueurCourantEstNoir; - copie.jNoir = this.jNoir; - copie.jBlanc = this.jBlanc; - copie.currentIA = this.currentIA; - - return copie; - } } \ No newline at end of file diff --git a/src/Pion.java b/src/Pion.java index d7aab3af6d4edd9ee73bd2107acd4ef5ae3474ac..062fa933a9b53e807fb3928e5511b0b021bdb8c5 100644 --- a/src/Pion.java +++ b/src/Pion.java @@ -48,4 +48,6 @@ public class Pion { return posy; } + + }