?? ai.java
字號:
package org.javagarden.j2me.fivelink.client;
/**
* 游戲的人式智能處理類。
* @author Turbo Chen
* @created 2005-4-5
*/
public class AI
{
/**
* 找到最佳下棋點。
* 基本思路是, 先計算每個點的權值,在權值最高的位置下棋
* @author Turbo Chen
* @created 2005-5-11
*/
public static Location findBestChessLocation( Player currentPlayer, FiveLinkModel model)
{
//權值數組
int[][] power = new int[FiveLinkModel.BOARD_SIZE][FiveLinkModel.BOARD_SIZE];
for ( short i = 0; i < FiveLinkModel.BOARD_SIZE; i++ )
{
for ( short j = 0; j < FiveLinkModel.BOARD_SIZE; j++ )
{
// 當已有子時將該點的權值設為-1
if ( model.getChess()[i][j] !=0 )
{
power[i][j] = -1;
}
// 否則計算該點權值
else
{
power[i][j] = (short) calcPower(i, j, currentPlayer,model);
}
}
}
//計算完所有點的權值后, 再找出其中權值最大的點
Location bestLoc = calcMaximumPowerLocation(power);
power = null;
return bestLoc;
}
/**
* 找出權值最大點.
* @param power
* @return
*/
private static Location calcMaximumPowerLocation(int[][] power)
{
int max = 0;
short x = 0, y = 0;
for ( short i = 0; i < FiveLinkModel.BOARD_SIZE; i++ )
{
for ( short j = 0; j < FiveLinkModel.BOARD_SIZE; j++ )
{
if ( power[i][j] > max )
{
x = i;
y = j;
max = power[i][j];
}
}
}
return new Location(x,y);
}
/**
* 檢查m,n點的權值.<p>
* 思路是, 假定在m,n位置下棋后,計算4個方向經過該點,同色相連的棋子數量, 不同的數量有不同的
* 權值,將四個方向上權值相加即為該點的權值.計算完后恢復該點的狀態.
* @param m
* @param n
* @param currentPlayer
* @param model
* @return
*/
private static int calcPower(short m, short n, Player currentPlayer, FiveLinkModel model)
{
int p = 0;
//找AI自己的取勝點,
int p1 = 1000;
//找AI自己的三個相連的點
int p3 = 60;
//找AI自己的兩個相連的點
int p5 = 20;
//找AI自己的相連的點
int p7 = 10;
//找對手的取勝點
int p2 = 85;
//找對手的三個相連的點
int p4 = 45;
//找對手的兩個相連的點
int p6 = 15;
//找對方的相連的點
int p8 = 5;
short[] arrLinks = new short[4];
//如果當是我方下棋, 判斷我方所持棋子的顏色, 在該點預下一子, 然后進行后續計算.
if ( currentPlayer.getChessType()==Player.BLACK )
{
//我方是黑子
model.setChess(m,n,1);
}else
{
//我方是白子
model.setChess(m,n,-1);
}
// 計算4個方向上同色相連棋子的數量.
arrLinks = calcLinkCount(m,n,model.getChess());
//如果m,n是中心點, 將權值加1
if ( m == FiveLinkModel.BOARD_SIZE/2 && n == FiveLinkModel.BOARD_SIZE/2 )
{
p += 1;
}
//計算我方在該點四個方向的權值
for ( short i = 0; i < 4; i++ )
{
if ( Math.abs(arrLinks[i]) == 5 )
{
p += p1;
}
if ( arrLinks[i] == 4 )
{
p += p3;
}
if ( arrLinks[i] == 3 )
{
p += p5;
}
if ( arrLinks[i] == 2 )
{
p += p7;
}
}
//如果當是對手方下棋, 判斷對方所持棋子的顏色, 在該點預下一子, 然后進行后續計算.
if ( currentPlayer.getChessType()==1 )
{
//如果對方是白子,
model.setChess(m,n,-1);
}else
{
//如果對方是黑子,
model.setChess(m,n,1);
}
arrLinks = calcLinkCount(m,n,model.getChess());
//計算對手在該點四個方向的權值
for ( short i = 0; i < 4; i++ )
{
if ( Math.abs(arrLinks[i]) == 5 )
{
p += p2;
}
if ( arrLinks[i] == 4 )
{
p += p4;
}
if ( arrLinks[i] == 3 )
{
p += p6;
}
if ( arrLinks[i] == 2 )
{
p += p8;
}
}
//計算完后恢復該點的原來狀態.
model.setChess(m,n,0);
arrLinks = null;
return p;
}
/**
* 判斷是否平局.
* @param arrchessboard
* @return
*/
public static boolean isTie(short[][] arrchessboard)
{
//當所有位置都有子時為平局
for (short i=0;i<FiveLinkModel.BOARD_SIZE;i++)
{
for (short j=0;j<FiveLinkModel.BOARD_SIZE;j++)
{
if (arrchessboard[i][j] == 0)
return false;
}
}
return true;
}
/**
* 計算4個方向相連棋子的個數
* @param m
* @param n
* @param arrchessboard
* @return 返回一個4元素的數據,分別代表(m,n)點上四個方向聽相連子的個數.
*/
private static short[] calcLinkCount(short m,short n, short[][] arrchessboard)
{
short[] counts = new short[4];
//---------------------------------------
//檢查是否無子可下(當flag=2時表示無子可下)
short flag = 0;
//連子個數
short num = 1;
//檢查正東方向
short x = (short)(m+1);
int y = n+1;
//不超出棋格
for(;x < FiveLinkModel.BOARD_SIZE;)
{
//如果前方的棋子與m,n點不同則跳出循環
if (arrchessboard[x][n] == arrchessboard[m][n])
{
num++;
x++;
}
else
{
break;
}
}
//正東方向超出棋格
if (x==FiveLinkModel.BOARD_SIZE)
{
flag++;
}
else
{
//正東方向有別的子不可再下
if(arrchessboard[x][n] != 0)
{
flag++;
}
}
//檢查正西方向
x = (short)(m-1);
for (;x >= 0;)
{
//前方的棋子與m,n點不同時跳出循環
if (arrchessboard[x][n] == arrchessboard[m][n])
{
num++;
x--;
}
else
{
break;
}
}
//正西方向超出棋格
if (x == -1)
{
flag++;
}
else
{
//正西方向有別的子不可再下
if(arrchessboard[x][n] != 0)
{
flag++;
}
}
if (flag == 2)
{
counts[0] = (short)-num;
}
else
{
if (flag == 1 && num == 3 )
{
//連子數為3時有一邊不能下就不是活三
counts[0] = (short)-num;
}
else
{
counts[0] = num;
}
}
//---------------------------------------
//檢查是否無子可下(當flag=2時表示無子可下)
flag = 0;
//連子個數
num = 1;
//檢查正南方向
x = (short)(n+1);
for(;x<FiveLinkModel.BOARD_SIZE;)
{
//前方的棋子與m,n點不同時跳出循環
if (arrchessboard[m][x] == arrchessboard[m][n])
{
num++;
x++;
}
else
{
break;
}
}
//正南方向超出棋格
if (x==FiveLinkModel.BOARD_SIZE)
{
flag++;
}
else
{
//正南方向有別的子不可在下
if(arrchessboard[m][x] != 0)
{
flag++;
}
}
//檢查正北方向
x = (short) (n-1);
for(;x >= 0;)
{
//前方的棋子與m,n點不同時跳出循環
if (arrchessboard[m][x] == arrchessboard[m][n])
{
num++;
x--;
}
else
{
break;
}
}
//正北方向超出棋格
if (x == -1)
{
flag++;
}
else
{
//正北方向有別的子不可在下
if(arrchessboard[m][x] != 0)
{
flag++;
}
}
if (flag == 2)
{
counts[1] = (short)-num;
}
else
{
if (flag == 1 && num == 3 )
{
//連子數為3時有一邊不能下就不是活三
counts[1] = (short)-num;
}
else
{
counts[1] = num;
}
}
//--------------------------------------
//檢查是否無子可下(當flag=2時表示無子可下)
flag = 0;
//連子個數
num = 1;
//檢查東南方向
x = (short)(m+1);
//不超出棋格
for(;x < FiveLinkModel.BOARD_SIZE && y < FiveLinkModel.BOARD_SIZE;)
{
//前方的棋子與m,n點不同時跳出循環
if (arrchessboard[x][y] == arrchessboard[m][n])
{
num++;
x++;
y++;
}
else
{
break;
}
}
//東南方向超出棋格
if (x==FiveLinkModel.BOARD_SIZE || y==FiveLinkModel.BOARD_SIZE)
{
flag++;
}
else
{
//東南方向有別的子不可在下
if(arrchessboard[x][y] != 0)
{
flag++;
}
}
//檢查西北方向
x = (short)(m-1);
y = n-1;
//不超出棋格
for(;x >= 0 && y >= 0;)
{
//前方的棋子與m,n點不同時跳出循環
if (arrchessboard[x][y] == arrchessboard[m][n])
{
num++;
x--;
y--;
}
else
{
break;
}
}
//西北方向超出棋格
if (x == -1 || y == -1)
{
flag++;
}
else
{
//西北方向有別的子不可在下
if(arrchessboard[x][y] != 0)
{
flag++;
}
}
if (flag == 2)
{
counts[2] = (short)-num;
}
else
{
if (flag == 1 && num == 3 )
{
//連子數為3時有一邊不能下就不是活三
counts[2] = (short)-num;
}
else
{
counts[2] = num;
}
}
//------------------------------------
//檢查是否無子可下(當flag=2時表示無子可下)
flag = 0;
//連子個數
num = 1;
//檢查西南方向
x = (short)(m-1);
y = n+1;
//不超出棋格
for(;x >= 0 && y < FiveLinkModel.BOARD_SIZE;)
{
//前方的棋子與m,n點不同時跳出循環
if (arrchessboard[x][y] == arrchessboard[m][n])
{
num++;
x--;
y++;
}
else
{
break;
}
}
//西南方向超出棋格
if (x == -1 || y == FiveLinkModel.BOARD_SIZE)
{
flag++;
}
else
{
//西南方向有別的子不可在下
if(arrchessboard[x][y] != 0)
{
flag++;
}
}
//檢查東北方向(
x = (short)(m+1);
y = n-1;
//不超出棋格
for(;x < FiveLinkModel.BOARD_SIZE && y >= 0;)
{
//前方的棋子與m,n點不同時跳出循環
if (arrchessboard[x][y] == arrchessboard[m][n])
{
num++;
x++;
y--;
}
else
{
break;
}
}
//東北方向超出棋格
if (x == FiveLinkModel.BOARD_SIZE || y == -1)
{
flag++;
}
else
{
//東北方向有別的子不可在下
if(arrchessboard[x][y] != 0)
{
flag++;
}
}
if (flag == 2)
{
counts[3] = (short)-num;
}
else
{
if (flag == 1 && num == 3 )
{
//連子數為3時有一邊不能下就不是活三
counts[3] = (short)-num;
}
else
{
counts[3] = num;
}
}
// 返回四個方向的相連子的個數。
return counts;
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -