L'algorithme GOZIQI AI est également un algorithme de jeu AI typique. Certains algorithmes d'échecs AI peuvent être utilisés comme référence. Ce qui suit est le code d'implémentation Java.
Interface abstraite d'échecs
Importer java.util.list; Interface publique IChessboard {// Obtenez la coordonnée horizontale maximale de la carte publique int getMaxx (); // coordonnée verticale maximale publique int getMaxy (); // obtient tous les points vierges actuels, et ces points ne peuvent jouer que des échecs publique <point> getFreEpoint (); }Implémentation de classe d'échecs
// Le point de classe d'échecs {// c'est la performance, définie sur public int x; public int y; public int getX () {return x; } public Point setx (int x) {this.x = x; retourner ceci; } public int gety () {return y; } public Point Sety (int y) {this.y = y; retourner ceci; } public Point (int x, int y) {this.x = x; this.y = y; } @Override public int hashcode () {return x + y; } @Override public boolean equals (objet obj) {if (this == obj) return true; Point autre = (point) obj; if (x! = autre.x) return false; if (y! = Autre.y) renvoie false; Retour Vrai; }} Interface abstraite des joueurs
Importer java.util.list; Interface publique iPlayer {// L'étape suivante consiste à passer l'ensemble d'échecs que l'adversaire a déjà défini public Void Run (liste <point> ennemis, point Point); Booléen public Haswin (); Public Void SetChessboard (Ichessboard Chessboard); Liste publique <point> getMyPoint (); } Classe abstraite de base du joueur
import java.util.arraylist; Importer java.util.list; Public Abstract Class BasePlayer implémente iPlayer {// La pièce d'échecs que j'ai placée à la liste protégée <point> MyPoints = new ArrayList <point> (200); // Le tableau d'échecs a protégé les échecs ichess; // Les coordonnées horizontales et verticales maximales de la carte sont protégées int maxx; protégé int maxy; // Tous les pièces d'échecs vierges Liste protégé <point> allFreepoint; @Override public Final List <point> getMyPOINTS () {return MyPoints; } @Override public void SetChessboard (ichessboard Chessboard) {this.chessboard = échecboard; allFreEpoint = Chessboard.getFreEpoint (); maxx = Chessboard.getMaxx (); maxy = échecboard.getMaxy (); myPoint.Clear (); } Point final privé Temp = nouveau point (0, 0); // est-ce que je gagne publique final booléen haswin () {if (mypoint.size () <5) {return false; } Point Point = myPoint.get (myPoint.size () - 1); int count = 1; int x = point.getx (), y = point.gety (); // horizontal- temp.setx (x) .sety (y); while (myPoint.Contains (temp.setx (temp.getx () - 1)) && temp.getx ()> = 0 && count <5) {count ++; } if (count> = 5) {return true; } temp.setx (x) .sety (y); while (myPoint.Contains (temp.setx (temp.getx () - 1)) && temp.getx ()> = 0 && count <5) {count ++; } if (count> = 5) {return true; } temp.setx (x) .sety (y); while (myPoint.Contains (temp.setx (temp.getx () + 1)) && temp.getx () <maxx && count <5) {count ++; } if (count> = 5) {return true; } // perpendiculaire | Count = 1; temp.setx (x) .sety (y); while (myPoint.Contains (temp.sety (temp.gety () - 1)) && temp.gety ()> = 0) {count ++; } if (count> = 5) {return true; } temp.setx (x) .sety (y); while (myPoint.Contains (temp.sety (temp.gety () - 1)) && temp.gety ()> = 0) {count ++; } if (count> = 5) {return true; } temp.setx (x) .sety (y); while (myPoint.Contains (temp.sety (temp.gety () + 1)) && temp.gety () <maxy && count <5) {count ++; } if (count> = 5) {return true; } // Forward oblique / count = 1; temp.setx (x) .sety (y); while (myPoint.Contains (temp.setx (temp.getx () - 1) .sety (temp.gety () + 1)) && temp.getx ()> = 0 && temp.gety () <maxy) {count ++; } if (count> = 5) {return true; } temp.setx (x) .sety (y); while (myPoint.Contains (temp.setx (temp.getx () + 1) .sety (temp.gety () - 1)) && temp.getx () <maxx && temp.gety ()> = 0 && count <6) {count ++; } if (count> = 5) {return true; } // backslash / count = 1; temp.setx (x) .sety (y); while (myPoint.Contains (temp.setx (temp.getx () - 1) .sety (temp.gety () - 1)) && temp.getx ()> = 0 && temp.gety ()> = 0) {count ++; } if (count> = 5) {return true; } temp.setx (x) .sety (y); while (myPoint.Contains (temp.setx (temp.getx () + 1) .sety (temp.gety () + 1)) && temp.getx () <maxx && temp.gety () <maxy && count <5) {count ++; } if (count> = 5) {return true; } return false; }} Implémentation de l'IA informatique
import java.util.arraylist; Importer java.util.collections; import java.util.hashmap; Importer java.util.list; importation java.util.map; // La classe principale de l'algorithme, l'idée principale de l'algorithme est divisée en trois étapes. // La première étape: assumez cycliquement le score pour soi-même et l'autre partie (pour faire un score dans une certaine gamme) en fonction de la situation actuelle des deux parties, et juger des changements dans la situation que cette pièce peut apporter, par exemple s'il peut se précipiter 4, qu'il puisse former notre double ou ennemi, etc. (Je l'appelle à moitié en direct 4), etc.), y compris l'ennemi et notre côté. // Étape 3: Triez le résultat précédent en fonction des règles fournies par l'utilisateur et sélectionnez des formes sous-sujet et défensives (il existe des règles pour les formes offensives et défensives) classe publique BasecomputeRerai étend BasPlayer {// quatre directions, horizontal -, vertical | , Forward-Slant /, Back-Slant / Private Static Final int Heng = 0; finale statique privée int zhong = 1; final statique privé int zheng_xie = 2; Final statique privé int fan_xie = 3; // d'avant en arrière avant privé final booléen final = true; Boolean final statique privé vers l'arrière = false; // Affichez le résultat de l'analyse. Que le point actuel soit un pass à deux fins (vivant) ou seulement une passe à une fin (Half_alive), le processus d'analyse des pièces d'échecs bloqué est automatiquement bloqué, et non comme une pièce d'échecs pour être sélectionné privé static final int vif = 1; Final statique privé int half_alive = 0; // Final statique privé Int mort = -1; // Calculer la plage, trop grande plage aura des problèmes de performances classe privée calcuterange {int xstart, ystart, xstop, ystop; Calcuterange privé (int xstart, int ystart, int xstop, int ystop) {this.xstart = xstart; this.ystart = ystart; this.xstop = xstop; this.ystop = ystop; }} // Limiter la plage de calcul de l'ordinateur. Si l'ensemble des performances de calcul de la carte d'échecs est trop médiocre, il est actuellement formé sur la base de la valeur limite de toutes les pièces d'échecs qui ont été utilisées. Il s'agit actuellement de 1 INT Final statique privé_step = 1; Calcuterange CurrentRange = nouveau Calcuterange (0, 0, 0, 0); Private void initRange (list <point> Couts, list <point> humains) {currentRange.xstart = humans.get (0) .getx () - range_step; currentRange.ystart = humans.get (0) .gety () - range_step; currentRange.xstop = humans.get (0) .getx () + range_step; currentRange.ystop = humans.get (0) .gety () + range_step; pour (point de point: humains) {if (point.getx () - range_step <currentRange.xStart) {currentRange.xstart = point.getx () - range_step; } else if (point.getx () + range_step> currentRange.xstop) {currentRange.xstop = point.getx () + range_step; } if (point.gety () - range_step <currentRange.ystart) {currentRange.ystart = Point.gety () - range_step; } else if (point.gety () + range_step> currentRange.ystop) {currentRange.ystop = Point.gety () + range_step; }} pour (point de point: COUTERS) {if (Point.getX () - range_step <currentRange.xStart) {currentRange.xStart = Point.getx () - range_step; } else if (point.getx () + range_step> currentRange.xstop) {currentRange.xstop = point.getx () + range_step; } if (point.gety () - range_step <currentRange.ystart) {currentRange.ystart = Point.gety () - range_step; } else if (point.gety () + range_step> currentRange.ystop) {currentRange.ystop = Point.gety () + range_step; }} // Si la plage est étendue et dépasse l'échecteur, il est égal à l'échiquier currentRange.xstart = currentRange.xstart <0? 0: currentRange.xStart; currentRange.ystart = currentRange.ystart <0? 0: currentRange.ystart; currentRange.ystart = currentRange.ystart <0? 0: currentRange.ystart; currentRange.xstop = currentRange.xstop> = maxx? maxx-1: currentRange.xstop; currentRange.ystop = currentRange.ystop> = maxy? maxy-1: currentRange.ystop; } // Analyser la forme actuelle de la méthode d'entrée. L'analyse est divisée en trois étapes au total. La troisième étape peut être contrôlée par des sous-classes pour difficulté. Point Point Doanalysis (List <point> Couts, List <point> Humans) {if (Humans.Size () == 1) {// La première étape renvoie GetFirstpoint (humains); } // Initialisez la plage de calcul InitRange (Comuters, humains); // effacer les résultats précédents initanalysisResults (); // Démarrer l'analyse, scanner tous les points vides et former le premier point de résultat d'analyse BestPoint = Dofirstanalysis (Comuters, humains); if (bestpoint! = null) {//system.out.println(" cette pièce est la plus importante, vous ne pouvez jouer de cette pièce que "); retourner le meilleur point; } // Analyser le premier résultat et trouver votre meilleur point meilleur point = docomputersencondanalysis (ordinateurFirStResults, ordinateur EncodResults); if (bestpoint! = null) {//system.out.println("I'm sur le point de gagner, je jouerai cette pièce "); retourner le meilleur point; } ComputerFirStresults.Clear (); System.gc (); // Analyser le premier résultat et trouver le meilleur point du meilleur point ennemi = Dohumansencondanalysis (HumanFirstresults, HumansencodResults); if (bestpoint! = null) {//system.out.println(" si vous ne jouez pas cette pièce, vous perdrez "); retourner le meilleur point; } HumanFirstresults.Clear (); System.gc (); // Aucun point de mise à mort final n'a été trouvé, l'analyse du troisième résultat a renvoyé Dothirdanalysis (); } // La première étape de la pièce d'échecs ne nécessite pas de calculs compliqués, et il est terminé en fonction de la valeur X de la première étape humaine de la pièce d'échecs. Private Point getFirstPoint (list <point> humains) {Point Point = Humans.get (0); if (Point.getX () == 0 || Point.gety () == 0 || Point.getx () == Maxx && point.gety () == Maxy) renvoie le nouveau point (maxx / 2, maxy / 2); else {return new Point (point.getx () - 1, Point.gety ()); }} // private int debugx, debugy; // Utiliser pour Debug // Démarrer l'analyse, scanner tous les points vierges et former le premier résultat d'analyse DoFirstanalysis (List <point> Couts, List <point> humains) {int size = allFreePoint.Size (); Point ComputerPoint = null; Point HumanPoint = null; int x, y; FirstanalysisResult Firstanalysis Result; pour (int i = 0; i <size; i ++) {ComputerPoint = allfreepoint.get (i); // Cliquez d'abord les coordonnées x et y, car l'objet d'origine sera modifié pendant le processus d'analyse x = ComputerPoint.getX (); y = ordinateur.gety (); if (x <currentRange.xstart || x> currentRange.xstop || y <currentRange.ystart || y> currentRange.ystop) {continuant; } // if (x == debugx && y == debugy) {// system.out.println ("SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSIG System.out.println ("SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS = TryandCountreSult (Comutters, humains, ordinateur, Heng); ComputerPoint.setx (x) .sety (y); // Répondez la valeur d'origine du point pour la prochaine analyse if (FirstanalysisResult! = null) {// Pas de résultat, il est impossible d'atteindre cinq pièces d'échecs dans cette direction. Si (FirstanalysisResult.Count == 5) // égal à 5 signifie que vous pouvez jouer des pièces d'échecs à ce stade et que vous pouvez vous connecter à 5. Si vous gagnez, vous ne l'analyserez pas. Return ComputerPoint; // enregistrer le premier résultat d'analyse addtofirstanalysisResult (FirstanalysyResult, ComputerFirstrestresults); } // Répétez les étapes ci-dessus dans la "direction verticale" FirstanalysisResult = TryandCountreSult (COMUTERS, HUMANS, ordinateur, zhong); ComputerPoint.setx (x) .sety (y); if (FirstanalysisResult! = null) {// Die les échecs, ne joue pas si (FirstanalysisResult.Count == 5) return ComputerPoint; AddtoFirstanalysisResult (Firstanalysis Result, ComputerFirstresults); } // Forward Oblique FirstanalysisResult = TryandCountreSult (Comuters, humains, ordinateur, zheng_xie); ComputerPoint.setx (x) .sety (y); if (FirstAnalysisResult! = null) {// Dead Chess, ne jouez pas si (FirstanalysisResult.Count == 5) return ComputerPoint; AddtoFirstanalysisResult (Firstanalysis Result, ComputerFirstresults); } // Backside FirstAnalysisResult = tryandCountreSult (Comuters, humains, ordinateur, fan_xie); ComputerPoint.setx (x) .sety (y); if (FirstAnalysisResult! = null) {// Dead Chess, ne jouez pas si (FirstanalysisResult.Count == 5) return ComputerPoint; AddtoFirstanalysisResult (Firstanalysis Result, ComputerFirstresults); } // Analyser l'état de cette pièce dans l'ennemi dans la direction "horizontale", comme le live 3, semi-vie 4, etc. FirstanalysisResult = TryandCountreult (humains, Comuters, ordinateur, Heng); ComputerPoint.setx (x) .sety (y); if (FirstanalysisResult! = null) {// Die Chess, ne jouez pas si (FirstanalysisResult.Count == 5) HumanPoint = ComputerPoint; AddtoFirstanalysisResult (Firstanalysis Result, HumanFirstresults); } // "Long-perpendiculaire" FirstanalysisResult = TryandCountreSult (humains, Comutters, ordinateur, zhong); ComputerPoint.setx (x) .sety (y); if (FirstanalysisResult! = null) {// Die Chess, ne joue pas si (FirstanalysisResult.Count == 5) HumanPoint = ComputerPoint; AddtoFirstanalysisResult (Firstanalysis Result, HumanFirstresults); } // "Forward-Slant" FirstanalysisResult = TryandCountreSult (Humans, Comuters, Computerpoint, Zheng_xie); ComputerPoint.setx (x) .sety (y); if (FirstanalysisResult! = null) {// Die Chess, ne joue pas si (FirstanalysisResult.Count == 5) HumanPoint = ComputerPoint; AddtoFirstanalysisResult (Firstanalysis Result, HumanFirstresults); } // "BackSlash" FirstanalysisResult = TryandCountreSult (Humains, Comuters, Computerpoint, fan_xie); ComputerPoint.setx (x) .sety (y); if (FirstanalysisResult! = null) {// Die Chess, ne joue pas si (FirstanalysisResult.Count == 5) HumanPoint = ComputerPoint; AddtoFirstanalysisResult (Firstanalysis Result, HumanFirstresults); }} // S'il n'y a pas de pièce gagnante, la première analyse n'a pas besoin de retourner le résultat de la première analyse; } // La deuxième analyse, analyse le résultat de la première formation, le premier résultat d'analyse générera jusqu'à quatre objets Firstanalysis Result (quatre ennemis et les uns les autres). // Les quatre objets doivent être combinés dans un objet SencondanalysisResult, privé DoComputersEnCondanalysis (MAP <Point, List <FirstanalysisResult>> Firstresults, List <SencondanalysisResult> Sencodersults) {list <premierAnalysyResult> List = NULL; SencondanalysisResult Sr = null; pour (point p: firstresults.Keyset ()) {sr = new sencondanalysisResult (p); list = firstresults.get (p); pour (FirstAnalysis Result: List) {if (result.count == 4) {if (result.alivestate == via) {// Après le filtrage précédent, les deux parties ont exclu la mise à mort ultime. S'il y a 4, passez cette étape et gagnez la prochaine étape. Result.point; // S'il y a un meurtre final, le premier tour est revenu. Dans cette manche de 4, c'est déjà une bonne pièce, retournez directement et ne l'analyse plus} else {sr.halfalive4 ++; Computer4Halfalives.Add (SR); }} else if (result.count == 3) {if (result.aliveState == Alive) {sr.alive3 ++; if (sr.alive3 == 1) {Computer3alives.add (sr); } else {ComputerDouble3alives.add (sr); }} else {sr.halfalive3 ++; Computer3Halfalives.Add (SR); }} else {// semi-live 2 a été exclu dans la première étape et n'est plus traité sr.alive2 ++; if (sr.alive2 == 1) {ordinateur2alives.add (sr); } else {ComputerDouble2alives.add (sr); }}}} sencodResults.add (sr); } // Aucun live 4 n'a été trouvé; retourner null; } // Cette méthode est fondamentalement la même que celle ci-dessus, mais pour les performances, c'est moins le jugement, sépare les humains et les ordinateurs Point Point Dohumansencondanalysis (Map <Point, List <FirstanalysisResult>> FirstResult, List <SencondanalysisResult> SencodeRresults) {List <FirstanalysyResult> List = Null; SencondanalysisResult Sr = null; pour (point p: firstresults.Keyset ()) {sr = new sencondanalysisResult (p); list = firstresults.get (p); for (FirstanalysisResult Result: list) {if (result.count == 4) {if (result.aliveState == via) {human4alives.add (sr); } else {sr.halfalive4 ++; Human4Halfalives.add (SR); }} else if (result.count == 3) {if (result.aliveState == Alive) {sr.alive3 ++; if (sr.alive3 == 1) {human3alives.add (sr); } else {Humandouble3alives.add (sr); }} else {sr.halfalive3 ++; Human3Halfalives.add (SR); }} else {sr.alive2 ++; if (sr.alive2 == 1) {human2alives.add (sr); } else {Humandouble2alives.add (sr); }}} sencodsults.add (sr); } // Aucun live 4 n'a été trouvé Retour null; } private void sleep (int miseCond) {try {thread.sleep (miniseConde); } Catch (InterruptedException E) {}} // La troisième analyse, aucune des parties ne peut créer un live 4, trouver Double Live 3 Pieces, sinon, trouver Half Live 4, sinon, trouver un seul live 3, Double Live 2 Private Point Dothirdanalysis () {if (! Computer4Halfalives.IsempTy ()) {retour Computer4Halfalives.get (0). } System.gc (); sommeil (300); Collection.Sort (ordinateur EncodResults); System.gc (); // Je suis sur le point de vivre 4, et je n'ai pas à moitié vivant 4 ou plus, donc je ne peux que bloquer Point Mostbest = GetBestPoint (Human4alives, ordinateur EncodResults); if (le plusBest! = null) Renvoie le plus; Collection.Sort (HumansencodResults); System.gc (); mostBest = getBestPoint (); if (le plusBest! = null) Renvoie le plus; // retirez les premiers, et celui qui est meilleur renverra ordinateurencodsults.get (0) .point; } // sous-classe implémente cette méthode et modifie son ordre pour atteindre le point protégé ou attaquer le point protégé GetBestPoint () {// je suis sur le point de vivre 4, et je n'ai pas à moitié vivant 4 ou plus, donc je ne peux pas bloquer le point le plusable = GetBestPoint (ComputerDouble3Alives, HumansEncoDReSult); if (le plusBest! = null) Renvoie le plus; MostBest = GetBestPoint (Computer3Alives, HumansencoDResults); if (le plusBest! = null) Renvoie le plus; MostBest = GetBestPoint (Humandouble3alives, ordinateurCcoDeSults); if (le plusBest! = null) Renvoie le plus; MostBest = GetBestPoint (Human3alives, ordinateur EncodResults); if (le plusBest! = null) Renvoie le plus; MostBest = GetBestPoint (ComputerDouble2Alives, HumansencodResults); if (le plusBest! = null) Renvoie le plus; MostBest = GetBestPoint (ordinateur2alives, humansencodsults); if (le plusBest! = null) Renvoie le plus; MostBest = GetBestPoint (Computer3Halfalives, HumansencoDResults); if (le plusBest! = null) Renvoie le plus; MostBest = GetBestPoint (Human4Halfalives, ordinateur EncodResults); if (le plusBest! = null) Renvoie le plus; MostBest = GetBestpoint (Humandouble2alives, ordinateur EncodResults); if (le plusBest! = null) Renvoie le plus; MostBest = GetBestPoint (Human2Alives, ordinateurCodResults); if (le plusBest! = null) Renvoie le plus; MostBest = GetBestPoint (Human3Halfalives, ordinateur EncodResults); retourner le plus; } // La dernière étape de la troisième analyse, le deuxième résultat a été trié, ici vous pouvez sélectionner la meilleure pièce d'échec vOTSEncoDResults) {if (myBest.Contains (your)) {return your.point; }} return mybest.get (0) .point; } else {return mybest.get (0) .point; }} return null; } // La première analyse Résultat de la carte finale privée <Point, Liste <FirstanalysisResult>> ComputerFirSults = new Hashmap <Point, List <FirsanalysisResult >> (); Carte finale privée <Point, liste <InferAnalysisResult >> HumanFirSults = new Hashmap <Point, List <FirstanalysisResult >> (); // la deuxième liste finale de résultats totaux protégé <sencondanalysisResult> ComputersencoDResults = new ArrayList <SencondanalysisResult> (); Liste finale protégée <sencondanalysisResult> HumansencoDResults = new ArrayList <SencondanalysisResult> (); Liste finale protégé <sencondanalysisResult> (); // Le deuxième résultat est que la liste finale protégé par ordinateur <sencondanalysisResult> Computer4Halfalives = new ArrayList <SencondanalysisResult> (2); Liste finale protégé <sencondanalysisResult> ComputerDouble3alives = new ArrayList <SencondanalysisResult> (4); Liste finale protégée <sencondanalysisResult> Computer3alives = new ArrayList <SencondanalysisResult> (5); Liste finale protégée <sencondanalysisResult> Computer3alives = new ArrayList <SencondanalysisResult> (5); Liste finale protégée <sencondanalysisResult> ComputerDouble2Alives = new ArrayList <SencondanalysisResult> (); Liste finale protégé <sencondanalysisResult> Computer2Alives = new ArrayList <SencondanalysisResult> (); Liste finale protégée <sencondanalysisResult> Computer3Halfalives = new ArrayList <SencondanalysisResult> (); // Le deuxième résultat est, la liste finale protégé par l'homme <sencondanalysisResult> Human4alives = new ArrayList <SencondanalysisResult> (2); Liste finale protégé <sencondanalysisResult> Human4Halfalives = new ArrayList <SencondanalysisResult> (5); Liste finale protégé <sencondanalysisResult> Humandouble3alives = new ArrayList <SencondanalysisResult> (2); Liste finale protégé <sencondanalysisResult> Human3alives = new ArrayList <SencondanalysisResult> (10); Liste finale protégée <sencondanalysisResult> Humandouble2alives = new ArrayList <SencondanalysisResult> (3); Liste finale protégée <sencondanalysisResult> Human2Alives = new ArrayList <SencondanalysisResult> (); Liste finale protégé <sencondanalysisResult> Human3Halfalives = new ArrayList <SencondanalysisResult> (); // L'analyse Résultats de la compensation de la pièce précédente avant la première analyse Private Void InitanalysisResults () {ComputerFirStresults.Clear (); HumanFirstresults.Clear (); // le deuxième résultat total ComputerSencoDResults.Clear (); humansencodersults.clear (); // le deuxième résultat Computer4Halfalives.Clear (); ComputerDouble3alives.Clear (); Computer3Alives.Clear (); ComputerDouble2alives.Clear (); Computer2Alives.Clear (); Computer3Halfalives.Clear (); Computer3Alives.Clear (); ComputerDouble2alives.Clear (); Computer2Alives.Clear (); Computer3Halfalives.Clear (); // Le deuxième résultat est Human4alives.Clear (); Human4Halfalives.Clear (); Humandouble3alives.Clear (); Human3alives.Clear (); Humandouble2alives.Clear (); Human2Alives.Clear (); Human3Halfalives.Clear (); System.gc (); } // Ajouter à la première analyse Résultat privé void addtoFirstanalysyResult (premierAnalysisResult Result, map <Point, list <FirstanalysisResult>> dest) {if (dest.containsKey (result.point)) {dest.get (result.point) .add (résultat); } else {list <firstanalysisResult> list = new ArrayList <FirstanalysisResult> (1); list.add (résultat); dest.put (result.point, liste); }} // Classe de résultats de première analyse Première classe privative FirstanalysisResult {// Count continu; // point de point de point; // Direction de Direction; // État int alivestate; private FirstanalysisResult (int, point de point, direction int) {this (compter, point, direction, vivant); } private FirstAnalysisResult (int, point de point, direction int, int alivestate) {this.count = count; this.point = point; this.direction = direction; this.alivestate = alivestate; } private FirstanalysisResult init (point de point, direction int, int alivestate) {this.count = 1; this.point = point; this.direction = direction; this.alivestate = alivestate; retourner ceci; } private FirstanalysisResult Cloneme () {return new FirstanalysyResult (comte, point, direction, alivestate); }} // SecondAnalysisResult implémente comparable <sencondanalysisResult> {int vivant4 = 0; // vivant 3 int anive3 = 0; // secondLiving 4, une extrémité du sceau int halfalive4 = 0; // SecondLiving 3, une extrémité du sceau int halfalive3 = 0; // vivant 2 quantité int anive2 = 0; // point de point; @Override public int hashcode () {final int prime = 31; Int résultat = 1; result = prime * result + ((point == null)? 0: point.hashcode ()); Résultat de retour; } @Override public booléen equals (objet obj) {sencondanalysisResult other = (sencondanalysisResult) obj; if (point == null) {if (autre.point! = null) return false; } else if (! Point.equals (autre.point)) renvoie false; Retour Vrai; } private sencondanalysisResult (point de point) {this.point = point; } // Au cours de la troisième analyse, les résultats de la deuxième analyse sont triés. Ceci est la fonction de rappel de tri @Override public int compareto (sencondanalysisResult un autre) {return comparetowResult (this, un autre); }} // Si le retour -1 est le premier paramètre, 1 est le deuxième paramètre est le premier, et 0 est le private int int dans l'ordre d'origine CompareTowResult (SencondanalysisResult OneResult, SencondanalysisResult un autre) {if (oneresult.alive4> Another.alive4) {return -1; } if (oneResult.alive4 <Another.alive4) {return 1; } if (oneResult.alive4> un autre.alive4) {return -1; } if (oneResult.alive3> un autre.alive3) {return -1; } if (oneResult.alive3 <Another.alive3) {return 1; } if (oneResult.alive2> un autre.alive2) {return -1; } if (oneResult.alive2 <autre.alive2) {return 1; } if (oneResult.alive3> un autre.alive3) {return -1; } if (oneResult.alive3> un autre.alive3) {return 1; } return 0; } // Un objet temporaire est utilisé pour stocker temporairement les résultats de l'analyse lors de la première analyse. S'il y a plus de 1 (excluant) des résultats, la méthode du clonème est appelée pour obtenir le résultat. Sinon, ce résultat sera rejeté private final FirstanalysisResult Far = new FirstanalysyResult (1, null, heng); // Analyse Si le sous-marin est à côté de la position actuelle, combien de sous-marins seront formés dans une certaine direction. Paramètres: Tous les points qui ont été placés du côté actuel, le point qui doit être supposé, la direction qui doit être jugée privée private FirstanalysisResult TryandCountreult (list <point> mypoints, list <point> enegyPoints, point Point, intwere) {int x = point.getx (); int y = point.gety (); FirstanalysisResult FR = NULL; int maxCountonThisDirection = maxCountonThisDirection (point, ennemis, direction, 1); if (maxCountonThisDirection <5) {// pièce d'échecs insensée renvoie null; // il y a moins de cinq espaces vides dans cette direction, et la pièce d'échecs que vous avez déjà définie est exclue} else if (maxCountonThisDirection == 5) {// l'état de demi-lead); } else {// Les deux extrémités sont fr = far.init (point, direction, vivant); } // Calculer CountPoint (Mypoints, EnemyPOINTS, Point.setx (x) .sety (y), fr, Direction, Forward); CountPoint (MyPoint, EnemyPOINTS, Point.setx (x) .sety (y), fr, direction, arrière); if (Fr.Count <= 1 || (fr.Count == 2 && fr.aliveState == Half_alive)) {// realve1, semi-active2 et les résultats suivants, Abandon Retour null; } // retourne le résultat de la copie de retour fr.cloneme (); } // La pièce d'échecs sort du mur privé booléen estoutsideofwall (point de point, direction int) {if (direction == Heng) {return point.getx () <0 || Point.getX ()> = maxx; // Les valeurs x et y maximales sont à l'extérieur du mur, alors utilisez le signe égal} else if (direction == zhong) {return point.gety () <0 || Point.gety ()> = maxy; } else {// il peut y avoir un problème ici return point.getx () <0 || Point.gety () <0 || Point.gety () <0 || Point.gety () <0 || Point.gety () <0 || Point.getx ()> = maxx || Point.gety ()> = maxy; }} Private Point PointTonext (point de point, direction int, booléen avant) {switch (direction) {case Heng: if (Forward) Point.x ++; else Point.x--; casser; cas zhong: if (avant) point.y ++; else Point.y--; casser; Case zheng_xie: if (en avant) {point.x ++; point.y--; } else {Point.x--; Point.y ++; } casser; case fan_xie: if (en avant) {point.x ++; Point.y ++; } else {Point.x--; point.y--; } casser; } point de retour; } // Combien de pièces peuvent être jouées dans une certaine direction (l'une des huit). Cette méthode est la méthode principale dans la première analyse Private Void CountPoint (List <point> MyPoints, List <point> EnemyPOINTS, Point Point, FirstanalysisResult FR, INT Direction, Boolean Forward) {if (MyPoint.Contains (PointTonext (Point, Direction, Forward))) {Fr.Count ++; if (myPoint.Contains (PointTonext (point, direction, avant))) {fr.Count ++; if (myPoint.Contains (PointTonext (point, direction, avant))) {fr.Count ++; if (myPoint.Contains (PointTonext (point, direction, avant))) {fr.Count ++; } else if (ennessyPoint.Contains (point) || Isoutsideofwall (point, direction)) {fr.aliveState = half_alive; }} else if (ennessyPoint.contains (point) || Isoutsideofwall (point, direction)) {fr.aliveState = half_alive; }} else if (ennessyPoint.contains (point, direction)) {fr.alivestate = half_alive; }} else if (ennessyPoint.contains (point) || Isoutsideofwall (point, direction)) {fr.aliveState = half_alive; }} else if (ennessyPoint.contains (point) || Isoutsideofwall (point, direction)) {fr.aliveState = half_alive; }} // pouvez-vous toujours obtenir cinq pièces dans une certaine direction privée int maxCountonThisDirection (point de point, liste <point> enness, int, int count) {int x = point.getx (), y = point.gety (); switch (direction) {// Horizontal Case Heng: while (! EnepyPoint.Contains (Point.setx (Point.getX () - 1)) && point.getx ()> = 0 && count <6) {count ++; } point.setx (x); while (! EnepyPoint.Contains (Point.setx (point.getx () + 1)) && point.getx () <maxx && count <6) {count ++; } casser; // Case perpendiculaire zhong: while (! EnepyPoint.Contains (Point.sety (Point.gety () - 1)) && point.gety ()> = 0) {count ++; } point.sety (y); while (! EnepyPoint.Contains (Point.Sety (Point.gety () + 1)) && point.gety () <maxy && count <6) {count ++; } casser; // Forward Oblique / Case zheng_xie: while (! EnepyPoint.Contains (Point.setx (Point.getX () - 1) .Sety (Point.gety () + 1)) && point.getx ()> = 0 && point.gety () <maxy) {count ++; } point.setx (x) .sety (y); while (! EnepyPoint.Contains (Point.setx (Point.getX () + 1) .Sety (Point.gety () - 1)) && point.getX () <maxx && point.gety ()> = 0 && count <6) {count ++; } casser; // backslash / case fan_xie: while (! EnepyPoint.Contains (Point.setx (Point.getX () - 1) .Sety (Point.gety () - 1)) && point.getx ()> = 0 && point.gety ()> = 0) {count ++; } point.setx (x) .sety (y); while (! EnepyPoint.Contains (Point.setx (Point.getX () + 1) .Sety (Point.gety () + 1)) && point.getx () <maxx && point.gety () <maxy && count <6) {count ++; } casser; } Return Count; } // Joue des pièces d'échecs, interface externe @Override public void run (list <point> humains, point p) {// supprimer la dernière étape de l'être humain allfreepoint.remove (humains.get (humains.size () - 1)); // une étape de l'ordinateur peut rendre le résultat ponctuel = doanalyse (mes points, humains); // Retirez les pièces d'échecs sur l'ordinateur allfreepoint.remove (résultat); // Ajouter aux pièces d'échecs de l'ordinateur et jouer MyPoint.Add (résultat); }} Il est très facile de mettre en œuvre des acteurs humains
Importer java.util.list; La classe publique HumanPlayer étend BasePlayer {@Override public void run (list <point> enevyPoint, point p) {getMyPoint (). add (p); allfreepoint.remove (p); }}Résumé: Bien qu'il soit écrit en Java, l'algorithme a été résumé et peut être facilement modifié en implémentations de diverses plateformes.
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.