中国象棋
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);
}
相关文章推荐
- Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)
- 折纸问题
- 求逆序对(复杂度为nlogn)
- Android学习(一)
- 五边形
- 安卓adb.exe无法启动
- 配置App真机测试证书的流程 一览
- <香港科技大学html+css+js课堂笔记>week1--CSS部分
- 《PCANet: A Simple Deep Learning Baseline for Image Classification》
- Mysql视图使用总结
- A tutorial on Principle Component Analysis
- linux 常用命令
- 「Emacs org-mode(一)」用Org-mode实现GTD
- css中的div布局之巧用div
- 求自定类型元素序列的中位数
- 20145233韩昊辰 第(三)周总结
- 理解socket的阻塞
- (一)MongoDB简介
- SQL Server 未删除任何行
- NSAttributedString 的21种属性 详解