1. 程式人生 > >人工智慧五子棋 java實現

人工智慧五子棋 java實現

一、演算法思想

1、搜尋樹 甲乙兩人下棋,甲有很多種落子方式,乙也有多種應對走法,如果把所有的走法列出來,自然就構成了一棵樹,即為搜尋樹,也稱博弈樹。樹的根結點為先手的第一步走法,下面的走法構成了樹的子結點,直至棋局結束。顯然,如果棋盤足夠大,子結點數會以幾何級數上升,而我們的任務是從這些子結點中尋找一個對己方最有利的結點,從而得到棋局的最佳走法。 估值函式 估值函式通常是為了評價棋型的狀態,根據實現定義的一個棋局估值表,對雙方的棋局形態進行計算,根據得到的估值來判斷應該採用的走法。棋局估值表是根據當前的棋局形勢,定義一個分值來反映其優勢程度,來對整個棋局形勢進行評價。 3、極大極小搜尋 極大極小搜尋演算法就是在博弈樹在尋找最優解的一個過程,這主要是一個對各個子結點進行比較取捨的過程,定義一個估值函式F(n)來分別計算各個終結點的分值,通過雙方的分值來對棋局形勢進行分析判斷。還是以甲乙兩人下棋為例,甲為max,乙為min。當甲走棋時,自然在博弈樹中尋找最大點的走法,輪到乙時,則尋找最小點的走法,如此反覆,這就是一個極大極小搜尋過程,以此來尋找對機器的最佳走法。 4、剪枝演算法 αβ剪枝演算法簡單來說,就是在搜尋過程中減少一定的冗餘現象,如已經找到極大值,執行該走法就可以獲勝,則無須再往下進行搜尋比較,此過程即為剪枝。對於極大的MAX結點,稱為α剪枝;反之為β剪枝。具體規則可以簡單描述如下: α剪枝:對於極大值層結點的α值如果不小於它的任一祖先極小值層結點的β值,即α(後續層)≥β(祖先層),則可中止該極大值層中這個MAX節點以下的搜尋過程,這個MAX節點最終的倒推值就確定為這個α值。 β剪枝:對於極小值結點層的β值如果不大於它任一祖先極大值層結點的α值,即α(祖先層)≥β(後續層),則可中止對該極小值層中這個MIN節點以下結點的搜尋,這個MIN節點最終的倒推值就確定為這個β值。

二、詳細設計

