您的位置:首页 > 其它

中国象棋

2016-03-20 16:54 323 查看
最近做的一个中国象棋程序,包含了一个简单的AI,头文件如下:
#ifndef CHINESECHESS_H
#define CHINESECHESS_H
//棋盘范围
#define START_ROW      3
#define END_ROW        12
#define START_COLUMN   3
#define END_COLUMN     11

//棋子编号
#define CHESSMAN_KING       1
#define CHESSMAN_ADVISOR    2
#define CHESSMAN_BISHOP     3
#define CHESSMAN_KNIGHT     4
#define CHESSMAN_ROOK       5
#define CHESSMAN_CANNON     6
#define CHESSMAN_PAWN       7

#define MAX_MOVES           134     //生成的最大走法数
#define LIMIT_DEPTH         32      //搜索深度
#define MATE_VALUE          10000   //最高分值
#define WIN_VALUE           9900    //胜负分界分值
#define ADVANCED_VALUE      3       //先走加成分值

const int chessBoardStart[256] = {
//0   1   2   3   4   5   6   7   8   9  10  11  12
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,//1
0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,//2
0,  0,  0, 12, 11, 10,  9,  8,  9, 10, 11, 12,  0,  0,  0,  0,//3
0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,//4
0,  0,  0,  0, 13,  0,  0,  0,  0,  0, 13,  0,  0,  0,  0,  0,//5
0,  0,  0, 14,  0, 14,  0, 14,  0, 14,  0, 14,  0,  0,  0,  0,//6
0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,//7
0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,//8
0,  0,  0,  7,  0,  7,  0,  7,  0,  7,  0,  7,  0,  0,  0,  0,//9
0,  0,  0,  0,  6,  0,  0,  0,  0,  0,  6,  0,  0,  0,  0,  0,//10
0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,//11
0,  0,  0,  5,  4,  3,  2,  1,  2,  3,  4,  5,  0,  0,  0,  0,//12
0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,//13
0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,//15
0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 //16
};

const char IN_BOARD[256] = {
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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 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
};

