黑白棋是一种群众喜闻乐见的棋类游戏,双方各执黑白一色棋子,在 8 * 8 的棋盘上进行比赛(棋盘初始布局如下图),双方轮流下子,黑棋先手。
每次行动,玩家可以选择在棋盘中任意的有效格子处下子。在落子后,会进行八个方向的翻转操作。
翻转操作的过程是这样的:以刚放下的那颗棋子为中心(简称为中心棋子),在上、下、左、右、左上、左下、右上、右下八个射线方向内,分别寻找一个离中心棋子最近的己方颜色的棋子(简称为外侧棋子)。如果某个方向不存在外侧棋子,或者中心棋子和外侧棋子之间存在空白格子,或者中心棋子和外侧棋子直接相邻,则该方向是无效的,需要跳过。
如果一个翻转方向是有效的,则对其执行翻转操作,将中心棋子和外侧棋子之间的所有棋子都变成己方颜色的棋子。
而所谓的有效格子,则表示该格子是一个空白格子,并且在该格子处下子,至少有一个方向能出现有效翻转。
由于 Dr. Cat 和 Prof. Chi 的脑补水平已经达到正常人的 6 倍,他们下棋完全不需要棋盘,仅仅用语言就能在脑中进行对决。而作为一般人的 Kotomi,根本搞不清他们的 N 步操作之后会变成什么样的局面。所以 Kotomi 请求你,勇敢的少年,快用你的程序创造奇迹吧!
输入格式
一个整数 T,表示有多少组测试数据。
对于每组测试数据,第一行是一个整数 N (1 <= N <= 60),表示这局黑白棋当前已经下过了 N 步棋子。
接下来的 N 行,每一行给出一个数字 X (1 <= X <= 8) 和一个字符 Y ('A' <= Y <= 'H'),表示棋子落在的位置。这些棋子是按照从开局到结束的行动顺序依次给出的,数据保证所有操作都是合法操作,并且不存在某个人无法落子的情况。
输出格式
对于每组测试数据,输出最终的棋盘局面。黑子由 ‘#’ 表示,白子由 ‘*’ 表示,空白的格子由 ‘.’ 表示。棋盘的格子之间由一个空格隔开,棋盘的行号和列号也要输出。具体细节请参照样例,注意不要有多余的空白和换行符。
样例输入
2
2
5 F
4 F
6
5 F
4 F
3 E
6 F
5 G
3 F
样例输出
A B C D E F G H
1 . . . . . . . .
2 . . . . . . . .
3 . . . . . . . .
4 . . . * * * . .
5 . . . # # # . .
6 . . . . . . . .
7 . . . . . . . .
8 . . . . . . . .
A B C D E F G H
1 . . . . . . . .
2 . . . . . . . .
3 . . . . # * . .
4 . . . * # * . .
5 . . . # # * # .
6 . . . . . * . .
7 . . . . . . . .
8 . . . . . . . .
#include<stdio.h>
#include<string.h>
int a[9][9];
int xis[]={-1, 1, 0, 0, -1, -1, 1, 1}; //上,下,左,右,左上,坐下,右上,右下
int yis[]={ 0, 0, -1, 1, -1, 1, -1, 1};
void print()
{
int i,j;
printf(" ");
for(i=0;i<8;i++)
printf(" %c",'A'+i);
printf("\n");
for(i=1;i<=8;i++)
{
printf("%d",i);
for(j=1;j<=8;j++)
if(a[i][j]==1)
printf(" #");
else if(a[i][j]==-1)
printf(" *");
else
printf(" .");
printf("\n");
}
}
//每走一步,执行的变换
void translate(int X,int Y, bool black)
{
int flag; //用于标记,当前是黑棋还是白棋
if(black)
flag=1;
else
flag=-1;
a[X][Y]=flag;
//printf("a[%d][%d]:%d\n",X,Y,a[X][Y]);
int i,xi,yi,tempX,tempY;
for(i=0;i<8;i++) //遍历8个方向
{
xi=xis[i];
yi=yis[i];
//printf("%d:%d方向搜索\n",xi,yi);
tempX=X+xi;
tempY=Y+yi;
int count=0; //用于计数,在xi,yi方向上走的步数
while(tempX>=1 && tempY>=1 && a[tempX][tempY]==-flag)
{ //xi,yi方向上搜索;如果是和X,Y上棋子颜色相反的,就继续搜索
count++;
tempX+=xi;
tempY+=yi;
}
//停止搜索时,如果遇到的是和X,Y上相同的棋子,就将(tempX,tempY)和(X,Y)之间的棋子,置为(X,Y)上的棋子
if(tempX>=1 && tempY>=1 && a[tempX][tempY]==flag )
{ //printf("%d:%d上有%d个变换\n",xi,yi,count);
tempX-=xi;
tempY-=yi;
//循环条件用count,不能用注释中的,tempX,tempY是八个方向的,搜索停止时,不一定都满足(tempX<=X && tempY<=Y)
while(count--)//while(tempX<=X && tempY<=Y),
{
a[tempX][tempY]=flag;
tempX-=xi;
tempY-=yi;
}
}
}
}
void getOneTest()
{
int N; //走的步数
int X; //每一步走的棋子,
char Y;
memset(a,0,sizeof(a)); //初始化为0,黑棋1,白棋-1
a[4][4]=-1;
a[4][5]=1;
a[5][4]=1;
a[5][5]=-1;
scanf("%d",&N);
bool black=true;
while(N--)
{
scanf("%d %c",&X,&Y);
Y=Y-'A'+1; //转换成坐标, 坐标从1开始,和棋盘对应
translate(X,Y,black);
black=!black;
}
print();
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
getOneTest();
}