使用Java怎么實(shí)現(xiàn)一個(gè)五子棋AI算法

本篇文章為大家展示了使用Java怎么實(shí)現(xiàn)一個(gè)五子棋AI算法,內(nèi)容簡明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。

創(chuàng)新互聯(lián)是一家專業(yè)提供宜陽企業(yè)網(wǎng)站建設(shè),專注與成都網(wǎng)站設(shè)計(jì)、做網(wǎng)站、H5技術(shù)、小程序制作等業(yè)務(wù)。10年已為宜陽眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站制作公司優(yōu)惠進(jìn)行中。

棋盤抽象接口

import java.util.List; 
 
 
public interface IChessboard { 
 //取得棋盤最大橫坐標(biāo) 
 public int getMaxX(); 
 //最大縱坐標(biāo) 
 public int getMaxY(); 
 //取得當(dāng)前所有空白點(diǎn),這些點(diǎn)才可以下棋 
 public List<Point> getFreePoints(); 
}

棋子類實(shí)現(xiàn)

//棋子類 
public class Point { 
 // 這了性能,設(shè)成公有 
 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 { 
 //下一步棋子,傳入對(duì)手已經(jīng)下的棋子集合 
 public void run(List<Point> enemyPoints, Point point); 
 
 public boolean hasWin(); 
  
 public void setChessboard(IChessboard chessboard); 
  
 public List<Point> getMyPoints(); 
}

玩家基礎(chǔ)抽象類

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; 
 //棋盤最大橫坐標(biāo)和縱標(biāo), 
 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類實(shí)現(xiàn)

import java.util.ArrayList; 
import java.util.Collections; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
 
//算法核心類,算法的主體思想分三個(gè)步驟, 
//第一步:根據(jù)雙方的當(dāng)前的形勢循環(huán)地假設(shè)性的分別給自己和對(duì)方下一子(在某個(gè)范圍內(nèi)下子),并判斷此棋子能帶來的形勢上的變化,如能不能沖4,能不能形成我方或敵方雙3等, 
//第二步:根據(jù)上一步結(jié)果,組合每一步棋子所帶來的所有結(jié)果(如某一步棋子可能形成我方1個(gè)活3,1個(gè)沖4(我叫它半活4)等),包括敵方和我方的。 
//第三步:根據(jù)用戶給的規(guī)則對(duì)上一步結(jié)果進(jìn)行排序,并選子(有進(jìn)攻形、防守形規(guī)則) 
public class BaseComputerAi extends BasePlayer { 
 
 // 四個(gè)方向,橫- 、縱| 、正斜/ 、反斜\ 
 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; 
  
  
  
 //標(biāo)示分析結(jié)果當(dāng)前點(diǎn)位是兩頭通(ALIVE)還是只有一頭通(HALF_ALIVE),封死的棋子分析過程自動(dòng)屏蔽,不作為待選棋子 
 private static final int ALIVE = 1; 
 private static final int HALF_ALIVE = 0; 
 //private static final int DEAD = -1; 
  
 //計(jì)算范圍,太大的范圍會(huì)有性能問題 
 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ì)算范圍,如果整個(gè)棋盤計(jì)算,性能太差,目前是根據(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; 
   } 
  } 
   
  //如果范圍擴(kuò)大后超過了棋盤,則等于棋盤 
  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; 
 } 
 
 // 分析當(dāng)前形式的入口方法,分析總共分三個(gè)步驟,第三步驟可由子類干預(yù)以作難度控制 
 private Point doAnalysis(List<Point> comuters, List<Point> humans) { 
  if(humans.size()==1){//第一步 
   return getFirstPoint(humans); 
  } 
   
  //初始化計(jì)算范圍 
  initRange(comuters, humans); 
   
  //清除以前的結(jié)果 
  initAnalysisResults(); 
  // 開始分析,掃描所有空白點(diǎn),形成第一次分析結(jié)果 
  Point bestPoint = doFirstAnalysis(comuters, humans); 
  if(bestPoint!=null){ 
   //System.out.println("這個(gè)棋子最重要,只能下這個(gè)棋子"); 
   return bestPoint; 
  } 
  // 分析第一次結(jié)果,找到自己的最佳點(diǎn)位 
  bestPoint = doComputerSencondAnalysis(computerFirstResults,computerSencodResults); 
  if(bestPoint!=null){ 
   //System.out.println("快要贏了,就下這個(gè)棋子"); 
   return bestPoint; 
  } 
  computerFirstResults.clear(); 
  System.gc(); 
  // 分析第一次結(jié)果,找到敵人的最佳點(diǎn)位 
  bestPoint = doHumanSencondAnalysis(humanFirstResults,humanSencodResults); 
  if(bestPoint!=null){ 
   //System.out.println("再不下這個(gè)棋子就輸了"); 
   return bestPoint; 
  } 
  humanFirstResults.clear(); 
  System.gc(); 
  //沒找到絕殺點(diǎn),第三次結(jié)果分析 
  return doThirdAnalysis(); 
 } 
  
 
 //下第一步棋子,不需要復(fù)雜的計(jì)算,根據(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 
 
 // 開始分析,掃描所有空白點(diǎn),形成第一次分析結(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坐標(biāo)記下來,因?yàn)樵诜治鲞^程中會(huì)改變原來的對(duì)象 
   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"); 
