上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人
3.4 不同表示方法的转换
一维数组与FEN串表示方法是非常重要的两种表示方法,博弈程序内部用到一维数组,与其他博弈程序对弈进行通信时要用到FEN串。博弈程序必须要能够将局面正确的从一维数组转换成FEN串,也要能够将FEN串表示的局面转换成一维数组。
3.4.1 一维数组转换成FEN串
算法3-1:一维数组转换成FEN串
行变量i=3 to 12 空格变量k=0 列变量j=3 to 11 pc= 棋盘i行j列元素值 if pc==0 k++; else if k>0 数字k转换成字符后附在字符串的尾部 k=0 pc值对应的字符附在字符串的尾部 if k>0 数字k转换成字符后附在字符串的尾部 k=0 if i!=12 附加’/’在字符串尾部 附加空格在字符串尾部 if是红方走棋 ‘w’附加在字符串尾部 else ‘b’附加在字符串尾部 在字符串尾部增加结束符号’\0’
程序代码
// 将一维数组表示的局面转换成FEN串 //---------------变量声明---------------------------------------------- int side; // 轮到哪方走,0表示红方,1表示黑方 unsigned char board[256]; // 棋盘数组 char FenString[128]; //局面的FEN串格式 void ArrayToString() { int i, j, k, pc; char *str;
str = FenString; for (i = 3; i <= 12; i ++) { k = 0; for (j = 3; j <= 11; j ++) { pc = board[(i << 4) + j]; if (pc != 0) { if (k > 0) { *str = k + '0'; str ++; k = 0; } *str = IntToChar(pc); str ++; } else { k ++; } } if (k > 0) { *str = k + '0'; str ++; } *str = '/'; str ++; } str --; *str = ' '; str ++; *str = (side == 0 ? 'w' : 'b'); str ++; *str = '\0'; }
代码技巧
数字k转换成字符:char ch = ‘0’ + k
二维矩阵i行j列位置转换成一维数组位置:(i << 4) + j
pc值对应的字符:如何求得pc整数对应的字符,可以用一个函数来实现
char IntToChar(int a) { if(a <32)
{ switch(a) { case 16: return 'K'; case 17: case 18: return 'A'; case 19: case 20: return 'B'; case 21: case 22: return 'N'; case 23: case 24: return 'R'; case 25: case 26: return 'C'; case 27: case 28: case 29: case 30: case 31: return 'P'; default: return 0; } } else { a = a-16; switch(a) { case 16: return 'k'; case 17: case 18: return 'a'; case 19: case 20: return 'b'; case 21: case 22: return 'n'; case 23: case 24: return 'r'; case 25: case 26: return 'c'; case 27: case 28: case 29: case 30: case 31: return 'p'; default: return 0; } } }
3.4.2 FEN串转换成一维数组
算法3-2:FEN串转换成一维数组
清空一维数组棋盘 行变量i=3 列变量j=3 str= 字符串下一字符 while(str!=’ ‘) if (str == '/') 换行操作:j = 3;i ++; else if str>=’1’ && str<=’9’ 列变量j向后移动str个位置j= j+(str-‘0’) else if str>=’A’ && str<=’Z’ 将字符转换成红方棋子的整数表示 将整数放入数组相应位置i<<4+j else if str>=’a’ && str<=’z’ 将字符转换成黑方棋子的整数表示 将整数放入数组相应位置i<<4+j str= 字符串下一字符 str= 字符串下一字符 //判断哪方走棋 if(str!=’b’) side =0; else side =1;
程序代码
void ClearBoard() //清空棋盘数组 { int i; side = 0; for (i = 0; i < 256; i ++) { board[i] = 0; }
} void StringToArray(const char *FenStr) //将FEN串表示的局面转换成一维数组 { int i, j, k; int pcWhite[7]={16,17,19,21,23,25,27}; int pcBlack[7]={32,33,35,37,39,41,43}; const char *str; ClearBoard(); str = FenStr; if (*str == '\0') { return; } i = 3; j = 3; while (*str != ' ') { if (*str == '/') { j = 3; i ++; if (i > 12) { break; } } else if (*str >= '1' && *str <= '9') { for (k = 0; k < (*str - '0'); k ++) { if (j >= 11) { break; } j ++; } } else if (*str >= 'A' && *str <= 'Z') {
if (j <= 11) { k = CharToSubscript(*str); if (k < 7) { if (pcWhite[k] < 32) { board[(i<<4) + j] = pcWhite[k]; pcWhite[k]++; } } j ++; } } else if (*str >= 'a' && *str <= 'z') { if (j <= 11) { k = CharToSubscript(*str); if (k < 7) { if (pcBlack[k] < 48) { board[(i<<4) + j] = pcBlack[k]; pcBlack[k]++; } } j ++; } } str ++; if (*str == '\0') { return; } } str ++; if (*str == 'b') side = 1;
else side = 0; }
代码技巧
设置一个数组pcWhite[7],保存每一种红方棋子的初始整数值,如表3-4所示。
表3-4 每一种红方棋子的初始整数值
下标0,1,2,3,4,5,6分别对应表示帅,仕,相,马,车,炮,兵。
当字符串中出现R时,表示红方一个车。如下操作可实现:
Int j = pcWhite[4]; //第1个车对应整数23 pcWhite[4]++;//将不同的车对应到不同的值,下一个车则是24
那又如何得到车的下标是4呢?
int CharToSubscript(char ch) { switch(ch) { case 'k': case 'K':return 0; case 'a': case 'A':return 1; case 'b': case 'B':return 2; case 'n': case 'N':return 3; case 'r': case 'R':return 4; case 'c': case 'C':return 5; case 'p': case 'P':return 6; default:return 7; } }
同理设置一个数组pcBlack[7],保存每一种黑方棋子的初始整数值,如表3-5所示。
表3-5 每一种黑方棋子的初始整数值
下标0,1,2,3,4,5,6分别对应表示将,士,象,马,车,炮,卒。
当字符串中出现R时,表示黑方一个车。如下操作可实现:
int j = pcWhite[4]; //第1个车对应整数39 pcWhite[4]++;//将不同的车对应到不同的值,下一个车则是40
参见程序:3-1.cpp