AI中国象棋核心就是:博弈;引申为:在一定的条件下,遵守一定的规则,一个或几个拥有绝对理想思维的团队,从各自允许选择的行为或策略经行选择并加以实施。
博弈问题一般有三个要素:局中人,规则,策略这里的三个要素分别对应象棋中的棋手、象棋规则以及棋术,有五个方面的内容:第一,博弈的参加者,即博弈过程中独立决策,独立承担后果的个人或者组织(本文局中人是棋手);第二,博弈信息,即博弈者所掌握的对选择策略有帮助的情报资料(本文就是两位棋手都知道对面的走的棋,因为棋盘都是公开透明);第三:博弈方可选择的全部行为或策略的集合(中国象棋每一步有50-70种走法,而平均30+回合即可决出胜负);第四:博弈的次序,即博弈参加者做出策略选择的先后(通俗点就是棋手是马吃炮,还是车吃马之间的选择);第五:博弈方的收益,即各博弈方做出的决策选择后的所得和所示(棋手最后是赢了还是输了或者平局)。
评价一个AI中国象棋的好坏主要看它的棋力,经过测试这款AI中国象棋可以战胜90%的象棋玩家,总体效果来说还勉强过得去吧。而一个棋力的好坏,主要看算法,这里用到的算法是决策树,大致的步骤就是(1)取得棋盘上的所有走法;(2)搜索所有走法的分支;(3)评估每个分支。
(1)取得棋盘上的所有分支,主要是根据象棋的规则来的
package com.pj.chess;
import static com.pj.chess.ChessConstant.*;
import static com.pj.chess.Tools.*;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Random;
import com.pj.chess.chessmove.ChessMovePlay;
import com.pj.chess.chessmove.ChessQuiescMove;
import com.pj.chess.chessmove.MoveNode;
import com.pj.chess.chessparam.ChessParam;
import com.pj.chess.evaluate.EvaluateCompute;
import com.pj.chess.evaluate.EvaluateComputeMiddle;
import com.pj.chess.zobrist.TranspositionTable;
import static com.pj.chess.chessmove.ChessQuiescMove.*;
/**
* @author pengjiu
* 棋子棋盘初始化操作
* 棋子的着法预生成
*/
public class ChessInitialize {
//马着法预生成数组
int[][] knightMove=new int[BOARDSIZE90][8];
//马着法拌腿位置预生成数组
int[][] horseLeg=new int[BOARDSIZE90][8];
//象着法预生成数组
int[][] elephantMove=new int[BOARDSIZE90][4];
//象着法拌腿位置预生成数组
int[][] elephantLeg=new int[BOARDSIZE90][4];
//兵着法预生成数组
int[][][] soldierMove=new int[2][BOARDSIZE90][3];
//车吃子着法预生成数组
int[][][] chariotMoveRowEat=new int[9][512][2];//行(上下)
int[][][] chariotMoveColEat=new int[10][1024][2]; //列(左右)
//车炮不吃子着法预生成数组
int[][][] move_chariotGunRowNop=new int[9][512][9];//行(上下)不吃子是有多个情况
int[][][] move_chariotGunColNop=new int[10][1024][10]; //列(左右)
//炮吃子着法预生成数组
int[][][] gunMoveRowEat=new int[9][512][2];//行(上下)
int[][][] gunMoveColEat=new int[10][1024][2]; //列(左右)
//炮伪攻击位置
int[][][] gunFackAttackRow=new int[9][512][9];//行(上下)
int[][][] gunFackAttackCol=new int[10][1024][10]; //列(左右)
//炮隔多子所能攻击到的位置
int[][][] gunMoreRestAttackRow=new int[9][512][9];//行(上下)
int[][][] gunMoreRestAttackCol=new int[10][1024][10]; //列(左右)
public static ChessParam getGlobalChessParam(int[] boardTemp ){
int[] board = new int[BOARDSIZE90];
int[] chesses = new int[48];
for (int i = 0; i < board.length; i++) {
board[i] = -1;
}
for (int i = 0; i < chesses.length; i++) {
chesses[i] = -1;
}
BitBoard[] chessBitBoardRole = new BitBoard[15];
for (int i = 0; i < chessBitBoardRole.length; i++) {
chessBitBoardRole[i] = new BitBoard();
}
ChessParam chessParamCont = new ChessParam(board, chesses, new int[2],
new int[10], new int[9], new int[15], new BitBoard(),
new BitBoard[] { new BitBoard(), new BitBoard() },
chessBitBoardRole);
for(int i=0;i0){
int destSite=i;
int chess=boardTemp[i];
chessParamCont.board[destSite]=chess;
chessParamCont.allChess[chess]=destSite;
int destRow = boardRow[destSite];
int destCol = boardCol[destSite];
chessParamCont.boardBitRow[destRow]|=(1<<(8-destCol));
chessParamCont.boardBitCol[destCol]|=(1<<(9-destRow));
}
}
chessParamCont.initChessBaseScoreAndNum();
TranspositionTable.genStaticZobrist32And64OfBoard(chessParamCont.board);
return chessParamCont;
}
static{
// 位棋盘的初始
for (int i = 0; i < MaskChesses.length; i++) {
MaskChesses[i] = new BitBoard(i);
}
new ChessInitialize();
}
private ChessInitialize(){
//马不考虑别腿的位棋盘
initBitBoard(KnightBitBoards);
//马别腿的位子
initBitBoard(KnightLegBitBoards);
//马象攻击生成
initBitBoard(KnightBitBoardOfAttackLimit);
initBitBoard(ElephanBitBoardOfAttackLimit);
cleanEmpty(knightMove);
cleanEmpty(horseLeg);
cleanEmpty(elephantMove);
cleanEmpty(elephantLeg);
cleanEmpty(soldierMove);
cleanEmpty(gunFackAttackRow);
cleanEmpty(gunFackAttackCol);
cleanEmpty(gunMoreRestAttackRow);
cleanEmpty(gunMoreRestAttackCol);
//初始马的着法
initKnightMove();
//初始象的着法
initElephantMove();
//初始卒的着法
initSoldier();
//初始不吃子车炮对应所有行着法
this.initChariotGunVariedMove(cleanEmpty(move_chariotGunRowNop), 0, 0,false);
//初始不吃子车炮对应所有列着法
this.initChariotGunVariedMove(cleanEmpty(move_chariotGunColNop), 1, 0,false);
//初始炮吃子对应所有行着法
this.initChariotGunVariedMove(cleanEmpty(gunMoveRowEat), 0, 1,true);
//初始炮吃子对应所有列着法
this.initChariotGunVariedMove(cleanEmpty(gunMoveColEat), 1, 1,true);
//车吃子 (行)
this.initChariotGunVariedMove(cleanEmpty(chariotMoveRowEat), 0, 0,true);
//车吃子 (列)
this.initChariotGunVariedMove(cleanEmpty(chariotMoveColEat), 1, 0,true);
/******炮伪攻击位置*******/
initGunFackEatMove(gunFackAttackRow,0);
initGunFackEatMove(gunFackAttackCol,1);
//炮隔多子能攻击到的位置
this.initChariotGunVariedMove(gunMoreRestAttackRow, 0, 2,true);
this.initChariotGunVariedMove(gunMoreRestAttackCol, 1, 2,true);
//生成置换表
// genBoardZobrist();
//生成基础分 和 棋子数量
//预生成所有位棋盘
preAllBitBoard();
}
private void preAllBitBoard() {
// 马 考虑别腿所能攻击到的位置
preBitBoardAttack(knightMove, horseLeg, KnightBitBoardOfAttackLimit, 0);
// 象 考虑别腿所能攻击到的位置
preBitBoardAttack(elephantMove, elephantLeg,
ElephanBitBoardOfAttackLimit, 1);
// 车炮不吃子的情况 行
preGunAndChariotBitBoardAttack(move_chariotGunRowNop,
MoveChariotOrGunBitBoardRow, 0);
// 车炮不吃子的情况 列
preGunAndChariotBitBoardAttack(move_chariotGunColNop,
MoveChariotOrGunBitBoardCol, 1);
// 车吃子情况 行
preGunAndChariotBitBoardAttack(chariotMoveRowEat,
ChariotBitBoardOfAttackRow, 0);
// 车吃子情况 列
preGunAndChariotBitBoardAttack(chariotMoveColEat,
ChariotBitBoardOfAttackCol, 1);
// 炮吃子情况 行
preGunAndChariotBitBoardAttack(gunMoveRowEat, GunBitBoardOfAttackRow, 0);
// 炮吃子情况 列
preGunAndChariotBitBoardAttack(gunMoveColEat, GunBitBoardOfAttackCol, 1);
// 生成将的位棋盘
preBitBoardKingMove(KingBitBoard);
// 生成士的位棋盘
preBitBoardGuardMove(GuardBitBoard);
// 卒将军的棋盘
preKingCheckedSoldierBitBoards(KingCheckedSoldierBitBoards);
//炮伪攻击位置
preGunAndChariotBitBoardAttack(gunFackAttackRow, GunBitBoardOfFakeAttackRow, 0);
preGunAndChariotBitBoardAttack(gunFackAttackCol, GunBitBoardOfFakeAttackCol, 1);
//车炮的机动性
preGunAndChariotMobility(MoveChariotOrGunBitBoardRow,ChariotAndGunMobilityRow);
preGunAndChariotMobility(MoveChariotOrGunBitBoardCol,ChariotAndGunMobilityCol);
// 炮隔多子吃子情况 行
preGunAndChariotBitBoardAttack(gunMoreRestAttackRow, GunBitBoardOfMoreRestAttackRow, 0);
// 炮隔多子吃子情况 列
preGunAndChariotBitBoardAttack(gunMoreRestAttackCol, GunBitBoardOfMoreRestAttackCol, 1);
//加载开局库
// loadBook();
}
private void preKingCheckedSoldierBitBoards(BitBoard[] bitBoard){
for(int i=0;i7) {
_tSoldierMoveTab=new int[]{+0x10,-0x01,+0x01};
}else{
_tSoldierMoveTab=new int[]{+0x10};
}
}else if(i==REDPLAYSIGN){
//红方兵以经过界
if(site/16<8){
_tSoldierMoveTab=new int[]{-0x10,-0x01,+0x01};
}else{
_tSoldierMoveTab=new int[]{-0x10};
}
}
for (int j = 0; j < _tSoldierMoveTab.length; j++) {
int _tSoldier = site + _tSoldierMoveTab[j];
if (isBoardTo255(_tSoldier)) {
int siteTo90=boardMap[site];
int _tSoldier90=boardMap[_tSoldier];
soldierMove[i][siteTo90][z] =_tSoldier90;
if(SoldiersBitBoard[i][siteTo90]==null){
SoldiersBitBoard[i][siteTo90]=new BitBoard();
}
//兵所能攻击到的位棋盘
SoldiersBitBoard[i][siteTo90].assignOr(MaskChesses[_tSoldier90]);
z++;
}
}
}
}
}
/**
*@author pengjiu
*@date:Sep 23, 2011 1:44:24 PM
* 功能:车炮吃子与不吃子
*@param moveEat 数组
*@param direction 方向
*@param handicapNum 中间间隔棋子数
*@param isEat 是否吃子 true false
*/
private void initChariotGunVariedMove(int [][][] moveEat,int direction,int handicapNum,boolean isEat){
int num=moveEat.length-1;
int sort=moveEat[0].length;
for(int i=0;i<=num;i++){
int site=1<0)){
if(isEat && j==site){ //吃子自己不能算进去
continue;
}
int isHandicap=0;
int eatIndex=0;
//向左(上)取值
for(int n=i+1;n<=num;n++){
int _tSite=1< 0){
if (isHandicap 0 ){
break;
}
}
}
isHandicap=0;
//向右(下)取值
for(int n=i-1;n>=0;n--){
int _tSite=1<0 ){
if(isHandicap0 ){
break;
}
}
}
}
}
}
}
/*
* 生成32位64位 唯一随机数
*/
// private void genBoardZobrist(){
// Random random = new Random();
// for(int i=0;i"+i);
// System.out.println(siteLegBit+" \n 现在位置"+i+siteLegBit.checkSumOfKnight()+" 棋子在->"+i);
// System.out.println("=====================================================");
// }else {
attackBoardBit[i][siteLegBit.checkSumOfKnight()]=siteAttBit;
//马的机动性
KnightMobility[i][siteLegBit.checkSumOfKnight()]=siteAttBit.Count();
// }
}else{ //象
// if(!attackBoardBit[i][siteLegBit.checkSumOfElephant()].isEmpty()){
// System.out.println("========================象=============================");
// System.out.println(attackBoardBit[i][siteLegBit.checkSumOfElephant()]+" \n 原位置"+i+attackBoardBit[i][siteLegBit.checkSumOfElephant()].checkSumOfElephant()+" 棋子在->"+i);
// System.out.println(siteLegBit+" \n 现在位置"+i+siteLegBit.checkSumOfElephant()+" 棋子在->"+i);
// System.out.println("=====================================================");
// }else {
attackBoardBit[i][siteLegBit.checkSumOfElephant()]=siteAttBit;
// }
}
}
}
}
//数组中去除重复数据
private int[] removeRepeatArray(int[] array){
int[] duplicate=new int[array.length];
for(int k=0;k0){
b++;
}
}
}
return r;
}
/**
*@author pengjiu
* index : 数组起始位置
* a : 数组
* num : 从数组后面拿取几位
* 一直拿取到只为0为止
*/
private String[] computCombination(int index,int[] a,int num){
String[] value=new String[10];
int b=0;
for(int i=index;i0) && j!=site){
boolean isEat=false;
boolean isHandicap=false;
int eatIndex=0;
//向左(上)取值
for(int n=i+1;n<=num;n++){
int _tSite=1< 0) {
if (isHandicap == false) {
isHandicap = true;
} else {
isEat = true;
}
} else if (isHandicap) {
if (direction == 0) {
moveEat[num - i][j][eatIndex++] = (num - n);
} else {
moveEat[num - i][j][eatIndex++] = (num - n) * 9;
}
}
}
isHandicap=false;
isEat=false;
//向右(下)取值
for(int n=i-1;n>=0;n--){
int _tSite=1<0 ){
if(isHandicap==false){
isHandicap=true;
}else{
isEat=true;
}
} else if (isHandicap) {
if(direction==0){
moveEat[num-i][j][eatIndex++]=(num-n);
}else{
moveEat[num-i][j][eatIndex++]=(num-n)*9;
}
}
}
}
}
}
}
public void preInCheck(){
}
private int[][][] cleanEmpty(int[][][] array){
for(int i=0;i
(2)评估;这里的评估是动态评估,起初可以给马,车,将等设置一个评估分数,但随着时间、位置等的改变对应的分数也需要发生改变,这里将就列出部分评估的代码吧。
package com.pj.chess.evaluate;
import static com.pj.chess.ChessConstant.*;
import com.pj.chess.BitBoard;
import com.pj.chess.ChessConstant;
import com.pj.chess.Tools;
import com.pj.chess.chessparam.ChessParam;
public abstract class EvaluateCompute {
protected ChessParam chessParam ;
public abstract int evaluate(int play);
public abstract int chessAttachScore(int chessRole, int chessSite);
public static int KINGSCORE=3000;
public static int CHARIOTSCORE=1300;
public static int KNIGHTSCORE=490;
public static int GUNSCORE=610;
public static int ELEPHANTSCORE=200;
public static int GUARDSCORE=200;
public static int SOLDIERSCORE=100;
//棋子基本分数
public static final int[] chessBaseScore=new int[]{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
KINGSCORE,CHARIOTSCORE,CHARIOTSCORE,KNIGHTSCORE,KNIGHTSCORE,GUNSCORE,GUNSCORE,ELEPHANTSCORE,ELEPHANTSCORE,GUARDSCORE,GUARDSCORE,SOLDIERSCORE,SOLDIERSCORE,SOLDIERSCORE,SOLDIERSCORE,SOLDIERSCORE,
KINGSCORE,CHARIOTSCORE,CHARIOTSCORE,KNIGHTSCORE,KNIGHTSCORE,GUNSCORE,GUNSCORE,ELEPHANTSCORE,ELEPHANTSCORE,GUARDSCORE,GUARDSCORE,SOLDIERSCORE,SOLDIERSCORE,SOLDIERSCORE,SOLDIERSCORE,SOLDIERSCORE
};
protected BitBoard getMainAttackChessesBitBoad(int play){
BitBoard bitBoard=new BitBoard(chessParam.getBitBoardByPlayRole(play,CHARIOT));
bitBoard=BitBoard.assignXorToNew(chessParam.getBitBoardByPlayRole(play,KNIGHT),bitBoard);
bitBoard=BitBoard.assignXorToNew(chessParam.getBitBoardByPlayRole(play,GUN),bitBoard);
return bitBoard;
}
protected BitBoard getDefenseChessesBitBoad(int play){
BitBoard bitBoard=new BitBoard(chessParam.getBitBoardByPlayRole(play,ELEPHANT));
bitBoard=BitBoard.assignXorToNew(chessParam.getBitBoardByPlayRole(play,GUARD),bitBoard);
bitBoard=BitBoard.assignXorToNew( chessParam.getBitBoardByPlayRole(play,SOLDIER),bitBoard);
return bitBoard;
}
protected int chessMobility(int chessRole, int srcSite,BitBoard bitBoard){
int mobility=0;
int row=chessParam.boardBitRow[boardRow[srcSite]];
int col=chessParam.boardBitCol[boardCol[srcSite]];
switch (chessRole) {
//车炮
case REDCHARIOT:
case BLACKCHARIOT:
case REDGUN:
case BLACKGUN:
mobility=ChariotAndGunMobilityRow[srcSite][row]+ChariotAndGunMobilityCol[srcSite][col];
break;
//马
case REDKNIGHT:
case BLACKKNIGHT:
BitBoard legBoard = BitBoard.assignAndToNew(KnightLegBitBoards[srcSite],chessParam.maskBoardChesses);
BitBoard knightAttackSite = KnightBitBoardOfAttackLimit[srcSite][legBoard.checkSumOfKnight()];
mobility=knightAttackSite.Count()-BitBoard.assignAndToNew(knightAttackSite,bitBoard).Count();
break;
case REDKING:
case BLACKKING:
BitBoard kingMove = BitBoard.assignAndToNew(KingBitBoard[srcSite],chessParam.maskBoardChesses);
kingMove.assignXor(KingBitBoard[srcSite]);
mobility= kingMove.Count();
break;
default :
System.out.println("没有这个棋子:"+srcSite);
}
return mobility;
}
protected BitBoard chessAllMove(int chessRole, int srcSite, int play) {
BitBoard bitBoard=null;
switch (chessRole) {
case REDCHARIOT:
case BLACKCHARIOT:
int row=chessParam.boardBitRow[boardRow[srcSite]];
int col=chessParam.boardBitCol[boardCol[srcSite]];
//取出行列能攻击到的位置
bitBoard=BitBoard.assignXorToNew(ChariotBitBoardOfAttackRow[srcSite][row], ChariotBitBoardOfAttackCol[srcSite][col]);
bitBoard.assignXor(BitBoard.assignXorToNew(MoveChariotOrGunBitBoardRow[srcSite][row], MoveChariotOrGunBitBoardCol[srcSite][col]));
break;
case REDKNIGHT:
case BLACKKNIGHT:
//取出被别马腿的位置
BitBoard legBoard = BitBoard.assignAndToNew(KnightLegBitBoards[srcSite],chessParam.maskBoardChesses);
//能走到的位置
bitBoard=new BitBoard(KnightBitBoardOfAttackLimit[srcSite][legBoard.checkSumOfKnight()]);
break;
case REDGUN:
case BLACKGUN:
row=chessParam.boardBitRow[boardRow[srcSite]];
col=chessParam.boardBitCol[boardCol[srcSite]];
//取出行列能攻击到的位置
bitBoard=BitBoard.assignXorToNew(GunBitBoardOfAttackRow[srcSite][row], GunBitBoardOfAttackCol[srcSite][col]);
//能走到的位置
// bitBoard=BitBoard.assignXorToNew(MoveChariotOrGunBitBoardRow[srcSite][row], MoveChariotOrGunBitBoardCol[srcSite][col]);
//炮伪攻击位置
bitBoard.assignXor(BitBoard.assignXorToNew(GunBitBoardOfFakeAttackRow[srcSite][row], GunBitBoardOfFakeAttackCol[srcSite][col]));
break;
case REDELEPHANT:
case BLACKELEPHANT:
//取出被塞象眼的位置
legBoard=BitBoard.assignAndToNew(ElephanLegBitBoards[srcSite],chessParam.maskBoardChesses);
bitBoard=new BitBoard(ElephanBitBoardOfAttackLimit[srcSite][legBoard.checkSumOfElephant()]);
break;
case REDKING:
case BLACKKING:
//将能走到的位置
bitBoard=new BitBoard(KingBitBoard[srcSite]);
break;
case REDGUARD:
case BLACKGUARD:
bitBoard=new BitBoard(GuardBitBoard[srcSite]);
break;
case REDSOLDIER:
case BLACKSOLDIER:
bitBoard=new BitBoard(SoldiersBitBoard[play][srcSite]);
break;
default :
System.out.println("没有这个棋子:"+srcSite);
}
return bitBoard;
}
/**
*@author pengjiu
* 功能:空头炮
*/
protected int exposedCannon(int play,int oppkingSite,int row,int col){
BitBoard bitBoard = BitBoard.assignXorToNew( ChariotBitBoardOfAttackRow[oppkingSite][row], ChariotBitBoardOfAttackCol[oppkingSite][col]);
bitBoard.assignAnd(chessParam.getBitBoardByPlayRole(play, ChessConstant.GUN));
if (!bitBoard.isEmpty()) {
return bitBoard.MSB(play) ;
}
return -1;
}
/**
*@author pengjiu
* 功能:沉底炮
*/
protected int bottomCannon(int play,int oppkingSite,int row,int col){
BitBoard bitBoard = BitBoard.assignXorToNew( GunBitBoardOfMoreRestAttackRow[oppkingSite][row], GunBitBoardOfMoreRestAttackCol[oppkingSite][col]);
bitBoard.assignAnd(chessParam.getBitBoardByPlayRole(play, ChessConstant.GUN));
if (!bitBoard.isEmpty()) {
return bitBoard.MSB(play) ;
}
return -1;
}
/**
*@author pengjiu
* 功能:隔子车
*/
protected int restChariot(int play,int oppkingSite,int row,int col){
BitBoard bitBoard = BitBoard.assignXorToNew( GunBitBoardOfAttackRow[oppkingSite][row], GunBitBoardOfAttackCol[oppkingSite][col]);
bitBoard.assignAnd(chessParam.getBitBoardByPlayRole(play, ChessConstant.CHARIOT));
if (!bitBoard.isEmpty()) {
return bitBoard.MSB(play) ;
}
return -1;
}
public void trimPartitionScore(int[][] partitionScore, int[][] attackPartition, int[][] defensePartition) {
attackPartition[REDPLAYSIGN][LEFTSITE] = partitionScore[REDPLAYSIGN][1];
attackPartition[REDPLAYSIGN][RIGHTSITE] = partitionScore[REDPLAYSIGN][2];
attackPartition[REDPLAYSIGN][MIDSITE] = partitionScore[REDPLAYSIGN][3];
defensePartition[REDPLAYSIGN][LEFTSITE] = partitionScore[REDPLAYSIGN][4];
defensePartition[REDPLAYSIGN][RIGHTSITE] = partitionScore[REDPLAYSIGN][5];
defensePartition[REDPLAYSIGN][MIDSITE] = partitionScore[REDPLAYSIGN][6];
attackPartition[BLACKPLAYSIGN][LEFTSITE] = partitionScore[BLACKPLAYSIGN][4];
attackPartition[BLACKPLAYSIGN][RIGHTSITE] = partitionScore[BLACKPLAYSIGN][5];
attackPartition[BLACKPLAYSIGN][MIDSITE] = partitionScore[BLACKPLAYSIGN][6];
defensePartition[BLACKPLAYSIGN][LEFTSITE] = partitionScore[BLACKPLAYSIGN][1];
defensePartition[BLACKPLAYSIGN][RIGHTSITE] = partitionScore[BLACKPLAYSIGN][2];
defensePartition[BLACKPLAYSIGN][MIDSITE] = partitionScore[BLACKPLAYSIGN][3];
}
//攻击区域分数
static final int[] attackChessPartitionScore=new int[]{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,4,4,4,4,4,4,3,3,3,3,2,2,2,2,2,
0,4,4,4,4,4,4,3,3,3,3,2,2,2,2,2
};
//防守区域分数
static final int[] defenseChessPartitionScore=new int[]{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,4,4,4,4,4,4,3,3,3,3,2,2,2,2,2,
0,4,4,4,4,4,4,3,3,3,3,2,2,2,2,2
};
/**
* 动态调整攻击区域分数
*/
int redElephantNum ,redGuardNum,blackElephantNum,blackGuardNum,redGun,redKnight,blackGun,blackKnight;
//单士或单象价值下降
private static final int[] guarAndElephantNumScore=new int[]{0,2,3};
//对手'士'数量决定炮与马的区域价值
private static final int[] gunNumScoreDependGuard =new int[]{2,3,4};
private static final int[] knightNumScoreDependGuard =new int[]{5,5,4};
public void dynamicCMPChessPartitionScore(){
redGuardNum = chessParam.getChessesNum(REDPLAYSIGN,ChessConstant.GUARD);
redElephantNum = chessParam.getChessesNum(REDPLAYSIGN,ChessConstant.ELEPHANT);
blackGuardNum = chessParam.getChessesNum(BLACKPLAYSIGN,ChessConstant.GUARD);
blackElephantNum = chessParam.getChessesNum(BLACKPLAYSIGN,ChessConstant.ELEPHANT);
//单士或单象价值下降
defenseChessPartitionScore[23]=defenseChessPartitionScore[24]=guarAndElephantNumScore[blackElephantNum];
defenseChessPartitionScore[25]=defenseChessPartitionScore[26]=guarAndElephantNumScore[blackGuardNum];
defenseChessPartitionScore[39]=defenseChessPartitionScore[40]=guarAndElephantNumScore[redElephantNum];
defenseChessPartitionScore[41]=defenseChessPartitionScore[42]=guarAndElephantNumScore[redGuardNum];
// blackGun=(redGuardNum*2)+1;
// blackKnight=(5-redGuardNum);
// redGun=(blackGuardNum*2)+1;
// redKnight=(5-blackGuardNum);
//动态改变炮与马的攻击价值
attackChessPartitionScore[21]=attackChessPartitionScore[22]=gunNumScoreDependGuard[redGuardNum];
attackChessPartitionScore[19]=attackChessPartitionScore[20]=knightNumScoreDependGuard[redGuardNum];
attackChessPartitionScore[37]=attackChessPartitionScore[38]=gunNumScoreDependGuard[blackGuardNum];
attackChessPartitionScore[35]=attackChessPartitionScore[36]=knightNumScoreDependGuard[blackGuardNum];
}
// public static final int KING=7; //王
// public static final int CHARIOT=6; //车
// public static final int KNIGHT=5; //马
// public static final int GUN=4; //炮
// public static final int ELEPHANT=3; //象
// public static final int GUARD=2; //士
// public static final int SOLDIER=1; //兵
/**区域分数
* @param site
* @param chess
* @param partitionScore
*/
public void compPartitionScore(int play,int site,int chess,int[] partitionScore){
int parSiteTemp=chessRolePartitionSite[chessRoles[chess]][site];
if(play==REDPLAYSIGN){ //红
switch(parSiteTemp){
case 1:
partitionScore[parSiteTemp]+=attackChessPartitionScore[chess];
break;
case 2:
partitionScore[parSiteTemp]+=attackChessPartitionScore[chess];
break;
case 3:
partitionScore[parSiteTemp]+=attackChessPartitionScore[chess];
break;
case 31:
partitionScore[3]+=attackChessPartitionScore[chess];
partitionScore[1]+=attackChessPartitionScore[chess];
break;
case 32:
partitionScore[3]+=attackChessPartitionScore[chess];
partitionScore[2]+=attackChessPartitionScore[chess];
break;
case 33:
partitionScore[3]+=attackChessPartitionScore[chess];
partitionScore[2]+=attackChessPartitionScore[chess];
partitionScore[1]+=attackChessPartitionScore[chess];
break;
case 4:
partitionScore[parSiteTemp]+=defenseChessPartitionScore[chess];
break;
case 5:
partitionScore[parSiteTemp]+=defenseChessPartitionScore[chess];
break;
case 6:
partitionScore[parSiteTemp]+=defenseChessPartitionScore[chess];
break;
case 64:
partitionScore[6]+=defenseChessPartitionScore[chess];
partitionScore[4]+=defenseChessPartitionScore[chess];
break;
case 65:
partitionScore[6]+=defenseChessPartitionScore[chess];
partitionScore[5]+=defenseChessPartitionScore[chess];
break;
case 66:
partitionScore[6]+=defenseChessPartitionScore[chess];
partitionScore[5]+=defenseChessPartitionScore[chess];
partitionScore[4]+=defenseChessPartitionScore[chess];
break;
}
}else{ //黑
switch(parSiteTemp){
case 1:
partitionScore[parSiteTemp]+=defenseChessPartitionScore[chess];
break;
case 2:
partitionScore[parSiteTemp]+=defenseChessPartitionScore[chess];
break;
case 3:
partitionScore[parSiteTemp]+=defenseChessPartitionScore[chess];
break;
case 31:
partitionScore[3]+=defenseChessPartitionScore[chess];
partitionScore[1]+=defenseChessPartitionScore[chess];
break;
case 32:
partitionScore[3]+=defenseChessPartitionScore[chess];
partitionScore[2]+=defenseChessPartitionScore[chess];
break;
case 33:
partitionScore[3]+=defenseChessPartitionScore[chess];
partitionScore[2]+=defenseChessPartitionScore[chess];
partitionScore[1]+=defenseChessPartitionScore[chess];
break;
case 4:
partitionScore[parSiteTemp]+=attackChessPartitionScore[chess];
break;
case 5:
partitionScore[parSiteTemp]+=attackChessPartitionScore[chess];
break;
case 6:
partitionScore[parSiteTemp]+=attackChessPartitionScore[chess];
break;
case 64:
partitionScore[6]+=attackChessPartitionScore[chess];
partitionScore[4]+=attackChessPartitionScore[chess];
break;
case 65:
partitionScore[6]+=attackChessPartitionScore[chess];
partitionScore[5]+=attackChessPartitionScore[chess];
break;
case 66:
partitionScore[6]+=attackChessPartitionScore[chess];
partitionScore[5]+=attackChessPartitionScore[chess];
partitionScore[4]+=attackChessPartitionScore[chess];
break;
}
}
}
static int[] ChariotPartitionSite=new int[]{ //车
1 ,1 ,1 ,31 ,3 , 32,2 ,2 ,2
,1 ,1 ,1 ,31 ,33, 32,2 ,2 ,2
,1 ,1 ,1 ,31 ,33, 32,2 ,2 ,2
,0 ,0 ,0 ,3 ,3 , 3 ,0 ,0 ,0
,0 ,0 ,0 ,3 ,3 , 3 ,0 ,0 ,0
,0 ,0 ,0 ,6 ,6 ,6 ,0 ,0 ,0
,0 ,0 ,0 ,6 ,6 ,6 ,0 ,0 ,0
,4 ,4 ,4 ,64,66,65,5 ,5 ,5
,4 ,4 ,4 ,64,66,65,5 ,5 ,5
,4 ,4 ,4 ,64,6 ,65,5 ,5 ,5
};
static int[] KnightPartitionSite=new int[]{ //马
1 ,1 ,1 ,0 ,0 ,0 ,2 ,2 ,2
,1 ,1 ,1 ,31,33 ,32,2 ,2 ,2
,1 ,1 ,1 ,31,33 ,32,2 ,2 ,2
,0 ,1 ,1 ,31,33 ,32,2 ,2 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,4 ,4 ,64,66,65 ,5 ,5 ,0
,4 ,4 ,4 ,64,66,65,5 ,5 ,5
,4 ,4 ,4 ,64,66,65,5 ,5 ,5
,4 ,4 ,4 ,0 ,0 ,0 ,5 ,5 ,5
};
static int[] GunPartitionSite=new int[]{ //炮
1 ,1 ,1 ,0 ,0 ,0 ,2 ,2 ,2
,1 ,1 ,1 ,0 ,0 ,0 ,2 ,2 ,2
,1 ,1 ,1 ,0 ,3 ,0 ,2 ,2 ,2
,0 ,0 ,0 ,32,33,32,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,64 ,66 ,65,0 ,0 ,0
,4 ,4 ,4 ,0 ,6 ,0 ,5 ,5 ,5
,4 ,4 ,4 ,0 ,0 ,0 ,5 ,5 ,5
,4 ,4 ,4 ,0 ,0 ,0 ,5 ,5 ,5
};
static int[] SoldierPartitionSite=new int[]{ //卒
0 ,0 ,0 ,3 ,3 ,3 ,0 ,0 ,0
,0 ,0 ,0 ,3 ,3 ,3 ,0 ,0 ,0
,0 ,0 ,0 ,3 ,3 ,3 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,6 ,6 ,6 ,0 ,0 ,0
,0 ,0 ,0 ,6 ,6 ,6 ,0 ,0 ,0
,0 ,0 ,0 ,6 ,6 ,6 ,0 ,0 ,0
};
static int[] DefensePartitionSite=new int[]{ //象士
1 ,1 ,1 ,31 ,33,32 ,2 ,2 ,2
,1 ,1 ,1 ,31 ,33,32 ,2 ,2 ,2
,1 ,1 ,1 ,31 ,33,32 ,2 ,2 ,2
,1 ,1 ,1 ,31 ,3 ,32 ,2 ,2 ,2
,1 ,1 ,1 ,31 ,3 ,32 ,2 ,2 ,2
,4 ,4 ,4 ,64 ,6 ,65 ,5 ,5 ,5
,4 ,4 ,4 ,64 ,6 ,65 ,5 ,5 ,5
,4 ,4 ,4 ,64 ,66 ,65 ,5 ,5 ,5
,4 ,4 ,4 ,64 ,66 ,65 ,5 ,5 ,5
,4 ,4 , 4 ,64 ,66 ,65 ,5 ,5 ,5
};
static int[]KingPartitionSite=new int[]{ //王
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
};
static final int[][] chessRolePartitionSite=new int[][]{
{},SoldierPartitionSite,DefensePartitionSite,DefensePartitionSite,GunPartitionSite,KnightPartitionSite,ChariotPartitionSite,KingPartitionSite
,SoldierPartitionSite,DefensePartitionSite,DefensePartitionSite,GunPartitionSite,KnightPartitionSite,ChariotPartitionSite,KingPartitionSite
};
protected final static BitBoard[][] AttackDirection= new BitBoard[2][3];
protected final static BitBoard[][] DefenseDirection= new BitBoard[2][3];
protected final static int LEFTSITE=0,RIGHTSITE=1,MIDSITE=2,OTHERSITE=3;
static{
int[] AttackRedLeftSite=new int[]{
1 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,0
,1 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,0
,1 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
};
int[] AttackRightSite=new int[]{
0 ,0 ,0 ,0 ,2 ,2 ,2 ,2 ,2
,0 ,0 ,0 ,0 ,2 ,2 ,2 ,2 ,2
,0 ,0 ,0 ,0 ,2 ,2 ,2 ,2 ,2
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
};
int[] AtackRedMidSite=new int[]{
0 ,0 ,0 ,3 ,3 ,3 ,0 ,0 ,0
,0 ,0 ,0 ,3 ,3 ,3 ,0 ,0 ,0
,0 ,0 ,0 ,3 ,3 ,3 ,0 ,0 ,0
,0 ,0 ,0 ,3 ,3 ,3 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
};
int[] AttackBlackLeftSite=Tools.exchange(AttackRedLeftSite);
int[] AttackBlackRightSite=Tools.exchange(AttackRightSite);
int[] AttackBlackMidSite=Tools.exchange(AtackRedMidSite);
BitBoard AttackBlackLeftBit = new BitBoard(AttackBlackLeftSite);
BitBoard AttackBlackRightBit = new BitBoard(AttackBlackRightSite);
BitBoard AttackBlackMidBit = new BitBoard(AttackBlackMidSite);
BitBoard AttackRedLeftBit = new BitBoard(AttackRedLeftSite);
BitBoard AttackRedRightBit = new BitBoard(AttackRightSite);
BitBoard AttackRedMidBit = new BitBoard(AtackRedMidSite);
AttackDirection[REDPLAYSIGN][LEFTSITE]=AttackRedLeftBit;
AttackDirection[REDPLAYSIGN][RIGHTSITE]=AttackRedRightBit;
AttackDirection[REDPLAYSIGN][MIDSITE]=AttackRedMidBit;
AttackDirection[BLACKPLAYSIGN][LEFTSITE]=AttackBlackLeftBit;
AttackDirection[BLACKPLAYSIGN][RIGHTSITE]=AttackBlackRightBit;
AttackDirection[BLACKPLAYSIGN][MIDSITE]=AttackBlackMidBit;
DefenseDirection[BLACKPLAYSIGN][LEFTSITE]=AttackRedLeftBit;
DefenseDirection[BLACKPLAYSIGN][RIGHTSITE]=AttackRedRightBit;
DefenseDirection[BLACKPLAYSIGN][MIDSITE]=AttackRedMidBit;
DefenseDirection[REDPLAYSIGN][LEFTSITE]=AttackBlackLeftBit;
DefenseDirection[REDPLAYSIGN][RIGHTSITE]=AttackBlackRightBit;
DefenseDirection[REDPLAYSIGN][MIDSITE]=AttackBlackMidBit;
}
}
由于这个项目篇幅较大,放上来极不方便,故有需要的同学可以叫我微信:18476275715(永久有效)