2.1總體設計 在演算法設計中,比較重要的是評價函式的求法,因為評價函式是在中級或者高階難度的遊戲模式中,計算機選擇落棋位置的重要依據。 在五子棋遊戲中,棋型很重要,其中有連五(表示已經有五子連線),活四(四子連線並且兩邊都沒有被堵住),眠四(四子連線有一邊被堵住),活三(三子連線兩邊都沒有被堵上),眠三(三子連線,有一邊被堵上),活二,眠二依次類推,其中還有一些其他的情況如:EUUOUU,OUUOUUO等,其中E表示有衝突(邊界或者對方的棋子),U表示已經連線的棋子,O表示空白的位置,我們對這些很有可能連線的棋型,按照連成五子的概率大小不同定義不同的分值。因為我們求評價函式的作用是選擇一個合適的地方落子,所以求評價值是針對空位置。假如我要求某位置黑子的評價值,就是試驗性的將這個位置放上黑子,在橫向,縱向,兩個斜線方向分別以這個位置(x,y)為中心,向兩邊分別擷取4位(因為第五位和此位置無關)一共擷取9位,再看棋型,得到分數,再將這四個方向的分數相加。就為此位置的評價值。具體的擷取方法,匹配方法與計算的方法我在詳細設計部分會很清楚的表達。這部分用方法public int calculateScore(final int x,final int y,int color)實現,x,y為橫座標,縱座標,color為棋子的顏色。返回求得的評價值。 中級難度的下法為,遍歷棋盤,找到己方評價函式最高的位置A,再找到對方評價值最高的位置B,假如自己方的分數高於或者等於對方的分數,就將棋子落在A,反之落在位置B。 高階的下法為 整個程式設計的類,屬性,方法如下: 1、類fivechess: public class fivechess extends JFrame implements ActionListener 成員: JButton back=new JButton(“悔棋”); JButton start=new JButton(“開始”); JButton game=new JButton(“中級難度”); JButton game2=new JButton(“高階難度”); GameBoard gb=new GameBoard(); JPanel pb=new JPanel(); JPanel pg=new JPanel(); 方法: public fivechess()//建構函式 public void actionPerformed(ActionEvent e)//實現按鈕事件 2、類GameBoard: public class GameBoard extends JPanel implements MouseListener 成員: public int row=14;//棋盤行數 public int col=14;//棋盤列數 public int length=30;//每個格子的大小 public int edgedis=30;//邊距 public int[][] ChessBoard=new int[row+1][col+1];//棋子代表的二維陣列, int chessNum=0;//已經下了的棋子數目 boolean IsBlack=true;//判斷哪方下子(黑子先行) int lastx=-1,lasty=-1; //最後下子的位置 int llastx=-1,llasty=-1; //倒數第二次下的位置,方便悔棋 boolean Win=false;//是否勝利的標誌 static final int radius=15; //棋盤的位置的分值(固定為15x15的棋盤) 方法: public GameBoard()//建構函式 public void paintComponent(Graphics g)//畫棋局 public void mousePressed(MouseEvent e)//滑鼠事件 public void computerplayer()//中級下法 public void computerplayerhigher()//高階下法 public int maxMinWithAlphaBetaCut(int chessBoard[][], int whiteOrBlack, int depth, int x,int y, int alpha, int beta)//剪枝演算法 public int calculateScore(final int x,final int y,int color)//算分值 public boolean isExit(int x,int y)//此位置有沒有棋子 public boolean IsWin()//判斷是否已經有五子連線的情況 public int ChessCount(int xChange,int yChange,int color)//計算棋子在xChange和yChange方向上連線的數量(1,0)橫向,(0,1)縱向,(1,1)主對角線,(-1,-1)副對角線 2.2 演算法設計

