El algoritmo de AI de Goziqi también es un algoritmo típico de AI de juego. Algunos algoritmos de AI de ajedrez se pueden usar como referencia. El siguiente es el código de implementación de Java.
Interfaz abstracto de tablero de ajedrez
import java.util.list; interfaz pública ichessboard {// Obtenga la coordenada horizontal máxima de la Junta public int getMaxx (); // coordenada vertical máxima pública int getmaxy (); // Obtenga todos los puntos en blanco actuales, y estos puntos solo pueden jugar a la lista pública de ajedrez <point> getFreePoints (); }Implementación de la clase de ajedrez
// El punto de clase de ajedrez {// Esta es la actuación, establecida en public int x; público int y; public int getx () {return x; } public Point SetX (int x) {this.x = x; devolver esto; } public int gety () {return y; } public Point Sety (int y) {this.y = y; devolver esto; } Public Point (int x, int y) {this.x = x; this.y = y; } @Override public int hashcode () {return x + y; } @Override public boolean iguales (objeto obj) {if (this == obj) return true; Punto otro = (punto) obj; if (x! = other.x) return false; if (y! = other.y) return false; devolver verdadero; }} Interfaz abstracta del jugador
import java.util.list; Public Interface iPlayer {// El siguiente paso es pasar el conjunto de tablero de ajedrez que el oponente ya ha establecido public void run (list <foint> enemyPoints, punto de punto); Public Boolean Haswin (); Public void setchessboard (tablero de ajedrez IChessboard); Lista pública <Point> getMyPoints (); } Jugador clase de abstracto básico
import java.util.arrayList; import java.util.list; Public Abstract Class BasePlayer implementa iPlayer {// La pieza de ajedrez he colocado la lista protegida <Point> myPoints = new ArrayList <Point> (200); // El tablero de ajedrez protegió el tablero de ajedrez Ichessboard; // Las coordenadas horizontales y verticales máximas de la junta están protegidas int maxx; protegido int maxy; // Todas las piezas de ajedrez en blanco Lista protegida <Point> AllFreePoints; @Override Public Final List <Point> getMyPoints () {return MyPoints; } @Override public void setchessboard (ICHessboard Chessboard) {this.chessboard = Chessboard; allfreePoints = Chessboard.getFreePoints (); maxx = Chessboard.getMaxx (); maxy = Chessboard.getMaxy (); mypoints.clear (); } punto final privado temp = nuevo punto (0, 0); // ¿Gano el público Final Boolean Haswin () {if (myPoints.size () <5) {return false; } Point Point = myPoints.get (myPoints.size ()-1); int count = 1; int x = point.getx (), y = Point.gety (); // horizontal- temp.setx (x) .sety (y); while (mypoints.contains (temp.setx (temp.getx ()-1)) && temp.getx ()> = 0 && count <5) {Count ++; } if (count> = 5) {return true; } temp.setx (x) .sety (y); while (mypoints.contains (temp.setx (temp.getx ()-1)) && temp.getx ()> = 0 && count <5) {Count ++; } if (count> = 5) {return true; } temp.setx (x) .sety (y); while (mypoints.contains (temp.setx (temp.getx ()+1)) && temp.getx () <maxx && count <5) {count ++; } if (count> = 5) {return true; } // Perpendicular | recuento = 1; temp.setx (x) .sety (y); while (mypoints.contains (temp.sety (temp.gety ()-1)) && temp.gety ()> = 0) {count ++; } if (count> = 5) {return true; } temp.setx (x) .sety (y); while (mypoints.contains (temp.sety (temp.gety ()-1)) && temp.gety ()> = 0) {count ++; } if (count> = 5) {return true; } temp.setx (x) .sety (y); while (mypoints.contains (temp.sety (temp.gety ()+1)) && temp.gety () <maxy && count <5) {count ++; } if (count> = 5) {return true; } // hacia adelante oblicua/count = 1; temp.setx (x) .sety (y); while (mypoints.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 (mypoints.contains (temp.setx (temp.getx ()+1) .sety (temp.gety ()-1)) && temp.getx () <maxx && temp.gety ()> = 0 && Count <6) {Count ++; } if (count> = 5) {return true; } // Back -stain/count = 1; temp.setx (x) .sety (y); while (mypoints.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 (mypoints.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; }} Implementación de la IA de la computadora
import java.util.arrayList; import java.util.collections; import java.util.hashmap; import java.util.list; import java.util.map; // La clase central del algoritmo, la idea principal del algoritmo se divide en tres pasos. // El primer paso: asume cíclicamente el puntaje para uno mismo y la otra parte (para hacer un puntaje dentro de un cierto rango) de acuerdo con la situación actual de ambas partes, y juzgar los cambios en la situación que esta pie Llámalo mitad en vivo 4), etc.), incluidos el enemigo y nuestro lado. // Paso 3: Ordene el resultado anterior de acuerdo con las reglas dadas por el usuario y seleccione Subjetivo y formas defensivas (hay reglas para formas ofensivas y defensivas) BaseComputerai de clase pública extiende BasePlayer {// Cuatro direcciones, horizontal -, vertical | , delantero-cenador /, retroceso / privado estático final int heng = 0; Private estático final int zhong = 1; Private estático final int zheng_xie = 2; privado estático final int fan_xie = 3; // delantero final de la parte delantera a la espalda delantero del booleano estático privado = true; Private estático final Boolean hacia atrás = falso; // Muestra el resultado del análisis. Ya sea que el punto actual sea un pase de dos gama (vivo) o solo pase de un solo gama (half_alive), el proceso de análisis de la pieza de ajedrez bloqueado se bloquea automáticamente, no como una pieza de ajedrez para ser seleccionada estática privada final int viva = 1; Private estático final int half_alive = 0; // Private estático final intit = -1; // Calcular el rango, el rango demasiado grande tendrá problemas de rendimiento de la clase privada CalcUterSange {int xStart, ystart, xstop, ystop; privado calcUterange (int xStart, int ystart, int xStop, int ystop) {this.xstart = xStart; this.Start = ystart; this.xstop = xstop; this.ThoTop = ystop; }} // limita el rango de cálculo de la computadora. Si todo el rendimiento del cálculo del tablero de ajedrez es demasiado pobre, actualmente se forma en función del valor límite de todas las piezas de ajedrez que se han puesto en uso. Actualmente es 1 privado estático final int range_step = 1; CalcUterange currentRange = new CalcUterGe (0, 0, 0, 0); Private void initRange (List <Point> Couters, List <Point> Humans) {currentRange.xStart = humanos.get (0) .getx ()-range_step; CurrentRange.Start = humanos.get (0) .gety ()-range_step; currentRange.xstop = humanos.get (0) .getx ()+range_step; CurrentRange.ThoTop = humanos.get (0) .gety ()+range_step; for (punto de punto: humanos) {if (punto.getx ()-range_step <currentRange.xstart) {currentRange.xstart = punto.getx ()-range_step; } else if (punto.getx ()+range_step> currentRange.xstop) {currentRange.xstop = point.getx ()+range_step; } if (point.gety ()-range_step <currentRange.Start) {currentRange.Start = Point.gety ()-range_step; } else if (punto.gety ()+range_step> currentRange.ytop) {currentRange.ytop = point.gety ()+range_step; }} para (punto de punto: couters) {if (punto.getx ()-range_step <currentRange.xstart) {currentRange.xstart = point.getx ()-range_step; } else if (punto.getx ()+range_step> currentRange.xstop) {currentRange.xstop = point.getx ()+range_step; } if (point.gety ()-range_step <currentRange.Start) {currentRange.Start = Point.gety ()-range_step; } else if (punto.gety ()+range_step> currentRange.ytop) {currentRange.ytop = point.gety ()+range_step; }} // Si el rango se expande y excede el tablero de ajedrez, es igual al tablero de ajedrez CurrentRange.xstart = CurrentRange.xStart <0? 0: CurrentRange.xStart; CurrentRange.Start = CurrentRange.Start <0? 0: CurrentRange.Start; CurrentRange.Start = CurrentRange.Start <0? 0: CurrentRange.Start; currentRange.xstop = currentRange.xstop> = maxx? Maxx-1: currentRange.xstop; CurrentRange.ThoTop = CurrentRange.YTOP> = maxy? Maxy-1: currentRange.Thop; } // Analizar la forma actual de método de entrada. El análisis se divide en tres pasos en total. El tercer paso puede controlarse por subclases para dificultades. Punto privado doanalysis (List <Point> Couters, List <Point> Humans) {if (humanos.size () == 1) {// El primer paso devuelve getFirstpoint (humanos); } // Inicializar el rango de cálculo InitRange (comutadores, humanos); // Borrar los resultados anteriores InitanalysisResults (); // Inicie el análisis, escanee todos los puntos en blanco y forme el primer punto de análisis del punto BestPoint = dOfirstanalysis (comutadores, humanos); if (bestPoint! = null) {//system.out.println("is pieza es la más importante, solo puedes reproducir esta pieza "); devolver bestpoint; } // Analice el primer resultado y encuentre su mejor punto bestpoint = doComputerSencondanalysis (ComputerFirStresults, ComputerSencodresults); if (bestpoint! = null) {//system.out.println("i''m a punto de ganar, reproduciré esta pieza "); devolver bestpoint; } ComputerFirStresults.Clear (); System.gc (); // Analizar el primer resultado y encontrar el mejor punto del enemigo BestPoint = Dohumansencondanalysis (HumanFirstresults, Humansencodresults); if (bestpoint! = null) {//system.out.println("I no tocas esta pieza, perderás "); devolver bestpoint; } HumanFirStresults.Clear (); System.gc (); // no se encontró ningún punto de muerte final, el tercer análisis de resultados devolvió Dothirdanalysis (); } // El primer paso de la pieza de ajedrez no requiere cálculos complicados, y se completa en función del valor x del primer paso humano de la pieza de ajedrez. Point privado getFirstpoint (List <Point> Humans) {Point Point = Humans.get (0); if (punto.getx () == 0 || Point.gety () == 0 || Point.getx () == maxx && point.gety () == maxy) return nuevo punto (maxx/2, maxy/2); else {return new Point (punto.getx ()-1, punto.gety ()); }} // private int debugx, debugy; // use para el análisis de depuración // iniciar el análisis, escanear todos los puntos en blanco y formar el primer análisis resultado de punto privado dOfirstanalysis (list <point> couters, list <point> humanos) {int size = allFreepoints.size (); Point ComputerPoint = nulo; Point HumanPoint = nulo; int x, y; FirstanalysisResult FirstanalysisResult; for (int i = 0; i <size; i ++) {computerPoint = allFreePoints.get (i); // Haga clic en las coordenadas X e Y primero, porque el objeto original se cambiará durante el proceso de análisis x = ComputerPoint.getx (); y = ComputerPoint.gety (); if (x <currentRange.xstart || x> currentRange.xstop || y <currentRange.Start || y> currentRange.ytop) {continuar; } // if (x == Debugx && y == Debugy) {// System.out.println ("SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS) {continuar;} // if (x == Debugx && Y == Debugy) {/// System.out.println("ssssssssssssssssssssssssssssssssssssssssssss){ // } //Try to set a chess piece at this position and analyze the states that we can only form in the "horizontal" direction, such as live 4, live 3, semi-living 4, live 2, etc. firstAnalysisResult = tryAndCountresult (comutadores, humanos, computerpoint, heng); ComputerPoint.setX (x) .sety (y); // Responder el valor original del punto para el siguiente análisis if (FirstAnalysisResult! = NULL) {// Sin resultado de retorno, es imposible alcanzar cinco piezas de ajedrez en esta dirección. If (FirstAnalysisResult.Count == 5) // igual a 5 significa que puede jugar piezas de ajedrez en este punto y puede conectarse a 5. Si gane, no lo analizará. Devolver Computerpoint; // Registre el primer resultado del análisis AddToFirStanalysisResult (FirstanalysisResult, ComputerFirStresults); } // Repita los pasos anteriores en la "dirección vertical" FirstanalysysuSult = tryandCounTresult (comutadores, humanos, computerpoint, zhong); ComputerPoint.setX (x) .sety (y); if (FirstAnalysisResult! = Null) {// muere el ajedrez, no repunte if (firstAnalysisResult.count == 5) return ComputerPoint; AddtofirStanalysisResult (FirstAnalysisResult, ComputerFirStresults); } // avanzado oblicuo FirstanalysisResult = TryandCountresult (comutadores, humanos, computerpoint, zheng_xie); ComputerPoint.setX (x) .sety (y); if (FirstAnalysisResult! = NULL) {// Dead Chess, no juegue if (FirstAnalysisResult.Count == 5) return ComputerPoint; AddtofirStanalysisResult (FirstAnalysisResult, ComputerFirStresults); } // Backside FirstAnalysisResult = TryAndCoUnTreSult (comutadores, humanos, computerpoint, fan_xie); ComputerPoint.setX (x) .sety (y); if (FirstAnalysisResult! = NULL) {// Dead Chess, no juegue if (FirstAnalysisResult.Count == 5) return ComputerPoint; AddtofirStanalysisResult (FirstAnalysisResult, ComputerFirStresults); } // Analizar el estado de esta pieza en el enemigo en la dirección "horizontal", como el enemigo Live 3, semi-viviendo 4, etc. FirstAnalysisResult = TryandCountresult (humanos, comutadores, computerpoint, heng); ComputerPoint.setX (x) .sety (y); if (FirstAnalysisResult! = NULL) {// Die Chess, no juegue if (FirstAnalysisResult.count == 5) HumanPoint = ComputerPoint; AddtofirStanalysisResult (FirstanalysisResult, HumanFirstresults); } // "Long-Perpendicular" FirstAnalysysisResult = TryandCountresult (humanos, comutadores, computerpoint, zhong); ComputerPoint.setX (x) .sety (y); if (FirstAnalysisResult! = NULL) {// Die Chess, no se reproduce si (FirstAnalysisResult.count == 5) HumanPoint = ComputerPoint; AddtofirStanalysisResult (FirstanalysisResult, HumanFirstresults); } // "Forward-Slant" FirstAnalysisResult = TryandCountresult (humanos, comutadores, computerpoint, zheng_xie); ComputerPoint.setX (x) .sety (y); if (FirstAnalysisResult! = NULL) {// Die Chess, no se reproduce si (FirstAnalysisResult.count == 5) HumanPoint = ComputerPoint; AddtofirStanalysisResult (FirstanalysisResult, HumanFirstresults); } // "Back -savlash" FirstAnalysisResult = TryandCountresult (humanos, comutadores, computerpoint, fan_xie); ComputerPoint.setX (x) .sety (y); if (FirstAnalysisResult! = NULL) {// Die Chess, no se reproduce si (FirstAnalysisResult.count == 5) HumanPoint = ComputerPoint; AddtofirStanalysisResult (FirstanalysisResult, HumanFirstresults); }} // Si no hay una pieza ganadora, el primer análisis no necesita devolver el resultado del primer análisis; } // El segundo análisis, analice el resultado de la primera formación, el primer resultado del análisis generará hasta cuatro objetos de FirstanalysisResult (cuatro enemigos y entre sí). // Los cuatro objetos deben combinarse en un objeto SencondanalysysultResult, Point DoComputerSencondanalysis de punto privado (MAP <Point, LIST <FirstAnalysisResult>> FirStresults, List <sencondanalysysisResult> sencodresults) {list <sveralysalysysisResult> list = null; SencondanalysisResult sr = null; para (punto p: firstresults.keySet ()) {sr = new sencondanalysysuResult (p); list = FirStresults.get (P); for (FirstAnalysisResult Result: List) {if (result.count == 4) {if (result.alivestate == Alive) {// Después del filtrado anterior, ambos lados descartaron la muerte final. Si hay 4, da este paso y gana el siguiente paso. resultado.point; // Si hay una muerte final, la primera ronda ha regresado. En esta ronda de 4 ya es una buena pieza, regrese directamente y ya no analice} else {sr.halfalive4 ++; Computer4Halfalives.Add (SR); }} else if (result.count == 3) {if (result.alivestate == vivo) {sr.alive3 ++; if (sr.alive3 == 1) {Computer3Alives.Add (sr); } else {ComputerDouble3Alives.Add (sr); }} else {sr.halfalive3 ++; Computer3halfalives.Add (SR); }} else {// semi-live 2 ha sido excluido en la primera etapa y ya no procesado Sr.alive2 ++; if (sr.alive2 == 1) {Computer2Alives.Add (Sr); } else {ComputerDouble2Alives.Add (sr); }}}} sencodresults.add (sr); } // No se encontró Live 4; regresar nulo; } // Este método es básicamente el mismo que el anterior, pero para el rendimiento, es menos juicio, separa a los humanos y computadoras Punto privado Dohumansencondanalysis (map <punto, lista <sveralysalysuSeSult>> firstresults, list <sencondanalysisresult> sencodresults) SencondanalysisResult sr = null; para (punto p: firstresults.keySet ()) {sr = new sencondanalysysuResult (p); list = FirStresults.get (P); para (FirstAnalysisResult Result: List) {if (result.count == 4) {if (result.alivestate == vivo) {human4alives.add (sr); } else {sr.halfalive4 ++; Human4halfalives.Add (SR); }} else if (result.count == 3) {if (result.alivestate == vivo) {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); }}} sencodresults.add (sr); } // No se encontró en vivo 4 return null; } private nulo sleep (int minisecond) {try {thread.sleep (minisecond); } capt (interruptedException e) {}} // El tercer análisis, ninguno de los lados puede crear un 4 piezas en vivo en vivo 3, si no, encontrar la mitad de vida 4, si no, encontrar un único en vivo 3, doble live 2 private point dothandanalysis () {if (! Computer4halfalives.isempty ()) {devuelve Computer4halfalfalives.get (0) .Point; } System.gc (); dormir (300); Colección.sort (ComputerSencodresults); System.gc (); // Estoy a punto de vivir 4, y no tengo 4 o más vida 4 o más, por lo que solo puedo bloquear el punto MostBest = getBestpoint (human4alivos, computadorascodressults); if (MostBest! = NULL) return MostBest; Colección.sort (humanoscodresults); System.gc (); MostBest = GetBestPoint (); if (MostBest! = NULL) return MostBest; // Saque los primeros, y quien sea mejor devolverá ComputerSencodresults.get (0) .Point; } // La subclase implementa este método y cambia su orden para lograr el punto protegido orientado o atacando la defensa getBestpoint () {// Estoy a punto de vivir 4, y no tengo 4 o más vida 4 o más, por lo que solo puedo bloquear el punto MostBest = GetBestPoint (ComputerDouble3Alives, HumansencodResults); if (MostBest! = NULL) return MostBest; MostBest = GetBestpoint (Computer3Alives, HumansCodresults); if (MostBest! = NULL) return MostBest; MostBest = GetBestPoint (HumanDouble3alives, ComputerSencodresults); if (MostBest! = NULL) return MostBest; MostBest = GetBestpoint (human3alivos, computadorascodresults); if (MostBest! = NULL) return MostBest; MostBest = GetBestPoint (ComputerDouble2Alives, humansCodresults); if (MostBest! = NULL) return MostBest; MostBest = GetBestpoint (Computer2alives, humansiCodresults); if (MostBest! = NULL) return MostBest; MostBest = GetBestPoint (Computer3Halfalives, humansCodresults); if (MostBest! = NULL) return MostBest; MostBest = getBestpoint (human4halfalives, ComputerSencodresults); if (MostBest! = NULL) return MostBest; MostBest = GetBestpoint (HumanDouble2alives, ComputerSencodresults); if (MostBest! = NULL) return MostBest; MostBest = getBestpoint (human2alivos, computadorascodresults); if (MostBest! = NULL) return MostBest; MostBest = getBestpoint (human3halfalives, computadorascodresults); regresar MostBest; } // El último paso del tercer análisis, se ha ordenado el segundo resultado, aquí puede seleccionar la mejor pieza de ajedrez desde el punto de ajuste frontal GetBestpoint (list <sencondanalysisResult> myBest, list <sencondanalysisResult> theingodresults) {if (! MyBest.isempty () {if (mybest.size ()> 1) (SencondanalysalResult Your: tytisEncodResults) {if (myBest.contains (your)) {return Your.point; }} return myBest.get (0) .Point; } else {return myBest.get (0) .Point; }} return null; } // El primer análisis dura el mapa final privado <punto, lista <sveralysysisResult>> ComputerFirStresults = new HashMap <Point, List <SveralysysisResult>> (); mapa final privado <punto, lista <sveralysysisResult>> humanFirStresults = new HashMap <Point, List <FirstAnalysisResult> (); // La segunda lista final protegida por el resultado total <SenCondanalysisResult> ComputerSencodresults = new ArrayList <sencondanalysisResult> (); Lista final protegida <SenCondanalysisResult> humansiCodresults = new ArrayList <SencondanalysisResult> (); Lista final protegida <SencondanalysisResult> (); // El segundo resultado es, la lista final protegida por computadora <SencondanalysisResult> Computer4Halfalives = new ArrayList <SencondanalysisResult> (2); Lista final protegida <SenCondanalysisResult> ComputerDouble3Alives = new ArrayList <SencondanalysisResult> (4); Lista final protegida <SenCondanalysisResult> Computer3Alives = new ArrayList <SencondanalysisResult> (5); Lista final protegida <SenCondanalysisResult> Computer3Alives = new ArrayList <SencondanalysisResult> (5); Lista final protegida <SenCondanalysisResult> ComputerDouble2Alives = new ArrayList <SencondanalysisResult> (); Lista final protegida <SenCondanalysisResult> Computer2Alives = new ArrayList <SencondanalysisResult> (); Lista final protegida <SenCondanalysisResult> Computer3Halfalives = new ArrayList <SencondanalysisResult> (); // El segundo resultado es, la lista final protegida humana <SencondanalysisResult> human4alives = new ArrayList <SencondanalysisResult> (2); Lista final protegida <SenCondanalysisResult> human4halfalives = new ArrayList <SencondanalysisResult> (5); Lista final protegida <SenCondanalysisResult> HumAnDouble3Alives = new ArrayList <SencondanalysisResult> (2); Lista final protegida <SencondanalysisResult> human3alives = new ArrayList <SencondanalysisResult> (10); Lista final protegida <SenCondanalysisResult> HumanDouble2Alives = new ArrayList <SencondanalysisResult> (3); Lista final protegida <SenCondanalysisResult> human2Alives = new ArrayList <SencondanalysisResult> (); Lista final protegida <SenCondanalysisResult> human3halfalives = new ArrayList <SencondanalysisResult> (); // Los resultados del análisis de la liquidación de la pieza anterior antes del primer análisis Void private initanalysysuSults () {ComputerFirStresults.Clear (); HumanFirstresults.Clear (); // El segundo resultado total ComputerSencodresults.Clear (); humanoscodresults.clear (); // El segundo resultado Computer4Halfalives.Clear (); ComputerDouble3Alives.Clear (); Computer3alives.clear (); ComputerDouble2Alives.Clear (); Computer2Alives.clear (); Computer3halfalives.clear (); Computer3alives.clear (); ComputerDouble2Alives.Clear (); Computer2Alives.clear (); Computer3halfalives.clear (); // El segundo resultado es human4alives.clear (); human4halfalives.clear (); HumAndeuble3Alives.Clear (); human3alives.clear (); HumanDouble2Alives.Clear (); human2alives.clear (); human3halfalives.clear (); System.gc (); } // Agregar al primer análisis de análisis Void privado AddtofirStanalysysuResult (FirstAnalysisResult Result, MAP <Point, List <FirstAnalysisResult>> dest) {if (dest.containskey (result.point)) {Dest.get (resultado.Point) .Add (resultado); } else {list <SveralysysisResult> list = new ArrayList <SveralysysisResult> (1); list.add (resultado); dest.put (resultado.point, lista); }} // Clase de resultados de primer análisis Clase privada FirstAnalysysuSULT {// Conteo continuo; // punto de punto; // dirección int dirección; // estado int alivestate; Privado FirstanalysisResult (int count, punto de punto, int dirección) {this (cuenta, punto, dirección, vivo); } private FirstanalysisResult (int count, punto de punto, int dirección, int alivestate) {this.count = count; this.Point = Point; this.Direction = Direction; this.alivestate = alivestate; } private FirstanalysisResult Init (Point Point, int Direction, Int Alivestate) {this.count = 1; this.Point = Point; this.Direction = Direction; this.alivestate = alivestate; devolver esto; } private FirstanalysisResult Cloneme () {return New FirstanalysisResult (Count, Point, Direction, Alivestate); }} // SecondanalysisResult implementa comparable <sencondanalysisResult> {int vivo4 = 0; // Living 3 int Alive3 = 0; // Secondliving 4, un extremo del sello int halfalive4 = 0; // Secondliving 3, un extremo del sello int halfalive3 = 0; // Living 2 Cantidad int Alive2 = 0; // punto de punto; @Override public int hashcode () {final int prime = 31; int resultado = 1; resultado = Prime * resultado + ((Point == NULL)? 0: Point.HashCode ()); resultado de retorno; } @Override public boolean iguales (object obj) {sencondanalysisResult otros = (sencondanalysisResult) obj; if (punto == null) {if (otro.point! = null) return false; } else if (! Point.equals (Other.Point)) return false; devolver verdadero; } private sencondanalysisResult (punto de punto) {this.point = Point; } // Durante el tercer análisis, los resultados del segundo análisis están ordenados. Esta es la función de devolución de llamada de clasificación @Override public int Compareto (sencondanalysisResult otro) {return compareTowResult (este, otro); }} // Si el return -1 es el primer parámetro, 1 es el segundo parámetro es el primero, y 0 es el intent intent en el orden original comparación de la comparación (sencondanalysusysuSult OneResult, sencondanalysisResult otro) {if (oneResult.alive4> otro.alive4) {return -1; } if (oneResult.alive4 <otro.alive4) {return 1; } if (oneResult.alive4> otro.alive4) {return -1; } if (oneResult.alive3> otro.alive3) {return -1; } if (oneResult.alive3 <otro.alive3) {return 1; } if (oneResult.alive2> otro.alive2) {return -1; } if (oneResult.alive2 <other.alive2) {return 1; } if (oneResult.alive3> otro.alive3) {return -1; } if (oneResult.alive3> otro.alive3) {return 1; } return 0; } // Se utiliza un objeto temporal para almacenar temporalmente los resultados del análisis durante el primer análisis. Si hay más de 1 (excluyendo) resultados, se llama al método de clonema para obtener el resultado. De lo contrario, este resultado se descartará privado FirstAnalysysysUnsult Far = new FirstanalysisResult (1, Null, Heng); // Análisis Si el SUB está al lado de la posición actual, cuántos subs se formarán en una determinada dirección. Parámetros: todos los puntos que se han colocado en el lado actual, el punto que debe asumirse, la dirección que debe juzgarse private Firstanalysissult intyandCounTresult (List <Point> MyPoints, List <Point> EnemyPoints, Point Point, int Direction) {int x = punto.getx (); int y = punto.gety (); FirstAnalysisResult FR = NULL; int maxCountInThisDirection = maxCountInthisDirection (punto, enemyPoints, dirección, 1); if (maxCountInThisDirection <5) {// La pieza de ajedrez sin sentido return null; // Hay menos de cinco espacios vacíos en esta dirección, y la pieza de ajedrez que ya ha establecido está excluida} de lo contrario if (maxCountInthisDirection == 5) {// el estado medio principal, si es un fin de one-fin.init (punto, dirección, dirección); } else {// Ambos extremos son fr = far.init (punto, dirección, vivo); } // Calcule CountPoint (MyPoints, EnemyPoints, Point.setx (x) .sety (y), fr, dirección, hacia adelante); CountPoint (MyPoints, EnemyPoints, Point.SetX (x) .sety (y), fr, dirección, hacia atrás); if (fr.count <= 1 || (fr.count == 2 && fr.alivestate == half_alive)) {// realive1, semi-activo2 y los siguientes resultados, abandonan el retorno nulo; } // devuelve el resultado de copiar return Fr.Cloneme (); } // La pieza de ajedrez sale de la pared boolean privada isoutsideOfwall (punto de punto, int dirección) {if (direction == heng) {return point.getx () <0 || punto.getx ()> = maxx; // Los valores máximos x e y están fuera de la pared, así que use el signo igual} else if (direction == zhong) {return point.gety () <0 || Point.gety ()> = maxy; } else {// Puede haber un problema aquí return Point.getx () <0 || Point.gety () <0 || Point.gety () <0 || Point.gety () <0 || Point.gety () <0 || punto.getx ()> = maxx || Point.gety ()> = maxy; }} Point Point de privado (punto de punto, int dirección, boolean hacia adelante) {switch (direction) {case heng: if (hacia adelante) punto.x ++; else Point.x--; romper; Caso Zhong: if (hacia adelante) Point.y ++; más punto.y--; romper; caso zheng_xie: if (hacia adelante) {punto.x ++; punto.y--; } else {Point.x--; Point.y ++; } romper; Case Fan_Xie: if (hacia adelante) {Point.x ++; Point.y ++; } else {Point.x--; punto.y--; } romper; } punto de retorno; } // cuántas piezas se pueden jugar en una determinada dirección (una de las ocho). Este método es el método central en el primer análisis del punto de conteo privado (list> myPoints, list <foint> enemyPoints, punto de punto, firstAnalysisResult fr, int dirección, boolean hacia adelante) {if (myPoints.contains (puntos de puntos (punto, dirección, direction))) {FR.Count ++; if (myPoints.contains (PointTonext (Point, Direction, Forward))) {FR.Count ++; if (myPoints.contains (PointTonext (Point, Direction, Forward))) {FR.Count ++; if (myPoints.contains (PointTonext (Point, Direction, Forward))) {FR.Count ++; } else if (enemyPoints.contains (punto) || isoutsideOfWall (punto, dirección)) {fr.alivestate = half_alive; }} else if (enemyPoints.contains (punto) || isoutsideOfWall (punto, dirección)) {fr.alivestate = half_alive; }} else if (enemyPoints.contains (punto, dirección)) {fr.alivestate = half_alive; }} else if (enemyPoints.contains (punto) || isoutsideOfWall (punto, dirección)) {fr.alivestate = half_alive; }} else if (enemyPoints.contains (punto) || isoutsideOfWall (punto, dirección)) {fr.alivestate = half_alive; }} // ¿Todavía puedes obtener cinco piezas en una cierta dirección privada int maxCountIntisDirection (punto de punto, list <point> enemyPoints, int direction, int count) {int x = point.getx (), y = punto.gety (); switch (dirección) {// case horizontal heng: while (! enemyPoints.contains (punto.setx (punto.getx ()-1)) && point.getx ()> = 0 && count <6) {count ++; } Point.setx (x); while (! EnemyPoints.Contains (Point.SetX (Point.getx ()+1)) && Point.getx () <maxx && count <6) {count ++; } romper; // Caso perpendicular zhong: while (! EnemyPoints.contains (punto.sety (punto.gety ()-1)) && point.gety ()> = 0) {count ++; } punto.sety (y); while (! EnemyPoints.Contains (Point.Sety (Point.gety ()+1)) && Point.gety () <maxy && count <6) {Count ++; } romper; // hacia adelante oblicua/case zheng_xie: while (! EnemyPoints.contains (punto.setx (punto.getx ()-1) .sety (punto.gety ()+1)) && point.getx ()> = 0 && point.gety () <maxy) {count ++; } punto.setx (x) .sety (y); while (! EnemyPoints.Contains (Point.SetX (Point.getx ()+1) .sety (Point.gety ()-1)) && Point.getx () <maxx && point.gety ()> = 0 && Count <6) {Count ++; } romper; // Backslash/Case Fan_Xie: while (! EnemyPoints.contains (punto.setx (punto.getx ()-1) .sety (punto.gety ()-1)) && point.getx ()> = 0 && point.gety ()> = 0) {Count ++; } punto.setx (x) .sety (y); while (! EnemyPoints.Contains (Point.SetX (Point.getx ()+1) .sety (Point.gety ()+1)) && Point.getx () <maxx && point.gety () <maxy && count <6) {count ++; } romper; } recuento de retorno; } // Reproducir piezas de ajedrez, interfaz externa @Override public void run (List <Point> Humans, Point P) {// Eliminar el último paso del ser humano Allfreepoints.remove (humanos.get (humanos.size ()-1)); // un paso de la computadora puede hacer el resultado de punto = DoNalysis (mypoints, humanos); // Retire las piezas de ajedrez en la computadora AllfreePoints.Remove (resultado); // Agregar a las piezas de ajedrez de la computadora y reproducir mypoints.Add (resultado); }} Es muy fácil implementar jugadores humanos
import java.util.list; Public Class HumanPlayer extiende BasePlayer {@Override public void run (list <point> enemyPoints, punto p) {getMyPoints (). add (p); allfreePoints.remove (p); }}Resumen: aunque está escrito en Java, el algoritmo se ha abstraído y puede modificarse fácilmente en implementaciones de varias plataformas.
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.