黑白棋是一種羣衆喜聞樂見的棋類遊戲,雙方各執黑白一色棋子,在 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();
}