這部分只介紹重要的演算法,在此程式中重要的演算法有三個,評價值的計算,中級難度下法 1.評價值計算 在橫向,縱向,兩個斜線方向分別以這個位置(x,y)為中心,向兩邊分別擷取4位(因為第五位和此位置無關)一共擷取9位,再看棋型,得到分數,再將這四個方向的分數相加。就為此位置的評價值。 首先需要定義棋型,我將棋型用字串來表示儲存在string型別的陣列type中,將相應的得分儲存在int型別的陣列score中。其中E表示有衝突(邊界或者對方的棋子),U表示已經連線的棋子,O表示空白的位置。用下標對應 在這裡插入圖片描述 在這裡插入圖片描述 每種棋型的型別,以及棋型的評分合理與否很大程度上反應了智慧程度,所以在設定上要多留心,也可以在後續的測試中留意分值的設定是否合理。首先我們需要在棋盤中擷取棋型,以指定的座標(x,y)為中心,在橫向,豎向,正斜個,反斜上向兩邊擴充套件,定義一temp[4]陣列其為string型別,分別用來存放在橫向,豎向,正斜,反斜方向擷取的棋型。在橫向上的擷取是保持y座標不變,設擴充套件的位數為bite。在x軸左向擴充套件時座標的變化為(x-bite,y)所以要確保x-bite>=0,由於棋盤是以0開始的,所以當x小於4時能擴充套件的位數為bite=4-Math.abs(x-4)。 在往右向擴充套件時座標的變化為(x+bite,y)所以要確保x+bite<=14,當在bite小於等於4而x+bite>14時就停止擴充套件。當在擴充套件到的位置遇到自己方的棋子有temp[0]=temp[0]+"U"當在擴充套件位置遇到對方的棋子或者遇到邊界則有temp[0]=temp[0]+"C"擴充套件到的位置的為空位置則有temp[0]=temp[0]+“O”。同理在其他方向也按照這個原則進行擴充套件生成自己的棋型temp[]。 各個方向擴充套件的座標變化如下: 在這裡插入圖片描述
豎向向上(x,y-bite) 豎向向下(x,y+bite) 正斜向上(x-bite,y-bite) 正斜向下(x+bite,y+bite) 反斜向上(x+bite,y-bite) 反斜向下(x-bite,y+bite) 需要注意邊界問題。程式碼實現如下: ///////////////////////////在x軸方向上取//////////////////////////////// if(x-4<0){ int bite=4-Math.abs(x-4); temp[0]=temp[0]+“C”; while(bite!=0){ if(ChessBoard[x-bite][y]==0){ temp[0]=temp[0]+“O”; } else if(ChessBoard[x-bite][y]==color){ temp[0]=temp[0]+“U”; } else { temp[0]=temp[0]+“C”; } bite–; } } else { for(int i=4;i>0;i–){ if(ChessBoard[x-i][y]==0){ temp[0]=temp[0]+“O”; } else if(ChessBoard[x-i][y]==color){ temp[0]=temp[0]+“U”; } else { temp[0]=temp[0]+“C”; } } } for(int i=0;i<=4;i++){ if(x+i>14) { temp[0]=temp[0]+“C”; break; } if(ChessBoard[x+i][y]==0){ temp[0]=temp[0]+“O”; } else if(ChessBoard[x+i][y]==color){ temp[0]=temp[0]+“U”; } else { temp[0]=temp[0]+“C”; } } //////////////////在y方向擷取//////////////////////////// if(y-4<0){ int bite=4-Math.abs(y-4); temp[1]=temp[1]+“C”; while(bite!=0){ if(ChessBoard[x][y-bite]==0){ temp[1]=temp[1]+“O”; } else if(ChessBoard[x][y-bite]==color){ temp[1]=temp[1]+“U”; } else { temp[1]=temp[1]+“C”; } bite–; } } else { for(int i=4;i>0;i–){ if(ChessBoard[x][y-i]==0){ temp[1]=temp[1]+“O”; } else if(ChessBoard[x][y-i]==color){ temp[1]=temp[1]+“U”; } else { temp[1]=temp[1]+“C”; } } } for(int i=0;i<=4;i++){ if(y+i>14) { temp[1]=temp[1]+“C”; break; } if(ChessBoard[x][y+i]==0){ temp[1]=temp[1]+“O”; } else if(ChessBoard[x][y+i]==color){ temp[1]=temp[1]+“U”; } else { temp[1]=temp[1]+“C”; } }

	//////////////////////在左下,右上方向上//////////////////////////////
		if(x-4<0||14-(y+4)<0){
		int b=0;
		if(x-4<0&&14-(y+4)<0){     
			 b=Math.min(4-Math.abs(x-4),14-y);
			 }
		else if(x-4<0&&y<=10){
			b=4-Math.abs(x-4);
		}
		else if(14-(y+4)<0&&x-4>=0){
			b=14-y;
		}
			temp[2]=temp[2]+"C";
			while(b!=0){
				if(ChessBoard[x-b][y+b]==0){
					temp[2]=temp[2]+"O";
				}
				else if(ChessBoard[x-b][y+b]==color){
					temp[2]=temp[2]+"U";
				}
				else {
					temp[2]=temp[2]+"C";
				}
				b--;
			}
		}
		else{
			for(int i=4;i>0;i--){
				if(ChessBoard[x-i][y+i]==0){
					temp[2]=temp[2]+"O";
				}
				else if(ChessBoard[x-i][y+i]==color){
					temp[2]=temp[2]+"U";
				}
				else {
					temp[2]=temp[2]+"C";
				}
			}
		}
		if(y-4<0||14-(x+4)<0){  
			int b=0;
			if(y-4<0&&14-(x+4)<0){     
				 b=Math.min(4-Math.abs(y-4),14-x);
				 }
			else if(y-4<0&&x<=10){
				b=4-Math.abs(y-4);
			}
			else if(14-(x+4)<0&&y-4>=0){
				b=14-x;
			}
				while(b!=0){
					if(ChessBoard[x+b][y-b]==0){
						temp[2]=temp[2]+"O";
					}
					else if(ChessBoard[x+b][y-b]==color){
						temp[2]=temp[2]+"U";
					}
					else {
						temp[2]=temp[2]+"C";
					}
					b--;
				}
				temp[2]=temp[2]+"C";
			}
			else{
				for(int i=0;i<=4;i++){
					if(ChessBoard[x+i][y-i]==0){
						temp[2]=temp[2]+"O";
					}
					else if(ChessBoard[x+i][y-i]==color){
						temp[2]=temp[2]+"U";
					}
					else {
						temp[2]=temp[2]+"C";
					}
				}
			
		}
