Goziqi AI algorithm is also a typical game AI algorithm. Some chess AI algorithms can be used as reference. The following is the Java implementation code.
Chessboard abstract interface
import java.util.List; public interface IChessboard { //Get the maximum horizontal coordinate of the board public int getMaxX(); //Maximum vertical coordinate public int getMaxY(); //Get all current blank points, and these points can only play chess public List<Point> getFreePoints(); }Chess class implementation
//The chess class Point { // This is the performance, set to public int x; public int y; public int getX() { return x; } public Point setX(int x) { this.x = x; return this; } public int getY() { return y; } public Point setY(int y) { this.y = y; return this; } public Point(int x, int y) { this.x = x; this.y = y; } @Override public int hashCode() { return x + y; } @Override public boolean equals(Object obj) { if (this == obj) return true; Point other = (Point) obj; if (x != other.x) return false; if (y != other.y) return false; return true; } } Player abstract interface
import java.util.List; public interface IPlayer { //The next step is to pass the chessboard set that the opponent has already set public void run(List<Point> enemyPoints, Point point); public boolean hasWin(); public void setChessboard(IChessboard chessboard); public List<Point> getMyPoints(); } Player basic abstract class
import java.util.ArrayList; import java.util.List; public abstract class BasePlayer implements IPlayer { //The chess piece I have placed protected List<Point> myPoints = new ArrayList<Point>(200); //The chessboard protected IChessboard chessboard; //The maximum horizontal and vertical coordinates of the board are protected int maxX; protected int maxY; //All blank chess pieces protected List<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(); } private final Point temp = new Point(0, 0); //Do I win public 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| count = 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; } //Forward oblique/ 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; } //Backslash/ 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; } } Computer AI implementation
import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; //The core class of the algorithm, the main idea of the algorithm is divided into three steps. //The first step: cyclically assume the score for oneself and the other party (to make a score within a certain range) according to the current situation of both parties, and judge the changes in the situation that this piece can bring, such as whether it can rush 4, whether it can form our or enemy double 3, etc. //The second step: According to the results of the previous step, combine all the results brought by each piece (such as a piece of chess piece may form our side 1 live 3, 1 run 4 (I call it half live 4), etc.), including the enemy and our side. //Step 3: Sort the previous result according to the rules given by the user and select sub-subjective and defensive shapes (there are rules for offensive and defensive shapes) public class BaseComputerAi extends BasePlayer { // Four directions, horizontal - , vertical | , forward-slant / , back-slant / private static final int HENG = 0; private static final int ZHONG = 1; private static final int ZHENG_XIE = 2; private static final int FAN_XIE = 3; //Front to back private static final boolean FORWARD = true; private static final boolean BACKWARD = false; //Display the analysis result. Whether the current point is two-end pass (ALIVE) or only one-end pass (HALF_ALIVE), the blocked chess piece analysis process is automatically blocked, not as a chess piece to be selected private static final int ALIVE = 1; private static final int HALF_ALIVE = 0; //private static final int DEAD = -1; //calculate range, too large range will have performance problems private class CalcuteRange{ int xStart, yStart, xStop,yStop; private CalcuteRange(int xStart, int yStart, int xStop, int yStop) { this.xStart = xStart; this.yStart = yStart; this.xStop = xStop; this.yStop = yStop; } } //Limit the computer calculation range. If the entire chess board calculation performance is too poor, it is currently formed based on the boundary value of all the chess pieces that have been put into use. It is currently 1 private static final int RANGE_STEP = 1; CalcuteRange currentRange = new CalcuteRange(0, 0, 0, 0); private void initRange(List<Point> couters, List<Point> humans){ 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; for (Point point : humans) { 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; } } for (Point 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; } } //If the range is expanded and exceeds the chessboard, it is equal to the chessboard 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; } // Analyze the current form of entry method. The analysis is divided into three steps in total. The third step can be controlled by subclasses for difficulty. private Point doAnalysis(List<Point> couters, List<Point> humans) { if(humans.size()==1){//The first step returns getFirstPoint(humans); } //Initialize the calculation range initRange(comuters, humans); //Clear the previous results initAnalysisResults(); // Start analysis, scan all blank points, and form the first analysis result Point bestPoint = doFirstAnalysis(comuters, humans); if(bestPoint!=null){ //System.out.println("This piece is the most important, you can only play this piece"); return bestPoint; } // Analyze the first result and find your best point bestPoint = doComputerSencondAnalysis(computerFirstResults,computerSencodResults); if(bestPoint!=null){ //System.out.println("I'm about to win, I'll play this piece"); return bestPoint; } computerFirstResults.clear(); System.gc(); //Analyze the first result and find the best point of the enemy bestPoint = doHumanSencondAnalysis(humanFirstResults,humanSencodResults); if(bestPoint!=null){ //System.out.println("If you don't play this piece, you will lose"); return bestPoint; } humanFirstResults.clear(); System.gc(); //No final kill point was found, the third result analysis returned doThirdAnalysis(); } //The first step of the chess piece does not require complicated calculations, and it is completed based on the X value of the human first step of the chess piece. private Point getFirstPoint(List<Point> humans) { Point point = humans.get(0); if(point.getX()==0 || point.getY()==0 || point.getX()==maxX && point.getY()==maxY) return new Point(maxX/2, maxY/2); else{ return new Point(point.getX()-1,point.getY()); } } // private int debugx,debugy;//Use for DEBUG // Start analysis, scan all blank points, and form the first analysis result private Point doFirstAnalysis(List<Point> couters, List<Point> humans){ int size = allFreePoints.size(); Point computerPoint = null; Point humanPoint = null; int x,y; FirstAnalysisResult firstAnalysisResult; for (int i = 0; i < size; i++) { computerPoint = allFreePoints.get(i); //Click down the X and Y coordinates first, because the original object will be changed during the analysis process x = computerPoint.getX(); y = computerPoint.getY(); if(x<currentRange.xStart || x>currentRange.xStop || y<currentRange.yStart || y>currentRange.yStop){ continue; } // if(x==debugx && y==debugy){ // System.out.println("ssssssssssssssssssssssssssssssssssssss){ continue; } // 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(comuters,humans, computerPoint, HENG); computerPoint.setX(x).setY(y);//Reply the original value of the point for the next analysis if(firstAnalysisResult!=null){//No return result, it is impossible to reach five chess pieces in this direction. If(firstAnalysisResult.count==5)//Equal to 5 means that you can play chess pieces at this point and you can connect to 5. If you win, you will not analyze it down. Return computerPoint; //Record the first analysis result addToFirstAnalysisResult(firstAnalysisResult,computerFirstResults); } //Repeat the above steps in the "vertical direction" firstAnalysisResult = tryAndCountResult(comuters,humans, computerPoint, ZHONG); computerPoint.setX(x).setY(y); if(firstAnalysisResult!=null){//Die the chess, don't play if(firstAnalysisResult.count==5) return computerPoint; addToFirstAnalysisResult(firstAnalysisResult,computerFirstResults); } //Forward oblique firstAnalysisResult = tryAndCountResult(comuters,humans, computerPoint, ZHENG_XIE); computerPoint.setX(x).setY(y); if(firstAnalysisResult!=null){//Dead chess, do not play if(firstAnalysisResult.count==5) return computerPoint; addToFirstAnalysisResult(firstAnalysisResult,computerFirstResults); } //Backside firstAnalysisResult = tryAndCountResult(comuters,humans, computerPoint, FAN_XIE); computerPoint.setX(x).setY(y); if(firstAnalysisResult!=null){//Dead chess, do not play if(firstAnalysisResult.count==5) return computerPoint; addToFirstAnalysisResult(firstAnalysisResult,computerFirstResults); } //Analyze the state of this piece in the enemy in the "horizontal" direction, such as the enemy's live 3, semi-living 4, etc. firstAnalysisResult = tryAndCountResult(humans,comuters, computerPoint, HENG); computerPoint.setX(x).setY(y); if(firstAnalysisResult!=null){//Die chess, do not play if(firstAnalysisResult.count==5) humanPoint = computerPoint; addToFirstAnalysisResult(firstAnalysisResult,humanFirstResults); } //"Long-Perpendicular" firstAnalysisResult = tryAndCountResult(humans,comuters, computerPoint, ZHONG); computerPoint.setX(x).setY(y); if(firstAnalysisResult!=null){//Die chess, don't play if(firstAnalysisResult.count==5) humanPoint = computerPoint; addToFirstAnalysisResult(firstAnalysisResult,humanFirstResults); } //"Forward-slant" firstAnalysisResult = tryAndCountResult(humans,comuters, computerPoint, ZHENG_XIE); computerPoint.setX(x).setY(y); if(firstAnalysisResult!=null){//Die chess, don't play if(firstAnalysisResult.count==5) humanPoint = computerPoint; addToFirstAnalysisResult(firstAnalysisResult,humanFirstResults); } //"Backslash" firstAnalysisResult = tryAndCountResult(humans,comuters, computerPoint, FAN_XIE); computerPoint.setX(x).setY(y); if(firstAnalysisResult!=null){//Die chess, don't play if(firstAnalysisResult.count==5) humanPoint = computerPoint; addToFirstAnalysisResult(firstAnalysisResult,humanFirstResults); } } //If there is no winning piece, the first analysis does not need to return the result of the first analysis; } //The second analysis, analyze the result of the first formation, the first analysis result will generate up to four FirstAnalysisResult objects (four enemies and each other). //The four objects should be combined into a SencondAnalysisResult object, private Point doComputerSencondAnalysis(Map<Point,List<FirstAnalysisResult>> firstResults,List<SencondAnalysisResult> sencodResults) { List<FirstAnalysisResult> list = null; SencondAnalysisResult sr = null; for (Point p : firstResults.keySet()) { sr = new SencondAnalysisResult(p); list = firstResults.get(p); for (FirstAnalysisResult result : list) { if(result.count==4){ if(result.aliveState==ALIVE){//After the previous filtering, both sides ruled out the ultimate kill. If there is 4, take this step, and win the next step. result.point;//If there is a final kill, the first round has returned. In this round of 4 is already a good piece, return directly and no longer analyze it }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 has been excluded in the first stage and no longer processed sr.alive2++; if(sr.alive2==1){ computer2Alives.add(sr); }else{ computerDouble2Alives.add(sr); } } } } sencodResults.add(sr); } //No live 4 was found; return null; } //This method is basically the same as above, but for performance, it is less judgment, separates humans and computers private Point doHumanSencondAnalysis(Map<Point,List<FirstAnalysisResult>> firstResults,List<SencondAnalysisResult> sencodResults) { List<FirstAnalysisResult> list = null; SencondAnalysisResult sr = null; for (Point p : firstResults.keySet()) { sr = new SencondAnalysisResult(p); list = firstResults.get(p); for (FirstAnalysisResult result : list) { if(result.count==4){ if(result.aliveState==ALIVE){ 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); } } } sencodResults.add(sr); } //No live 4 was found return null; } private void sleep(int miniSecond){ try { Thread.sleep(miniSecond); } catch (InterruptedException e) { } } //The third analysis, neither side can create a live 4, find double live 3 pieces, if not, find half live 4, if not, find single live 3, double live 2 private Point doThirdAnalysis() { if(!computer4HalfAlives.isEmpty()){ return computer4HalfAlives.get(0).point; } System.gc(); sleep(300); Collections.sort(computerSencodResults); System.gc(); //I'm about to live 4, and I don't have half-living 4 or more, so I can only block Point mostBest = getBestPoint(human4Alives, computerSencodResults); if(mostBest!=null) return mostBest; Collections.sort(humanSencodResults); System.gc(); mostBest = getBestPoint(); if(mostBest!=null) return mostBest; //Take out the first ones, and whoever is better will return computerSencodResults.get(0).point; } //Subclass implements this method and changes its order to achieve defense-oriented or attacking protected Point getBestPoint(){ //I'm about to live 4, and I don't have half-living 4 or more, so I can only block Point mostBest = getBestPoint(computerDouble3Alives, humanSencodResults); if(mostBest!=null) return mostBest; mostBest = getBestPoint(computer3Alives, humanSencodResults); if(mostBest!=null) return mostBest; mostBest = getBestPoint(humanDouble3Alives, computerSencodResults); if(mostBest!=null) return mostBest; mostBest = getBestPoint(human3Alives, computerSencodResults); if(mostBest!=null) return mostBest; mostBest = getBestPoint(computerDouble2Alives, humanSencodResults); if(mostBest!=null) return mostBest; mostBest = getBestPoint(computer2Alives, humanSencodResults); if(mostBest!=null) return mostBest; mostBest = getBestPoint(computer3HalfAlives, humanSencodResults); 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(human2Alives, computerSencodResults); if(mostBest!=null) return mostBest; mostBest = getBestPoint(human3HalfAlives, computerSencodResults); return mostBest; } //The last step of the third analysis, the second result has been sorted, here you can select the best chess piece from the front protected Point getBestPoint(List<SencondAnalysisResult> myBest,List<SencondAnalysisResult> yourSencodResults){ if(!myBest.isEmpty()){ if(myBest.size()>1){ for (SencondAnalysisResult your : yourSencodResults) { if(myBest.contains(your)){ return your.point; } } return myBest.get(0).point; } else{ return myBest.get(0).point; } } return null; } //The first analysis result private final Map<Point,List<FirstAnalysisResult>> computerFirstResults = new HashMap<Point,List<FirstAnalysisResult>>(); private final Map<Point,List<FirstAnalysisResult>> humanFirstResults = new HashMap<Point,List<FirstAnalysisResult>>(); //The second total result protected final List<SencondAnalysisResult> computerSencodResults = new ArrayList<SencondAnalysisResult>(); protected final List<SencondAnalysisResult> humanSencodResults = new ArrayList<SencondAnalysisResult>(); protected final List<SencondAnalysisResult>(); //The second result is, the computer protected final List<SencondAnalysisResult> computer4HalfAlives = new ArrayList<SencondAnalysisResult>(2); protected final List<SencondAnalysisResult> computerDouble3Alives = new ArrayList<SencondAnalysisResult>(4); protected final List<SencondAnalysisResult> computer3Alives = new ArrayList<SencondAnalysisResult>(5); protected final List<SencondAnalysisResult> computer3Alives = new ArrayList<SencondAnalysisResult>(5); protected final List<SencondAnalysisResult> computerDouble2Alives = new ArrayList<SencondAnalysisResult>(); protected final List<SencondAnalysisResult> computer2Alives = new ArrayList<SencondAnalysisResult>(); protected final List<SencondAnalysisResult> computer3HalfAlives = new ArrayList<SencondAnalysisResult>(); //The second result is, human protected final List<SencondAnalysisResult> human4Alives = new ArrayList<SencondAnalysisResult>(2); protected final List<SencondAnalysisResult> human4HalfAlives = new ArrayList<SencondAnalysisResult>(5); protected final List<SencondAnalysisResult> humanDouble3Alives = new ArrayList<SencondAnalysisResult>(2); protected final List<SencondAnalysisResult> human3Alives = new ArrayList<SencondAnalysisResult>(10); protected final List<SencondAnalysisResult> humanDouble2Alives = new ArrayList<SencondAnalysisResult>(3); protected final List<SencondAnalysisResult> human2Alives = new ArrayList<SencondAnalysisResult>(); protected final List<SencondAnalysisResult> human3HalfAlives = new ArrayList<SencondAnalysisResult>(); //The analysis results of clearing the previous piece before the first analysis private void initAnalysisResults(){ computerFirstResults.clear(); humanFirstResults.clear(); //The second total result computerSencodResults.clear(); humanSencodResults.clear(); //The second result computer4HalfAlives.clear(); computerDouble3Alives.clear(); computer3Alives.clear(); computerDouble2Alives.clear(); computer2Alives.clear(); computer3HalfAlives.clear(); computer3Alives.clear(); computerDouble2Alives.clear(); computer2Alives.clear(); computer3HalfAlives.clear(); //The second result is human4Alives.clear(); human4HalfAlives.clear(); humanDouble3Alives.clear(); human3Alives.clear(); humanDouble2Alives.clear(); human2Alives.clear(); human3HalfAlives.clear(); System.gc(); } //Add to the first analysis result private void addToFirstAnalysisResult(FirstAnalysisResult result,Map<Point,List<FirstAnalysisResult>> dest){ if(dest.containsKey(result.point)){ dest.get(result.point).add(result); }else{ List<FirstAnalysisResult> list = new ArrayList<FirstAnalysisResult>(1); list.add(result); dest.put(result.point, list); } } //First analysis result class private class FirstAnalysisResult{ //Continuous count; //Point Point point; //Direction int direction; //State int aliveState; private FirstAnalysisResult(int count, Point point, int direction) { this(count, point, direction, ALIVE); } private FirstAnalysisResult(int count, Point point, int direction,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; return this; } private FirstAnalysisResult cloneMe(){ return new FirstAnalysisResult(count, point, direction,aliveState); } } //SecondAnalysisResult implements Comparable<SencondAnalysisResult>{ int alive4 = 0; //Living 3 int alive3 = 0; //SecondLiving 4, one end of the seal int halfAlive4 = 0; //SecondLiving 3, one end of the seal int halfAlive3 = 0; //Living 2 quantity int alive2 = 0; //Point point; @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((point == null) ? 0 : point.hashCode()); return result; } @Override public boolean equals(Object obj) { SencondAnalysisResult other = (SencondAnalysisResult) obj; if (point == null) { if (other.point != null) return false; } else if (!point.equals(other.point)) return false; return true; } private SencondAnalysisResult(Point point) { this.point = point; } // During the third analysis, the results of the second analysis are sorted. This is the sort callback function @Override public int compareTo(SencondAnalysisResult another) { return compareTowResult(this, another); } } // If the return -1 is the first parameter, 1 is the second parameter is the first, and 0 is the private int int in the original order compareTowResult(SencondAnalysisResult oneResult,SencondAnalysisResult another){ if(oneResult.alive4>another.alive4){ return -1; } if(oneResult.alive4<another.alive4){ return 1; } if(oneResult.alive4>another.alive4){ return -1; } if(oneResult.alive3>another.alive3){ return -1; } if(oneResult.alive3<another.alive3){ return 1; } if(oneResult.alive2>another.alive2){ return -1; } if(oneResult.alive2<another.alive2){ return 1; } if(oneResult.alive3>another.alive3){ return -1; } if(oneResult.alive3>another.alive3){ return 1; } return 0; } //A temporary object is used to temporarily store the analysis results during the first analysis. If there are more than 1 (excluding) results, the cloneMe method is called to obtain the result. Otherwise, this result will be discarded private final FirstAnalysisResult far = new FirstAnalysisResult(1, null, HENG); // Analysis If the sub is next to the current position, how many subs will be formed in a certain direction. Parameters: all points that have been placed on the current side, the point that needs to be assumed, the direction that needs to be judged private FirstAnalysisResult tryAndCountResult(List<Point> myPoints,List<Point> enemyPoints,Point point,int direction) { int x = point.getX(); int y = point.getY(); FirstAnalysisResult fr = null; int maxCountOnThisDirection = maxCountOnThisDirection(point, enemyPoints, direction, 1); if(maxCountOnThisDirection<5){ //Senseless chess piece return null;//There are less than five empty spaces in this direction, and the chess piece you have already set is excluded}else if(maxCountOnThisDirection==5){ //The half-dead state, if it is a one-end fr = far.init(point, direction,HALF_ALIVE); }else{ // Both ends are fr = far.init(point, direction,ALIVE); } //Calculate countPoint(myPoints,enemyPoints,point.setX(x).setY(y),fr,direction,FORWARD); countPoint(myPoints,enemyPoints,point.setX(x).setY(y),fr,direction,BACKWARD); if(fr.count<=1 || (fr.count==2 && fr.aliveState==HALF_ALIVE)){//Realive1, semi-active2 and the following results, abandon return null; } //Return the result of copying return fr.cloneMe(); } //The chess piece comes out of the wall private boolean isOutSideOfWall(Point point,int direction){ if(direction==HENG){ return point.getX()<0 || point.getX()>=maxX;//The maximum X and Y values are outside the wall, so use the equal sign}else if(direction==ZHONG){ return point.getY()<0 || point.getY()>=maxY; }else{//There may be a problem here 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 point,int direction,boolean forward){ switch (direction) { case HENG: if(forward) point.x++; else point.x--; break; case ZHONG: if(forward) point.y++; else point.y--; break; case ZHENG_XIE: if(forward){ point.x++; point.y--; }else{ point.x--; point.y++; } break; case FAN_XIE: if(forward){ point.x++; point.y++; }else{ point.x--; point.y--; } break; } return point; } //How many pieces can be played in a certain direction (one of eight). This method is the core method in the first analysis private void countPoint(List<Point> myPoints, List<Point> enemyPoints, Point point, FirstAnalysisResult fr,int direction,boolean forward) { 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 ++; if(myPoints.contains(pointToNext(point,direction,forward))){ fr.count ++; }else if(enemyPoints.contains(point) || isOutSideOfWall(point,direction)){ fr.aliveState=HALF_ALIVE; } }else if(enemyPoints.contains(point) || isOutSideOfWall(point,direction)){ fr.aliveState=HALF_ALIVE; } }else if(enemyPoints.contains(point,direction)){ fr.aliveState=HALF_ALIVE; } }else if(enemyPoints.contains(point) || isOutSideOfWall(point,direction)){ fr.aliveState=HALF_ALIVE; } }else if(enemyPoints.contains(point) || isOutSideOfWall(point,direction)){ fr.aliveState=HALF_ALIVE; } } //Can you still get five pieces in a certain direction private int maxCountOnThisDirection(Point point,List<Point> enemyPoints,int direction,int count){ int x=point.getX(),y=point.getY(); switch (direction) { //Horizontal case HENG: while (!enemyPoints.contains(point.setX(point.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 ++; } break; //Perpendicular case ZHONG: while (!enemyPoints.contains(point.setY(point.getY()-1)) && point.getY()>=0) { count ++; } point.setY(y); while (!enemyPoints.contains(point.setY(point.getY()+1)) && point.getY()<maxY && count<6) { count ++; } break; //Forward oblique/ case ZHENG_XIE: while (!enemyPoints.contains(point.setX(point.getX()-1).setY(point.getY()+1)) && point.getX()>=0 && point.getY()<maxY) { count ++; } point.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 ++; } break; //Backslash/ case FAN_XIE: while (!enemyPoints.contains(point.setX(point.getX()-1).setY(point.getY()-1)) && point.getX()>=0 && point.getY()>=0) { count ++; } point.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 ++; } break; } return count; } //Play chess pieces, external interface @Override public void run(List<Point> humans,Point p) { //Remove the last step of the human being allFreePoints.remove(humans.get(humans.size()-1)); //One step of the computer can make Point result = doAnalysis(myPoints, humans); //Remove the chess pieces on the computer allFreePoints.remove(result); //Add to the computer chess pieces and play myPoints.add(result); } } It's very easy to implement human players
import java.util.List; public class HumanPlayer extends BasePlayer { @Override public void run(List<Point> enemyPoints,Point p) { getMyPoints().add(p); allFreePoints.remove(p); } }Summary: Although it is written in Java, the algorithm has been abstracted and can be easily modified into implementations of various platforms.
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.