//   } 
    
   //嘗試在此位置上下一個(gè)棋子,并分析在“橫向”這個(gè)方向上我方可形成的狀態(tài),如活4,活3,半活4,活2等所有狀態(tài) 
   firstAnalysisResult = tryAndCountResult(comuters,humans, computerPoint, HENG); 
   computerPoint.setX(x).setY(y);//回復(fù)點(diǎn)位的原值,以供下次分析 
   if(firstAnalysisResult!=null){//無返回結(jié)果此方向上不可能達(dá)到五個(gè)棋子, 
    if(firstAnalysisResult.count==5)//等于5表示在此點(diǎn)上下棋子即可連成5個(gè),勝利了,不再往下進(jìn)行分析 
     return computerPoint; 
    //記錄第一次分析結(jié)果 
    addToFirstAnalysisResult(firstAnalysisResult,computerFirstResults); 
   } 
    
   //在“縱向”這個(gè)方向上重復(fù)上面的步驟 
   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é)果會(huì)把一步棋在四個(gè)方向上可形成的結(jié)果生成最多四個(gè)FirstAnalysisResult對(duì)象(敵我各四) 
 //這里要把這四個(gè)對(duì)象組合成一個(gè)SencondAnalysisResult對(duì)象, 
 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; 
 } 
  
 //這個(gè)方法和上面的基本一樣,但為了性能,少作幾次判斷,將人類和電腦的分開了 
 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; 
 } 
  
 //子類實(shí)現(xiàn)這個(gè)方法,并改變其順序可以實(shí)現(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; 
  //點(diǎn)位 
  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; 
  //點(diǎn)位 
  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; 
  } 
   
   
  //第三次分析時(shí),對(duì)第二次分析結(jié)果進(jìn)行排序,此為排序回調(diào)函數(shù) 
  @Override 
  public int compareTo(SencondAnalysisResult another) { 
   return compareTowResult(this, another); 
  } 
    
 } 
  
 //返加-1則第一個(gè)參數(shù)優(yōu)先,1則第二個(gè)參數(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; 
 } 
  
  
 //一個(gè)臨時(shí)對(duì)象,供第一次分析時(shí)臨時(shí)存放分析結(jié)果使用,如果分析出有活1以上(不含)的結(jié)果,則調(diào)用其cloneMe方法獲得結(jié)果,否則拋棄此結(jié)果 
 private final FirstAnalysisResult far = new FirstAnalysisResult(1, null, HENG); 
 // 分析如果在當(dāng)前位下一子,會(huì)形成某個(gè)方向上多少個(gè)子,參數(shù):當(dāng)前己方已下的所有點(diǎn),當(dāng)前要假設(shè)的點(diǎn),需要判斷的方向 
 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;//此方向不足五個(gè)空位,已排除己方已下的棋子 
  }else if(maxCountOnThisDirection==5){ 
   //半死狀態(tài),當(dāng)是一頭通 
   fr = far.init(point, direction,HALF_ALIVE); 
  }else{ 
   //兩頭皆通 
   fr = far.init(point, direction,ALIVE); 
  } 
   
  //在前和后的方向上計(jì)算一次 
  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; 
  } 
  //返回復(fù)制的結(jié)果 
  return fr.cloneMe(); 
 } 
  
 //棋子出了墻 
 private boolean isOutSideOfWall(Point point,int direction){ 
  if(direction==HENG){ 
   return point.getX()<0 || point.getX()>=maxX;//最大的X和Y值均在墻外所以用等號(hào) 
  }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; 
 } 
  
 //在某個(gè)方向(八個(gè)中的一個(gè))可下多少棋子,這個(gè)方法是第一分析中的核心方法 
 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; 
  } 
 } 
  
  
 
 //在某個(gè)方向上是否還能下到滿五個(gè)棋子 
 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; 
 } 
  
 //下棋子,對(duì)外接口 
 @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); 
 } 
}

人類玩家實(shí)現(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怎么實(shí)現(xiàn)一個(gè)五子棋AI算法,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

文章題目:使用Java怎么實(shí)現(xiàn)一個(gè)五子棋AI算法
文章源于:http://bm7419.com/article0/igogoo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供、網(wǎng)站設(shè)計(jì)、網(wǎng)站制作、自適應(yīng)網(wǎng)站域名注冊、企業(yè)建站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

手機(jī)網(wǎng)站建設(shè)