//////////////////////在左上,右下方向上////////////////////////////////
		if(x-4<0||y-4<0){
			int bite=0;
			if(x-4<0&&y-4<0){
		 bite=Math.min(4-Math.abs(x-4),4-Math.abs(y-4));
			}
			else if(x-4<0&&y-4>=0){
				bite=4-Math.abs(x-4);
			}
			if(y-4<0&&x-4>=0){
				bite=4-Math.abs(y-4);
			}
			temp[3]=temp[3]+"C";
			while(bite!=0){
				if(ChessBoard[x-bite][y-bite]==0){
					temp[3]=temp[3]+"O";
				}
				else if(ChessBoard[x-bite][y-bite]==color){
					temp[3]=temp[3]+"U";
				}
				else {
					temp[3]=temp[3]+"C";
				}
				bite--;
			}
		}
		else {
			for(int i=4;i>0;i--){
				if(ChessBoard[x-i][y-i]==0){
					temp[3]=temp[3]+"O";
				}
				else if(ChessBoard[x-i][y-i]==color){
					temp[3]=temp[3]+"U";
				}
				else {
					temp[3]=temp[3]+"C";
				}
			}
		}
		for(int i=0;i<=4;i++){
			if(y+i>14||x+i>14) {
				temp[3]=temp[3]+"C";
				break;
			}
		    if(ChessBoard[x+i][y+i]==0){
				temp[3]=temp[3]+"O";
			}
			else if(ChessBoard[x+i][y+i]==color){
				temp[3]=temp[3]+"U";
			}
			else {
				temp[3]=temp[3]+"C";
			}
		}

