本篇文章為大家展示了使用Java怎么實現(xiàn)一個五子棋AI算法,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
創(chuàng)新互聯(lián)是一家專業(yè)提供宜陽企業(yè)網(wǎng)站建設,專注與成都網(wǎng)站設計、做網(wǎng)站、H5技術(shù)、小程序制作等業(yè)務。10年已為宜陽眾多企業(yè)、政府機構(gòu)等服務。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站制作公司優(yōu)惠進行中。
棋盤抽象接口
import java.util.List; public interface IChessboard { //取得棋盤最大橫坐標 public int getMaxX(); //最大縱坐標 public int getMaxY(); //取得當前所有空白點,這些點才可以下棋 public List<Point> getFreePoints(); }
棋子類實現(xiàn)
//棋子類 public class Point { // 這了性能,設成公有 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; } }
玩家抽象接口
import java.util.List; public interface IPlayer { //下一步棋子,傳入對手已經(jīng)下的棋子集合 public void run(List<Point> enemyPoints, Point point); public boolean hasWin(); public void setChessboard(IChessboard chessboard); public List<Point> getMyPoints(); }
玩家基礎抽象類
import java.util.ArrayList; import java.util.List; public abstract class BasePlayer implements IPlayer { //我已下的棋子 protected List<Point> myPoints = new ArrayList<Point>(200); //棋盤 protected IChessboard chessboard; //棋盤最大橫坐標和縱標, protected int maxX; protected int maxY; //所有空白棋子 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); //我是否是否贏了 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(); //橫向-- 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; } //縱向| 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()<maxY && count<5) { count ++; } if(count>=5){ return true; } //正斜向 / 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; } //反斜 \ 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; } }
電腦AI類實現(xiàn)
import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; //算法核心類,算法的主體思想分三個步驟, //第一步:根據(jù)雙方的當前的形勢循環(huán)地假設性的分別給自己和對方下一子(在某個范圍內(nèi)下子),并判斷此棋子能帶來的形勢上的變化,如能不能沖4,能不能形成我方或敵方雙3等, //第二步:根據(jù)上一步結(jié)果,組合每一步棋子所帶來的所有結(jié)果(如某一步棋子可能形成我方1個活3,1個沖4(我叫它半活4)等),包括敵方和我方的。 //第三步:根據(jù)用戶給的規(guī)則對上一步結(jié)果進行排序,并選子(有進攻形、防守形規(guī)則) public class BaseComputerAi extends BasePlayer { // 四個方向,橫- 、縱| 、正斜/ 、反斜\ 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; //往前往后 private static final boolean FORWARD = true; private static final boolean BACKWARD = false; //標示分析結(jié)果當前點位是兩頭通(ALIVE)還是只有一頭通(HALF_ALIVE),封死的棋子分析過程自動屏蔽,不作為待選棋子 private static final int ALIVE = 1; private static final int HALF_ALIVE = 0; //private static final int DEAD = -1; //計算范圍,太大的范圍會有性能問題 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; } } //限定電腦計算范圍,如果整個棋盤計算,性能太差,目前是根據(jù)所有已下的棋子的邊界值加RANGE_STEP值形成,目前為1 private static final int RANGE_STEP = 1; CalcuteRange currentRange = new CalcuteRange(0, 0, 0, 0); private void initRange(List<Point> comuters, 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 : comuters) { 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; } } //如果范圍擴大后超過了棋盤,則等于棋盤 currentRange.xStart=currentRange.xStart<0?0:currentRange.xStart; 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; } // 分析當前形式的入口方法,分析總共分三個步驟,第三步驟可由子類干預以作難度控制 private Point doAnalysis(List<Point> comuters, List<Point> humans) { if(humans.size()==1){//第一步 return getFirstPoint(humans); } //初始化計算范圍 initRange(comuters, humans); //清除以前的結(jié)果 initAnalysisResults(); // 開始分析,掃描所有空白點,形成第一次分析結(jié)果 Point bestPoint = doFirstAnalysis(comuters, humans); if(bestPoint!=null){ //System.out.println("這個棋子最重要,只能下這個棋子"); return bestPoint; } // 分析第一次結(jié)果,找到自己的最佳點位 bestPoint = doComputerSencondAnalysis(computerFirstResults,computerSencodResults); if(bestPoint!=null){ //System.out.println("快要贏了,就下這個棋子"); return bestPoint; } computerFirstResults.clear(); System.gc(); // 分析第一次結(jié)果,找到敵人的最佳點位 bestPoint = doHumanSencondAnalysis(humanFirstResults,humanSencodResults); if(bestPoint!=null){ //System.out.println("再不下這個棋子就輸了"); return bestPoint; } humanFirstResults.clear(); System.gc(); //沒找到絕殺點,第三次結(jié)果分析 return doThirdAnalysis(); } //下第一步棋子,不需要復雜的計算,根據(jù)人類第一步棋子X值減1完成 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;//用于DEBUG // 開始分析,掃描所有空白點,形成第一次分析結(jié)果 private Point doFirstAnalysis(List<Point> comuters, 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); //先把X、Y坐標記下來,因為在分析過程中會改變原來的對象 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("sssssssssssss"); // } //嘗試在此位置上下一個棋子,并分析在“橫向”這個方向上我方可形成的狀態(tài),如活4,活3,半活4,活2等所有狀態(tài) firstAnalysisResult = tryAndCountResult(comuters,humans, computerPoint, HENG); computerPoint.setX(x).setY(y);//回復點位的原值,以供下次分析 if(firstAnalysisResult!=null){//無返回結(jié)果此方向上不可能達到五個棋子, if(firstAnalysisResult.count==5)//等于5表示在此點上下棋子即可連成5個,勝利了,不再往下進行分析 return computerPoint; //記錄第一次分析結(jié)果 addToFirstAnalysisResult(firstAnalysisResult,computerFirstResults); } //在“縱向”這個方向上重復上面的步驟 firstAnalysisResult = tryAndCountResult(comuters,humans, computerPoint, ZHONG); computerPoint.setX(x).setY(y); if(firstAnalysisResult!=null){//死棋,不下 if(firstAnalysisResult.count==5) return computerPoint; addToFirstAnalysisResult(firstAnalysisResult,computerFirstResults); } //正斜向 firstAnalysisResult = tryAndCountResult(comuters,humans, computerPoint, ZHENG_XIE); computerPoint.setX(x).setY(y); if(firstAnalysisResult!=null){//死棋,不下 if(firstAnalysisResult.count==5) return computerPoint; addToFirstAnalysisResult(firstAnalysisResult,computerFirstResults); } //反斜向 firstAnalysisResult = tryAndCountResult(comuters,humans, computerPoint, FAN_XIE); computerPoint.setX(x).setY(y); if(firstAnalysisResult!=null){//死棋,不下 if(firstAnalysisResult.count==5) return computerPoint; addToFirstAnalysisResult(firstAnalysisResult,computerFirstResults); } //在“橫向”上分析此棋子可在敵方形成如何狀態(tài),如敵方的活3、半活4等 firstAnalysisResult = tryAndCountResult(humans,comuters, computerPoint, HENG); computerPoint.setX(x).setY(y); if(firstAnalysisResult!=null){//死棋,不下 if(firstAnalysisResult.count==5) humanPoint = computerPoint; addToFirstAnalysisResult(firstAnalysisResult,humanFirstResults); } //“縱向” firstAnalysisResult = tryAndCountResult(humans,comuters, computerPoint, ZHONG); computerPoint.setX(x).setY(y); if(firstAnalysisResult!=null){//死棋,不下 if(firstAnalysisResult.count==5) humanPoint = computerPoint; addToFirstAnalysisResult(firstAnalysisResult,humanFirstResults); } //“正斜” firstAnalysisResult = tryAndCountResult(humans,comuters, computerPoint, ZHENG_XIE); computerPoint.setX(x).setY(y); if(firstAnalysisResult!=null){//死棋,不下 if(firstAnalysisResult.count==5) humanPoint = computerPoint; addToFirstAnalysisResult(firstAnalysisResult,humanFirstResults); } //“反斜” firstAnalysisResult = tryAndCountResult(humans,comuters, computerPoint, FAN_XIE); computerPoint.setX(x).setY(y); if(firstAnalysisResult!=null){//死棋,不下 if(firstAnalysisResult.count==5) humanPoint = computerPoint; addToFirstAnalysisResult(firstAnalysisResult,humanFirstResults); } } //如果沒有絕殺棋子,第一次分析不需要返回結(jié)果 return humanPoint; } //第二次分析,分析第一次形成的結(jié)果,第一次分析結(jié)果會把一步棋在四個方向上可形成的結(jié)果生成最多四個FirstAnalysisResult對象(敵我各四) //這里要把這四個對象組合成一個SencondAnalysisResult對象, 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){//經(jīng)過前面的過濾,雙方都排除了絕殺棋,有活4就下這一步了,再下一步就贏了 return result.point;//如果有絕殺,第一輪已返回,在此輪活4已經(jīng)是好的棋子,直接返回,不再往下分析 }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{//半活2在第一階段已被排除,不再處理 sr.alive2++; if(sr.alive2==1){ computer2Alives.add(sr); }else{ computerDouble2Alives.add(sr); } } } sencodResults.add(sr); } //沒有找到活4 return null; } //這個方法和上面的基本一樣,但為了性能,少作幾次判斷,將人類和電腦的分開了 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); } //沒有找到活4 return null; } private void sleep(int miniSecond){ try { Thread.sleep(miniSecond); } catch (InterruptedException e) { } } //第三次分析,雙方都不可以制造活4,找雙活3棋子,不行就找半活4,再不行就找單活3,雙活2 private Point doThirdAnalysis() { if(!computer4HalfAlives.isEmpty()){ return computer4HalfAlives.get(0).point; } System.gc(); sleep(300); Collections.sort(computerSencodResults); System.gc(); //即將單活4,且我沒有半活4以上的,只能堵 Point mostBest = getBestPoint(human4Alives, computerSencodResults); if(mostBest!=null) return mostBest; Collections.sort(humanSencodResults); System.gc(); mostBest = getBestPoint(); if(mostBest!=null) return mostBest; //拿出各自排第一的,誰好就下誰 return computerSencodResults.get(0).point; } //子類實現(xiàn)這個方法,并改變其順序可以實現(xiàn)防守為主還是猛攻 protected Point getBestPoint(){ //即將單活4,且我沒有半活4以上的,只能堵 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; } //第三次分析的最后一步,第二次結(jié)果已經(jīng)過排序,在此可以從前面選出最好的棋子 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; } //第一次分析結(jié)果 private final Map<Point,List<FirstAnalysisResult>> computerFirstResults = new HashMap<Point,List<FirstAnalysisResult>>(); private final Map<Point,List<FirstAnalysisResult>> humanFirstResults = new HashMap<Point,List<FirstAnalysisResult>>(); //第二次總結(jié)果 protected final List<SencondAnalysisResult> computerSencodResults = new ArrayList<SencondAnalysisResult>(); protected final List<SencondAnalysisResult> humanSencodResults = new ArrayList<SencondAnalysisResult>(); //第二次分結(jié)果,電腦 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> computerDouble2Alives = new ArrayList<SencondAnalysisResult>(); protected final List<SencondAnalysisResult> computer2Alives = new ArrayList<SencondAnalysisResult>(); protected final List<SencondAnalysisResult> computer3HalfAlives = new ArrayList<SencondAnalysisResult>(); //第二次分結(jié)果,人類 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>(); //第一次分析前清空上一步棋子的分析結(jié)果 private void initAnalysisResults(){ computerFirstResults.clear(); humanFirstResults.clear(); //第二次總結(jié)果 computerSencodResults.clear(); humanSencodResults.clear(); //第二次分結(jié)果 computer4HalfAlives.clear(); computerDouble3Alives.clear(); computer3Alives.clear(); computerDouble2Alives.clear(); computer2Alives.clear(); computer3HalfAlives.clear(); //第二次分結(jié)果,人類 human4Alives.clear(); human4HalfAlives.clear(); humanDouble3Alives.clear(); human3Alives.clear(); humanDouble2Alives.clear(); human2Alives.clear(); human3HalfAlives.clear(); System.gc(); } //加入到第一次分析結(jié)果中 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); } } //第一次分析結(jié)果類 private class FirstAnalysisResult{ //連續(xù)數(shù) int count; //點位 Point point; //方向 int direction; //狀態(tài) 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); } } //第二次分析結(jié)果類 class SencondAnalysisResult implements Comparable<SencondAnalysisResult>{ int alive4 = 0; //活3數(shù)量 int alive3 = 0; //半活4,一頭封的 int halfAlive4 = 0; //半活3,一頭封的 int halfAlive3 = 0; //活2數(shù)量 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; } //第三次分析時,對第二次分析結(jié)果進行排序,此為排序回調(diào)函數(shù) @Override public int compareTo(SencondAnalysisResult another) { return compareTowResult(this, another); } } //返加-1則第一個參數(shù)優(yōu)先,1則第二個參數(shù)優(yōu)先,0則按原來順序 private int compareTowResult(SencondAnalysisResult oneResult,SencondAnalysisResult another){ if(oneResult.alive4>another.alive4){ return -1; } if(oneResult.alive4<another.alive4){ return 1; } if(oneResult.halfAlive4>another.halfAlive4){ return -1; } if(oneResult.halfAlive4<another.halfAlive4){ 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.halfAlive3>another.halfAlive3){ return -1; } if(oneResult.halfAlive3>another.halfAlive3){ return 1; } return 0; } //一個臨時對象,供第一次分析時臨時存放分析結(jié)果使用,如果分析出有活1以上(不含)的結(jié)果,則調(diào)用其cloneMe方法獲得結(jié)果,否則拋棄此結(jié)果 private final FirstAnalysisResult far = new FirstAnalysisResult(1, null, HENG); // 分析如果在當前位下一子,會形成某個方向上多少個子,參數(shù):當前己方已下的所有點,當前要假設的點,需要判斷的方向 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){ //無意義的棋子 return null;//此方向不足五個空位,已排除己方已下的棋子 }else if(maxCountOnThisDirection==5){ //半死狀態(tài),當是一頭通 fr = far.init(point, direction,HALF_ALIVE); }else{ //兩頭皆通 fr = far.init(point, direction,ALIVE); } //在前和后的方向上計算一次 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)){//活1,半活2及其以下結(jié)果,拋棄 return null; } //返回復制的結(jié)果 return fr.cloneMe(); } //棋子出了墻 private boolean isOutSideOfWall(Point point,int direction){ if(direction==HENG){ return point.getX()<0 || point.getX()>=maxX;//最大的X和Y值均在墻外所以用等號 }else if(direction==ZHONG){ return point.getY()<0 || point.getY()>=maxY; }else{//這里可能有問題 return point.getX()<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; } //在某個方向(八個中的一個)可下多少棋子,這個方法是第一分析中的核心方法 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) || isOutSideOfWall(point,direction)){ fr.aliveState=HALF_ALIVE; } }else if(enemyPoints.contains(point) || isOutSideOfWall(point,direction)){ fr.aliveState=HALF_ALIVE; } } //在某個方向上是否還能下到滿五個棋子 private int maxCountOnThisDirection(Point point,List<Point> enemyPoints,int direction,int count){ int x=point.getX(),y=point.getY(); switch (direction) { //橫向 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; //縱向 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; //正斜向 / 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; //反斜 / 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; } //下棋子,對外接口 @Override public void run(List<Point> humans,Point p) { //把人類下的最后一步棋子去除 allFreePoints.remove(humans.get(humans.size()-1)); //電腦可以下的一步棋子 Point result = doAnalysis(myPoints, humans); //去除電腦下的棋子 allFreePoints.remove(result); //加入到電腦棋子中,下棋了 myPoints.add(result); } }
人類玩家實現(xiàn)起來就非常簡單
import java.util.List; public class HumanPlayer extends BasePlayer { @Override public void run(List<Point> enemyPoints,Point p) { getMyPoints().add(p); allFreePoints.remove(p); } }
上述內(nèi)容就是使用Java怎么實現(xiàn)一個五子棋AI算法,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
文章題目:使用Java怎么實現(xiàn)一個五子棋AI算法
文章源于:http://jinyejixie.com/article0/igogoo.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供、網(wǎng)站設計、網(wǎng)站制作、自適應網(wǎng)站、域名注冊、企業(yè)建站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)