题目
这条题输入格式要求非常多...很多坑,笔者就在输出格式这搞了很久最终通过网站https://cn.vjudge.net debug才发现哪里不对,先提一下。
L输出的每个坐标间要有空格,但是整行首末都不能有空格;题目与题目之间有空行,且最后一题在输出棋盘后也有一个空行;M命令输出的棋数统计的数字占两格(%2d)。
输入
输入包括三部分
第一部分只有一个数字 n,表示下面一共有 n 个题目。
第二部分有 9 行,代表当前棋盘状态。前八行是 8*8 的棋盘,'-'代表空,'B'代表黑棋,'W'代表白棋。第九行是 'B' 或者 'W' 代表当前玩家。
第三部分是操作命令,有三种:
'L': 输出当前玩家可放棋的所有位置。column优先升序再到row升序。
'Mij': 当前玩家在 (i,j)下棋子,如果当前玩家没有可放棋的位置则直接变为对手下这一步棋。下棋之后转换当前玩家。
'Q': 退出这题。
处理
当放下一个棋子后,若该棋子的水平、垂直 或 对角线方向(共八个方向)满足有相同颜色的棋子且两棋子间都是相反颜色的棋子,则把中间的棋子全部变为己方的棋子。要求每次下棋至少有一个棋子被转换。
解读
题目主要需要处理的功能有两个:列出可走的位置 和 下棋。下面进行解析。
列出可走的位置只需传递一个参数 player(当前玩家),然后遍历棋盘所有空格,并判断该位置能否下棋,能则输出。所以这里右需要一个函数(check1)。
check1函数需要三个参数:player,x,y。但是判断一个位置又分八个方向,所以再加一个函数(check2)。遍历八个方向,有一个方向为真就返回1。
check2函数需要五个参数:player,x,y,dx,dy。其中 dx 和 dy 表示方向,取值 -1,0,1。遍历该方向,若符合则返回长度。
下棋则需要三个参数,player,x,y。遍历八个方向,用 check2 返回的长度对该方向遍历,进行转换。
代码
#define maxn 10
#include
#include
char broad[maxn][maxn];
void print() {
for (int i = 1; i <= 8; i++)
printf("%s\n", &broad[i][1]);
}
char readdisk() {
char ch;
while (ch = getchar())
if (ch == '-' || ch == 'W' || ch == 'B') return ch;
}
int list(char &player);
int check(char &player, int x, int y);
int check(char &player, int x, int y, int dx, int dy);
void place(char &player, int x, int y);
void sum();
int main() {
#ifdef TEST
freopen("test.in", "r", stdin);
freopen("test.out", "w", stdout);
#endif // TEST
int n, kase = 0;
scanf("%d", &n);
while (n--) {
if (kase++) putchar('\n');
memset(broad, '\0', sizeof(broad));
for (int i = 1; i <= 8; i++) {
broad[i][1] = readdisk();
for (int j = 2; j <= 8; j++) {
broad[i][j] = getchar();
}
}
char player[2];
scanf("%s", player);
char cmd[5];
while(scanf("%s", cmd) != EOF && cmd[0] != 'Q') {
if (cmd[0] == 'L') list(player[0]);
else if (cmd[0] == 'M') place(player[0], cmd[1] - '0', cmd[2] - '0');
}
print();
}
return 0;
}
int list(char &player) {
int sum = 0, kase = 0;
for (int x = 1; x <= 8; x++) for (int y = 1; y <= 8; y++) {
if (broad[x][y] != '-') continue;
if (check(player, x, y)) {
if (kase++) putchar(' ');
printf("(%d,%d)", x, y), sum++;
}
}
if (sum == 0) printf("No legal move.");
printf("\n");
return sum;
}
int check(char &player, int x, int y) {
for (int dx = -1; dx <= 1; dx++) for (int dy = -1; dy <= 1; dy++) {
//不遍历(0,0)方向
if (dx == 0 && dy == 0) continue;
if (check(player, x, y, dx, dy)) return 1;
}
return 0;
}
int check(char &player, int x, int y, int dx, int dy){
int len, flag = 0;
x += dx; y += dy;
//len统计该方向两棋间长度
for (len = 1; x <= 8 && x >= 1 && y <= 8 && y >= 1; len++) {
if (broad[x][y] == '-') break;
if (broad[x][y] == player) { flag = 1; break; }
x += dx; y += dy;
}
if (len == 1 || flag == 0) return 0;
return len;
}
void place(char &player, int x, int y) {
if (check(player, x, y) == 0) player = (player == 'W' ? 'B' : 'W');
broad[x][y] = player;
for (int dx = -1; dx <= 1; dx++) for (int dy = -1; dy <= 1; dy++) {
//不遍历(0,0)方向
if (dx == 0 && dy == 0) continue;
int len = check(player, x, y, dx, dy);
//遍历两棋间
for (int i = 1; i < len; i++) broad[x + i * dx][y + i * dy] = player;
}
player = (player == 'W' ? 'B' : 'W');
sum();
}
void sum() {
int sumb = 0, sumw = 0;
for (int x = 1; x <= 8; x++) for (int y = 1; y <= 8; y++) {
if (broad[x][y] == 'W') sumw++;
else if (broad[x][y] == 'B') sumb++;
}
printf("Black - %2d White - %2d\n", sumb, sumw);
}