擷取完之後我們需要計算得分,因為擷取到的長度是長於定義的棋型的,所以只要在擷取到棋型構成的字串裡面,有已經定義的棋型的子串,那麼就算匹配上,該位置的得分加上該棋型對應的分數。匹配引入包: import java.util.regex.Matcher; import java.util.regex.Pattern; 呼叫方法來求得 Pattern p=Pattern.compile(type[j]); Matcher m=p.matcher(temp[i]); if(m.find()) 因為棋型在type數組裡面儲存順序是按分數遞減儲存的,所以最開始找到的棋型為最好的,在這四個方向上找到最好的就停止尋找,繼續找下一個方向的。直到得到四個方向的分數並且相加,就為最終的結果。 程式碼實現為: int result=0; for(int i=0;i<4;i++){ for(int j=0;j<38;j++){ Pattern p=Pattern.compile(type[j]); Matcher m=p.matcher(temp[i]); if(m.find()){ result+=score[j]; break; } } } 3.3.2中級下法 中級難度的下法為,遍歷棋盤,找到己方評價函式最高的位置A,再找到對方評價值最高的位置B,假如自己方的分數高於或者等於對方的分數,就將棋子落在A,反之落在位置B。 程式碼實現如下: public void computerplayer(){ /////////////預設黑棋先行/////////////////////////// int MaxScoreBlack=0; int MaxScorewhite=0; int TempScore=0; int maxXB=0,maxYB=0,maxXW=0,maxYW=0; int color=2; llastx=lastx; llasty=lasty; ///////////////////////算白棋總分,當對方的棋局威脅不大時,自己方就進攻選擇得分最高的棋局//////////////// TempScore=0; for(int i=0;i<15;i++){ for(int j=0;j<15;j++){ if(ChessBoard[i][j]==0){ TempScore=this.calculateScore(i, j,color); if(TempScore>MaxScorewhite){ MaxScorewhite=TempScore; maxXW=i; maxYW=j; } } } } /////////////////////////算黑棋總分/////////////////////////////// color=1; TempScore=0; for(int i=0;i<15;i++){ for(int j=0;j<15;j++){ if(ChessBoard[i][j]==0){ TempScore=this.calculateScore(i, j,color); if(TempScore>MaxScoreBlack){ MaxScoreBlack=TempScore; maxXB=i; maxYB=j; } } } } if(MaxScorewhite>=MaxScoreBlack){ lastx=maxXW; lasty=maxYW; } else { lastx=maxXB; lasty=maxYB; } System.out.println(MaxScorewhite); System.out.println(MaxScoreBlack); ChessBoard[lastx][lasty]=2; IsBlack=!IsBlack; //換白棋 chessNum++; return; }

3、程式碼原始碼

import java.awt.Color; import java.awt.Container; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RadialGradientPaint; import java.awt.RenderingHints; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.geom.Ellipse2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException;

import javax.imageio.ImageIO; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JPanel;

public class fivechess extends JFrame{

public fivechess(){
	GameBoard gb=new GameBoard();
	Container contentPane=getContentPane();  
    contentPane.add(gb);
    gb.setOpaque(true);
    add(gb);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(526,549);
    setLocation(400,100);
}


public static void main(String[] args) {
	// TODO Auto-generated method stub
	fivechess f=new fivechess();
	f.setTitle("五子棋單機版-人機對戰");
	f.setVisible(true);

}

public class GameBoard extends JPanel implements MouseListener{
	BufferedImage bgImage=null;//背景圖片
	int row=14;//棋盤行數
	int col=14;//棋盤列數
	int span=30;//每個單元格的寬度
	int dis=30;//邊距
	int[][] ChessBoard=new int[row+1][col+1];//棋子代表的二維陣列,其中0代表沒有落子1代表黑子2代表白子
	
	//儲存每一步的操作,便於悔棋
	int[] allx=new int[(row+1)*(col+1)];
	int[] ally=new int[(row+1)*(col+1)];
	
	int chessNum=0;//已經下了的棋子數目
	boolean IsBlack=true;//判斷哪方下子(黑子先行)
	int lastx=-1,lasty=-1;   //最後下子的位置
	boolean Win=false;//是否勝利的標誌
	
	int[][][] Player=new int[row+1][col+1][4];
	int[][][] Computer=new int[row+1][col+1][4];
	//設定棋子半徑
	static final int radius=15;
	//棋盤的位置的分值(固定為15x15的棋盤)
	
	//建構函式
	public GameBoard() {
		try {
			bgImage=ImageIO.read(new File("src/wuziqi.jpg"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		this.addMouseListener(this);
		//初始化棋盤
		for(int i=0;i<row+1;i++){
			for(int j=0;j<col+1;j++){
				ChessBoard[i][j]=0;
			}
		}

	}
	
	
	//繪製棋盤
	public void paintComponent(Graphics g){
		super.paintComponent(g);
		g.drawImage(bgImage, 0, 0, row*span+2*dis, col*span+2*dis, null);
		//繪製線條
		for(int i=0;i<=row;i++){//橫線
			g.drawLine(dis, dis+i*span, col*span+dis, dis+i*span);
		}
		for(int j=0;j<=col;j++){//豎線
			g.drawLine(dis+j*span, dis, dis+j*span, row*span+dis);
		}
		//繪製棋子
		for(int i=0;i<row+1;i++){
			for(int j=0;j<col+1;j++){
				if(ChessBoard[i][j]!=0){//存在落子
					//獲取網格交叉點的座標(在螢幕上的)
					int x=i*span+dis;
					int y=j*span+dis;
					if(ChessBoard[i][j]==1){//如果落黑子
						g.setColor(Color.BLACK);
						RadialGradientPaint paint=new RadialGradientPaint(x-radius+25,y-radius+10,20,new float[]{0f,1f},new Color[]{Color.WHITE,Color.BLACK});
						((Graphics2D) g).setPaint(paint);  
			            ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);  
			            ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT); 
					}
					else if(ChessBoard[i][j]==2){//如果落白子
						g.setColor(Color.WHITE);
						RadialGradientPaint paint=new RadialGradientPaint(x-radius+25,y-radius+10,70,new float[]{0f,1f},new Color[]{Color.WHITE,Color.BLACK});
						((Graphics2D) g).setPaint(paint);  
			            ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);  
			            ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT); 
					}
					Ellipse2D e = new Ellipse2D.Float(x-radius, y-radius, 30, 30);  
			        ((Graphics2D) g).fill(e);
			        if(i==lastx&&j==lasty){
			        	g.setColor(Color.RED);
			        	g.drawRect(x-radius, y-radius, 30, 30);
			        }
				}
			}
		}
	}
	@Override
	public void mousePressed(MouseEvent e) {
		// TODO Auto-generated method stub 
		String mes="";
		String ChessColor=IsBlack?"黑子":"白子";
		if(Win){
			mes=String.format("遊戲結束!%s已經取得遊戲勝利,請重新開始遊戲!", ChessColor);
			JOptionPane.showMessageDialog(this, mes);
			return;
		}
		if(chessNum==(row+1)*(col+1)){
			mes="棋盤已滿!";
			JOptionPane.showMessageDialog(this, mes);
			return;//不執行任何操作
		}
		//獲得滑鼠落點在二維陣列的索引
		lastx=(e.getX()-dis+span/2)/span;
		lasty=(e.getY()-dis+span/2)/span;
		//落點不在棋盤內不能落子
		if(lastx<0||lastx>row||lasty<0||lasty>col){
			mes="落子處超出棋盤範圍!";
			JOptionPane.showMessageDialog(this, mes);
			return;
		}
		//落點已經存在棋子不能落子
		if(isExit(lastx,lasty)){
			mes="該處已有落子!";
			JOptionPane.showMessageDialog(this, mes);
			return;
		}
		//繪製落子
		if(IsBlack)
			ChessBoard[lastx][lasty]=1;
		else ChessBoard[lastx][lasty]=2;
		chessNum++;
		repaint();
		//判斷勝負
		if(IsWin()){
			Win=true;
			mes=String.format("恭喜,%s贏了!", ChessColor);
			JOptionPane.showMessageDialog(this, mes);
			return;
		}
		IsBlack=!IsBlack;
	}
	
	
	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub
	}
	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub
	}
	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub
	}
	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub
	}  
	public boolean isExit(int x,int y){
		if(ChessBoard[x][y]!=0)
			return true;
		return false;
	}
	public boolean IsWin(){
		int count=1;
		int color=ChessBoard[lastx][lasty];
		//判斷橫向上的相同顏色的棋子數量
		count=this.ChessCount(1, 0, color);
		if(count>=5)
			return true;
		//判斷縱向上的相同顏色棋子的數量
		count=this.ChessCount(0, 1, color);
		if(count>=5)
			return true;
		//判斷主對角線上/的相同顏色棋子的數量
		count=this.ChessCount(1, 1, color);
		if(count>=5)
			return true;
		//判斷副對角線上\的相同顏色棋子的數量
		count=this.ChessCount(1, -1, color);
		if(count>=5)
			return true;
		return false;
	}
	//計算棋子在xChange和yChange方向上連線的數量
	public int ChessCount(int xChange,int yChange,int color){
		int count=1;//棋子計數器
		int tempx=xChange;
		int tempy=yChange;
		//xChange取值範圍(1,0,1,1)和yChange取值範圍(0,1,1,-1)分別代表(橫向,縱向,/,\)
		//先計算正方向上的數量
		while (lastx + xChange >= 0 && lastx + xChange <= row && lasty + yChange >= 0 && lasty + yChange <= col && color == ChessBoard[lastx + xChange][lasty + yChange]) {
			count++;
			if (xChange != 0) {
                xChange++;
			}
			if (yChange != 0) {
                if (yChange > 0) 
                	yChange++;
                else 
                	yChange--;
			}
        }
		//回到最開始的方向
		xChange = tempx;
		yChange = tempy;
		//接著計算反方向上的數量
		while (lastx - xChange >= 0 && lastx - xChange <= row && lasty - yChange >= 0 && lasty - yChange <= col && color == ChessBoard[lastx - xChange][lasty - yChange]) {
			count++;
			if (xChange != 0) {
                xChange++;
			}
			if (yChange != 0) {
                if (yChange > 0) 
                	yChange++;
                else 
                	yChange--;
			}
		}
		return count;
	}
}
}

四、原始碼下載