const char IN_FORT[256] = {
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, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 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的距离
* -34 -33 -32 -31 -30
* -18 -17 -16 -15 -14
*  -2  -1   0   1   2
*  14  15  16  17  18
*  30  31  32  33  34
* 那么,设: 将 = 1, 士 = 2, 象 = 3, 马 = 4,则:
*   3  4  0  4  3
*   4  2  1  2  4
*   0  1  0  1  0
*   4  2  1  2  4
*   3  4  0  4  3
* 计算时,当前步长 = des - src ,
* 由chessboard定义可知当前步长的取值范围[-255, 255]
* 判断走法是否合法时, LEGAL_SPAN[当前步长 + 中心点在数组中的偏移] == 当前棋子
* 为了防止数组访问越界,数组大小必须大于等于步长取值范围,令中心点在数组中的偏移为256,则数组应该为如下所示
*/

const char LEGAL_SPAN[512] = {
//0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15
0, 0, 0, 0, 0, 0, 0, 0, //7
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //23
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //39
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //55
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //71
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //87
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //103
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //119
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //135
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //151
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //167
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //183
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //199
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //215
0, 0, 0, 0, 0, 0, 3, 4, 0, 4, 3, 0, 0, 0, 0, 0, //231
0, 0, 0, 0, 0, 0, 4, 2, 1, 2, 4, 0, 0, 0, 0, 0, //247
0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, //263
0, 0, 0, 0, 0, 0, 4, 2, 1, 2, 4, 0, 0, 0, 0, 0, //279
0, 0, 0, 0, 0, 0, 3, 4, 0, 4, 3, 0, 0, 0, 0, 0, //295
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //311
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //327
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //343
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //359
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //375
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //391
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //407
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //423
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //439
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //455
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //471
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //487
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //503
0, 0, 0, 0, 0, 0, 0, 0                          //511

};

/*计算马腿的位置,马的走法如下:
*   0 -33   0  -31     0
* -18   0   0    0   -14
*   0   0   0    0     0
*  14   0   0    0    18
*   0  31   0   33     0
* 对应的马腿位置如下:
*  0 -16 0 -16 0
* -1  0  0  0  1
*  0  0  0  0  0
* -1  0  0  0  1
*  0  16 0  16 0
* 计算时,当前步长 = des - src ,
* 由chessboard定义可知当前步长的取值范围[-255, 255]
* 计算马腿时, 马腿 = KNIGHT_HINDER[中心点偏移 + 当前步长] + src
* 为了防止数组访问越界,数组大小必须大于等于步长取值范围,令中心点在数组中的偏移为256,则数组应该为如下所示
*/
const char KNIGHT_HINDER[512] = {
//0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15
0, 0, 0, 0, 0, 0, 0, 0, //7
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //23
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //39
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //55
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //71
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //87
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //103
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //119
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //135
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //151
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //167
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //183
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //199
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //215
0, 0, 0, 0, 0, 0, 0,-16,0,-16,0, 0, 0, 0, 0, 0, //231
0, 0, 0, 0, 0, 0,-1, 0, 0, 0, 1, 0, 0, 0, 0, 0, //247
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //263
0, 0, 0, 0, 0, 0,-1, 0, 0, 0, 1, 0, 0, 0, 0, 0, //279
0, 0, 0, 0, 0, 0, 0,16, 0,16, 0, 0, 0, 0, 0, 0, //295
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //311
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //327
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //343
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //359
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //375
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //391
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //407
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //423
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //439
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //455
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4000
0, 0, 0, 0, 0, //471
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //487
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //503
0, 0, 0, 0, 0, 0, 0, 0                          //511
};

//各棋子步长,用于生成走法

const char KING_STEP[4] = {-16, -1, 1, 16};
const char ADVISOR_STEP[4] = {-17, -15, 15, 17};
const char BISHOP_STEP[4] = {-34, -30, 30, 34};
/*步长KNIGHT_STEP[i][j]马腿为KING_STEP[i]
* -34 -33 -32 -31 -30
* -18 -17 -16 -15 -14
*  -2  -1   0   1   2
*  14  15  16  17  18
*  30  31  32  33  34
*/
const char KNIGHT_STEP[4][2] = {{-33, -31}, {-18, 14}, {-14, 18}, {31, 33}};
//计算被马将军时马的相对位置,马腿对应ADVISOR_STEP
const char KNIGHT_CHECK[4][2] = {{-33, -18}, {-31, -14}, {14, 31}, {18, 33}};

// 子力位置价值表
const char valueOfLoc[7][256] = {
{ // 帅(将)
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,  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,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,
0,  0,  0,  0,  0,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,
0,  0,  0,  0,  0,  0, 11, 15, 11,  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,  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,  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, 20,  0, 20,  0,  0,  0,  0,  0,  0,  0,
0,  0,  0,  0,  0,  0,  0, 23,  0,  0,  0,  0,  0,  0,  0,  0,
0,  0,  0,  0,  0,  0, 20,  0, 20,  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,  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,  0,  0,  0,
0,  0,  0,  0,  0, 20,  0,  0,  0, 20,  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, 18,  0,  0,  0, 23,  0,  0,  0, 18,  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, 20,  0,  0,  0, 20,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
0,  0,  0, 90, 90, 90, 96, 90, 96, 90, 90, 90,  0,  0,  0,  0,
0,  0,  0, 90, 96,103, 97, 94, 97,103, 96, 90,  0,  0,  0,  0,
0,  0,  0, 92, 98, 99,103, 99,103, 99, 98, 92,  0,  0,  0,  0,
0,  0,  0, 93,108,100,107,100,107,100,108, 93,  0,  0,  0,  0,
0,  0,  0, 90,100, 99,103,104,103, 99,100, 90,  0,  0,  0,  0,
0,  0,  0, 90, 98,101,102,103,102,101, 98, 90,  0,  0,  0,  0,
0,  0,  0, 92, 94, 98, 95, 98, 95, 98, 94, 92,  0,  0,  0,  0,
0,  0,  0, 93, 92, 94, 95, 92, 95, 94, 92, 93,  0,  0,  0,  0,
0,  0,  0, 85, 90, 92, 93, 78, 93, 92, 90, 85,  0,  0,  0,  0,
0,  0,  0, 88, 85, 90, 88, 90, 88, 90, 85, 88,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
0,  0,  0,206,208,207,213,214,213,207,208,206,  0,  0,  0,  0,
0,  0,  0,206,212,209,216,233,216,209,212,206,  0,  0,  0,  0,
0,  0,  0,206,208,207,214,216,214,207,208,206,  0,  0,  0,  0,
0,  0,  0,206,213,213,216,216,216,213,213,206,  0,  0,  0,  0,
0,  0,  0,208,211,211,214,215,214,211,211,208,  0,  0,  0,  0,
0,  0,  0,208,212,212,214,215,214,212,212,208,  0,  0,  0,  0,
0,  0,  0,204,209,204,212,214,212,204,209,204,  0,  0,  0,  0,
0,  0,  0,198,208,204,212,212,212,204,208,198,  0,  0,  0,  0,
0,  0,  0,200,208,206,212,200,212,206,208,200,  0,  0,  0,  0,
0,  0,  0,194,206,204,212,200,212,204,206,194,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
0,  0,  0,100,100, 96, 91, 90, 91, 96,100,100,  0,  0,  0,  0,
0,  0,  0, 98, 98, 96, 92, 89, 92, 96, 98, 98,  0,  0,  0,  0,
0,  0,  0, 97, 97, 96, 91, 92, 91, 96, 97, 97,  0,  0,  0,  0,
0,  0,  0, 96, 99, 99, 98,100, 98, 99, 99, 96,  0,  0,  0,  0,
0,  0,  0, 96, 96, 96, 96,100, 96, 96, 96, 96,  0,  0,  0,  0,
0,  0,  0, 95, 96, 99, 96,100, 96, 99, 96, 95,  0,  0,  0,  0,
0,  0,  0, 96, 96, 96, 96, 96, 96, 96, 96, 96,  0,  0,  0,  0,
0,  0,  0, 97, 96,100, 99,101, 99,100, 96, 97,  0,  0,  0,  0,
0,  0,  0, 96, 97, 98, 98, 98, 98, 98, 97, 96,  0,  0,  0,  0,
0,  0,  0, 96, 96, 97, 99, 99, 99, 97, 96, 96,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
0,  0,  0,  9,  9,  9, 11, 13, 11,  9,  9,  9,  0,  0,  0,  0,
0,  0,  0, 19, 24, 34, 42, 44, 42, 34, 24, 19,  0,  0,  0,  0,
0,  0,  0, 19, 24, 32, 37, 37, 37, 32, 24, 19,  0,  0,  0,  0,
0,  0,  0, 19, 23, 27, 29, 30, 29, 27, 23, 19,  0,  0,  0,  0,
0,  0,  0, 14, 18, 20, 27, 29, 27, 20, 18, 14,  0,  0,  0,  0,
0,  0,  0,  7,  0, 13,  0, 16,  0, 13,  0,  7,  0,  0,  0,  0,
0,  0,  0,  7,  0,  7,  0, 15,  0,  7,  0,  7,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
}
};

class ChineseChess
{
public:
ChineseChess();
int chessBoard[256];
int playSide;

int movStack[1024];
int movStackTop;

int redValue, blackValue;
int distance;

//象棋逻辑部分
inline bool isInFort(int loc) { return IN_FORT[loc]; }
inline bool isInBoard(int loc) { return IN_BOARD[loc]; }

inline bool isKingSpan(int src, int des) {
return LEGAL_SPAN[des - src + 256] == CHESSMAN_KING;
}
inline bool isAdvisorSpan(int src, int des) {
return LEGAL_SPAN[des - src + 256] == CHESSMAN_ADVISOR;
}
inline bool isBishopSpan(int src, int des) {
return LEGAL_SPAN[des - src + 256] == CHESSMAN_BISHOP;
}
inline bool isKnightSpan(int src, int des) {
return LEGAL_SPAN[des - src + 256] == CHESSMAN_KNIGHT;
}

inline int getBishopHinder(int src, int des) {
return (src + des) >> 1;
}
inline int getKnightHinder(int src, int des) {
return src + KNIGHT_HINDER[des - src + 256];
}

//红方棋子表示为1~7,二进制0001~0111,返回0,黑方返回1
inline int getSideByChessman(int chessMan) { return ((chessMan >> 3) > 0 ? 1 : 0); }
//在棋盘数组中,0~127(0~111 1111)为黑方,返回1,128~255为红方,返回0
inline int getSideByLoc(int loc) { return ((loc >> 7) > 0 ? 0 : 1); }

/*一个位置用8位表示
* 高四位代表在数组中的行
* 低四位代表在数组中的列
*/
//获得格子的横纵坐标,根据横纵坐标得到格子
inline int getRow(int loc) { return loc >> 4; }
inline int getColumn(int loc) { return loc & 0x0F; }
inline int getLoc(int row, int col) { return (row << 4) + col; }

/*一次移动用一个int表示,
* 5到8位表示移动的棋子
* 9到16位表示被杀的棋子
* 17到24位表示移动的起始位置
* 25到32位表示移动的目标位置
*/
inline int getSub(int mov) { return mov >> 24 & 0xFF; }
inline int getObj(int mov) { return mov >> 16 & 0xFF; }
inline int getSrc(int mov) { return mov >> 8  & 0xFF; }
inline int getDes(int mov) { return mov & 0xFF; }
int  getMov(int src, int des);

inline changeSide() { playSide = 1 - playSide; }
inline getEvaluate() {
return (playSide == 0 ? redValue - blackValue : blackValue - redValue);
}

void initialChessBoard();

void addChessMan(int chessMan, int loc);
void deleteChessMan(int chessMan, int loc);
void makeMove(int mov);
void undoMove(int mov);

int searchedMov;
int generateMoves(int *mvs);
bool isLegal(int mov);
bool isChecked();
bool isMate();
int alphaBeta(int alpha, int beta, int depth);
int minMax(int depth);
void search();
};

#endif // CHINESECHESS_H
.cpp文件如下:
<pre style="margin-top: 0px; margin-bottom: 0px;"><span style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"chinesechess.h"</span>
#include <cstring>
#include <QDebug>
ChineseChess::ChineseChess()
{
initialChessBoard();
/*for (int i = 0; i != 16; ++i) {
qDebug()<<chessBoard[i * 16]<<chessBoard[i * 16 + 1]<<chessBoard[i * 16 + 2]<<chessBoard[i * 16 + 3]<<chessBoard[i * 16 + 4]<<chessBoard[i * 16 + 5]<<chessBoard[i * 16 + 6]<<chessBoard[i * 16 + 7]<<chessBoard[i * 16 + 8]<<chessBoard[i * 16 + 9]<<chessBoard[i * 16 + 10]<<chessBoard[i * 16 + 11]<<chessBoard[i * 16 + 12]<<chessBoard[i * 16 + 13]<<chessBoard[i * 16 + 14]<<chessBoard[i * 16 + 15];
}*/
}
void ChineseChess::initialChessBoard()
{
playSide = 0;
redValue = blackValue = 0;
distance = 0;
memcpy(chessBoard, chessBoardStart, sizeof(chessBoard));
qDebug()<<"start caculate value! sizeof(chessBoard)="<<sizeof(chessBoard);
for (int i = 0; i != 256; ++i) {
//qDebug()<<chessBoardStart[i];
if (chessBoardStart[i] != 0) {
if (chessBoardStart[i] < 8) {
redValue += (unsigned char)valueOfLoc[chessBoardStart[i] - 1][i];
qDebug()<<"chessman="<<chessBoardStart[i]<<"value="<<valueOfLoc[chessBoardStart[i] - 1][i];
} else {
blackValue += (unsigned char)valueOfLoc[chessBoardStart[i] - 8][254 - i];
}
}
}
qDebug()<<"初始局面:redValue = "<<redValue <<"blackValue="<< blackValue;
}
int ChineseChess::getMov(int src, int des)
{
int mov = 0;
mov |= des;
mov |= src << 8;
mov |= chessBoard[des] << 16;
mov |= chessBoard[src] << 24;
return mov;
}
void ChineseChess::addChessMan(int chessMan, int loc)
{
if (chessMan < 8) {
redValue += (unsigned char)valueOfLoc[chessMan - 1][loc];
} else {
blackValue += (unsigned char)valueOfLoc[chessMan - 8][254 - loc];
}
chessBoard[loc] = chessMan;
}
void ChineseChess::deleteChessMan(int chessMan, int loc)
{
if (chessMan < 8) {
redValue -= (unsigned char)valueOfLoc[chessMan - 1][loc];
} else {
blackValue -= (unsigned char)valueOfLoc[chessMan - 8][254 - loc];
}
chessBoard[loc] = 0;
}
void ChineseChess::makeMove(int mov)
{
int sub = getSub(mov);
int obj = getObj(mov);
int src = getSrc(mov);
int des = getDes(mov);
if (obj != 0) {
deleteChessMan(obj, des);
}
deleteChessMan(sub, src);
addChessMan(sub, des);
changeSide();
distance++;
}
void ChineseChess::undoMove(int mov)
{
int sub = getSub(mov);
int obj = getObj(mov);
int src = getSrc(mov);
int des = getDes(mov);
deleteChessMan(sub, des);
addChessMan(sub, src);
if (obj != 0) {
addChessMan(obj, des);
}
changeSide();
distance--;
}
int ChineseChess::generateMoves(int *mvs)
{
int legalMovLength = 0;
int des, mov, j;
int chessMan;
for (int src = 0; src != 256; ++src) {
chessMan = chessBoard[src];
if (chessMan != 0 && getSideByChessman(chessMan) == playSide) {
switch(chessMan)
{
//将:目标位置在九宫中,目标位置没有棋子或是对方棋子
case CHESSMAN_KING:
case CHESSMAN_KING + 7:
// qDebug()<<"king";
for (j = 0; j != 4; ++j) {
des = src + KING_STEP[j];
if (isInFort(des) &&
(chessBoard[des] == 0 || getSideByChessman(chessBoard[des]) != playSide)) {
mov = getMov(src, des);
if (isLegal(mov)) {
mvs[legalMovLength++] = mov;
}
}
}
break;
//士:目标位置在九宫中,目标位置没有棋子或是对方棋子
case CHESSMAN_ADVISOR:
case CHESSMAN_ADVISOR + 7:
//qDebug()<<"ADVISOR";
for (j = 0; j != 4; ++j) {
des = src + ADVISOR_STEP[j];
if (isInFort(des) &&
(chessBoard[des] == 0 ||
getSideByChessman(chessBoard[des]) != playSide)) {
mov = getMov(src, des);
if (isLegal(mov)) {
mvs[legalMovLength++] = mov;
}
}
}
break;
//象:目标位置在己方领地,目标位置没有棋子或是对方棋子, 象眼没有棋子
case CHESSMAN_BISHOP:
case CHESSMAN_BISHOP + 7:
//qDebug()<<"BISHOP";
for (j = 0; j != 4; ++j) {
des = src + BISHOP_STEP[j];
if (getSideByLoc(des) == getSideByChessman(chessBoard[src]) &&
(chessBoard[des] == 0 || getSideByChessman(chessBoard[des]) != playSide) &&
chessBoard[getBishopHinder(src, des)] == 0) {
mov = getMov(src, des);
if (isLegal(mov)) {
mvs[legalMovLength++] = mov;
}
}
}
break;
//马:目标位置没有棋子或是对方棋子, 马腿没有棋子
case CHESSMAN_KNIGHT:
case CHESSMAN_KNIGHT + 7:
// qDebug()<<"KNIGHT";
for (j = 0; j != 4; ++j) {
for (int k = 0; k != 2; ++k) {
des = src + KNIGHT_STEP[j][k];
if ((chessBoard[des] == 0 || getSideByChessman(chessBoard[des]) != playSide) &&
chessBoard[KING_STEP[j]] == 0) {
    mov = getMov(src, des);
    if (isLegal(mov)) {
    mvs[legalMovLength++] = mov;
}
}
}
}
break;
//车:目标位置没棋子或是对方棋子
case CHESSMAN_ROOK:
case CHESSMAN_ROOK + 7:
//qDebug()<<"rook";
for (j = 0; j != 4; ++j) {
int step = KING_STEP[j];
//往每个方向探索
des = src + step;
while (isInBoard(des)) {
//如果目标位置没有棋子
if (chessBoard[des] == 0) {
    mov = getMov(src, des);
mvs[legalMovLength++] = mov;
} else {
            break;
}
des += step;
}
//如果目标位置有棋子,检查合法性加入走法,停止该方向搜索
if (isInBoard(des)) {
if (getSideByChessman(chessBoard[des]) != playSide) {
    mov = getMov(src, des);
mvs[legalMovLength++] = mov;
}
}
}//for四个方向
break;
//炮:,或者
case CHESSMAN_CANNON:
case CHESSMAN_CANNON + 7:
// qDebug()<<"CANNON";
for (j = 0; j != 4; ++j) {
int step = KING_STEP[j];
des = src + step;
//目标位置没棋子
while (isInBoard(des)) {
if (chessBoard[des] == 0) {
    mov = getMov(src, des);
mvs[legalMovLength++] = mov;
} else {
            break;
}
des += step;
}
des += step;
//隔了一个棋子,目标是对方棋子
while (isInBoard(des)) {
if (chessBoard[des] != 0) {
if ( getSideByChessman(chessBoard[des]) != playSide) {
        mov = getMov(src, des);
    mvs[legalMovLength++] = mov;
}
            break;
}
des += step;
}
}
break;
//兵:往前走,目标没棋子或目标是对方棋子
case CHESSMAN_PAWN:
case CHESSMAN_PAWN + 7:
j = (getSideByChessman(chessBoard[src]) ? 16 : -16);
des = src + j;
if (isInBoard(des)) {
if (chessBoard[des] == 0 ||
(chessBoard[des] != 0 && getSideByChessman(chessBoard[des]) != playSide)) {
mov = getMov(src, des);
mvs[legalMovLength++] = mov;
}
}
if (getSideByChessman(chessBoard[src]) != getSideByLoc(src)) {
des = src + 1;
if (isInBoard(des)) {
    if (chessBoard[des] == 0 ||
    (chessBoard[des] != 0 && getSideByChessman(chessBoard[des]) != playSide)) {
    mov = getMov(src, des);
mvs[legalMovLength++] = mov;
}
}
des = src - 1;
if (isInBoard(des)) {
    if (chessBoard[des] == 0 ||
    (chessBoard[des] != 0 && getSideByChessman(chessBoard[des]) != playSide)) {
    mov = getMov(src, des);
mvs[legalMovLength++] = mov;
}
}
}
break;
}//switch
}//if是己方棋子
}//for遍历棋盘
return legalMovLength;
}
bool ChineseChess::isLegal(int mov)
{
int sub = getSub(mov);
int obj = getObj(mov);
int src = getSrc(mov);
int des = getDes(mov);
int i = 0, step = 0;
//1.如果目标位置不在棋盘
if (!isInBoard(des)) {
return false;
}
//2.如果移动棋子和被吃棋子是同一方
if (obj != 0 && getSideByChessman(sub) == getSideByChessman(obj)) {
return false;
}
//3.根据棋子类型做出判断
switch (sub) {
//将的合法条件:目标位置在九宫,移动距离合法
case CHESSMAN_KING:
case CHESSMAN_KING + 7:
return (isInFort(des) && isKingSpan(src, des));
//士的合法条件:目标位置在九宫,移动距离合法
case CHESSMAN_ADVISOR:
case CHESSMAN_ADVISOR + 7:
return (isInFort(des) && isAdvisorSpan(src, des));
//象的合法条件:棋子在己方地盘,移动距离合法,象眼没被堵
case CHESSMAN_BISHOP:
case CHESSMAN_BISHOP + 7:
return (getSideByChessman(sub) == getSideByLoc(des) &&
isBishopSpan(src, des) && chessBoard[getBishopHinder(src, des)] == 0);
//马的合法条件:马腿没有棋子,移动距离合法
case CHESSMAN_KNIGHT:
case CHESSMAN_KNIGHT + 7:
return (isKnightSpan(src, des) && chessBoard[getKnightHinder(src, des)] == 0);
//炮和车的合法条件
case CHESSMAN_ROOK:
case CHESSMAN_ROOK + 7:
case CHESSMAN_CANNON:
case CHESSMAN_CANNON + 7:
if (getRow(src) == getRow(des)) {
step = (src < des) ? 1 : -1;
} else if(getColumn(src) == getColumn(des)) {
step = (src < des) ? 16 :-16;
} else {
return false;
}
i = src + step;
while (i != des && chessBoard[i] == 0) {
i += step;
}
/*如果中间没棋子
* 1.目标位置没有棋子,则炮和车都合法
* 2.有棋子的话只有车合法
*/
if(i == des) {
return (chessBoard[des] == 0 || sub == CHESSMAN_ROOK || sub - 7 == CHESSMAN_ROOK);
//若src和des中间有棋子,则仅当des位置有棋子,sub为炮, 第一个中间棋子和目标位置之间没有棋子才合法
} else if (chessBoard[des] != 0 && (sub == CHESSMAN_CANNON || sub - 7 == CHESSMAN_CANNON)) {
i += step;
    while (i != des && chessBoard[i] == 0) {
i +=step;
}
return i == des;
} else {
return false;
}
//兵的合法条件:1.如果左右移动的话必须过河
//           2.否则必须往前移动
case CHESSMAN_PAWN:
case CHESSMAN_PAWN + 7:
if(getSideByChessman(sub) != getSideByLoc(src) && (des - src == 1 || des - src == -1)) {
return true;
}
i = (getSideByChessman(sub) ? 16: -16);
return des - src == i;
default:
return false;
}//switch
}
bool ChineseChess::isChecked()
{
int des;
int king = playSide * 7 + 1;
int kingLoc = 0;
while (kingLoc != 256 && chessBoard[kingLoc] != king) {
++kingLoc;
}
//1.是否被兵将军:兵在king左右,或者兵的前方是king
for (int i = -1; i != 3; i += 2) {
des = kingLoc + i;
if (chessBoard[des] == (!playSide) * 7 + CHESSMAN_PAWN) {
return true;
}
}
int oppForward = playSide ? -16 : 16;
des = kingLoc - oppForward;
if (chessBoard[des] == (!playSide) * 7 + CHESSMAN_PAWN) {
return true;
}
//2.是否被马将军
for (int i = 0; i != 4; ++i) {
if (chessBoard[ADVISOR_STEP[i] + kingLoc] == 0) {
for (int j = 0; j != 2; ++j) {
if (chessBoard[KNIGHT_CHECK[i][j] + kingLoc] == (!playSide) * 7 + CHESSMAN_KNIGHT) {
return true;
}
}
}
}
//3.是否被车/将/炮 将军
for (int i = 0; i != 4; ++i) {
int direct = KING_STEP[i];
des = kingLoc + direct;
while (isInBoard(des)) {
//跳过该方向上的空格
if (chessBoard[des] == 0) {
des += direct;
continue;
}
//找到的第一个棋子是车或对方的将,则说明被将军
if (chessBoard[des] == (!playSide) * 7 + CHESSMAN_ROOK ||
chessBoard[des] == (!playSide) * 7 + CHESSMAN_KING) {
return true;
} else {
//找到的第一个棋子是其他棋子,则继续搜索出现的第一个棋子,若这个棋子是炮,则被将军
des += direct;
while (isInBoard(des) && chessBoard[des] == 0) {
    des += direct;
}
if (chessBoard[des] == (!playSide) * 7 + CHESSMAN_CANNON) {
return true;
} else {
    break;
}
}
}//while (isInBoard(des))
}
return false;
}
bool ChineseChess::isMate()
{
int nMov;
int mvs[MAX_MOVES];
nMov = generateMoves(mvs);
for (int i = 0; i != nMov; ++i) {
makeMove(mvs[i]);
if (!isChecked()) {
undoMove(mvs[i]);
return false;
} else {
undoMove(mvs[i]);
}
}
return true;
}
int ChineseChess::alphaBeta(int alpha, int beta, int depth)
{
//qDebug()<<"depth = "<<depth<<endl;
int value, bestValue,bestMov, nMov;
int mvs[MAX_MOVES];
if (depth == 0) {
return playSide ? blackValue - redValue : redValue - blackValue;
}
bestMov = 0;
bestValue = -MATE_VALUE;
nMov = generateMoves(mvs);
//qDebug()<<"生成"<<nMov<<"个走法"<<endl;
for (int i = 0; i != nMov; ++i) {
makeMove(mvs[i]);
value = - alphaBeta(-beta, -alpha, depth - 1);
undoMove(mvs[i]);
if (value > bestValue) {
bestValue = value;
if (value >= beta) {
bestMov = mvs[i];
break;
}
if (value > alpha) {
bestMov = mvs[i];
alpha = value;
}
}
}
//5.
if (bestValue == -MATE_VALUE) {
return distance - MATE_VALUE;
}
if (bestMov  != 0) {
if (distance == 0) {
searchedMov = bestMov;
}
}
return bestValue;
}
int ChineseChess::minMax(int depth)
{
int value, bestMov;
int best = -MATE_VALUE;
if (depth <= 0) {
return playSide ? blackValue - redValue : redValue - blackValue;
}
int legalMov[134];
int movLength = generateMoves(legalMov);
for (int i = 0; i != movLength; ++i) {
makeMove(legalMov[i]);
if (!isChecked()) {
        distance++;
value = -minMax(depth - 1);
undoMove(legalMov[i]);
        distance--;
if (value > best) {
best = value;
bestMov = legalMov[i];
}
} else {
undoMove(legalMov[i]);
}
}
if (distance == 0 && bestMov != 0) {
searchedMov = bestMov;
}
return best;
}
void ChineseChess::search()
{
searchedMov = 0;
distance = 0;
//minMax(3);
alphaBeta(-MATE_VALUE, MATE_VALUE, 5);
}

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: