/*
这题实在是让人不由感慨一下,好的思路有多么重要!~
起因:因为自己实在想不出来,于是百度题解。然而搜到的题解,要不看得艰难,要不一看就是200行以上的,就可能是畏难吧,于是我甚至看题解,看别人的代码都看不下去了...
但是我又实在不想放弃,接着搜搜搜,居然在百度的比较靠后的页里,找到了一份对我而言,最简洁易懂的代码,马上就理解了,于是自己借用思路手敲了一次
BTW,这个博主写的真心是好,毫无冗余,并且条理逻辑十分清晰,虽然注释不多,但还是让人一眼就看懂了,真的强烈推荐大家去瞻仰一下
http://blog.csdn.net/fzl1941572592/article/details/75208834
但是值得一提的是,如果用这种写法,对格式的控制必须十分精细,不得有丝毫错漏,否则很容易WA,建议先把所有输入数据赋值到一个txt里,观察格式,末尾有无空格,还是只是换行?合理运用getchar(),必要时可以用 cout / printf 输出来检验自己的输入格式,是否真的控制好了。
还要说一下,如果选手在0和1间不断变换,可以用异或符号 ^=
0826更新--
今天我自己按照博主的思路敲了一次,才发现这题,黑白棋连子的判断和替换,选手的替换,这两个最大的难点,博主都用了十分简洁清晰的思路写出来了,真是十分佩服,要是我自己写,肯定得写得很长很长很麻烦
*/
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
char chess[10][10];
typedef pair<int, int > p;
p store[50];
int dxy[8][2] = { {1, 0}, {-1, 0}, {0, 1}, {0, -1}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1} };
//#define debug
void count()
{
int s1 = 0, s2 = 0;
for (int i = 1; i <= 8; i++)
for (int j = 1; j <= 8; j++)
{
switch (chess[i][j])
{
case 'B': s1++; break;
case 'W': s2++; break;
}
}
printf("Black - %2d White - %2d\n", s1, s2);
}
int is_legal(char c)
{
int res = 0;
memset(store, 0, sizeof (store));
for (int i = 1; i <= 8; i++)
{
for (int j = 1; j <= 8; j++)
{
bool flag = false;
if (chess[i][j] == '-') //在此放己方棋子作为起点
{
for (int k = 0; k < 8; k++)
{
int xx = i + dxy[k][0], yy = j + dxy[k][1];
if (xx >= 1&& xx <= 8 && yy >= 1 && yy <= 8 && chess[xx][yy] != c && chess[xx][yy] != '-') //只要该方向上距离 chess[i][j]最近的位置满足这个严苛的条件,就可以一直往这个方向循环,直到越界,或者因为不满足特定条件而break出来
{
while (xx >= 1&& xx <= 8 && yy >= 1 && yy <= 8) //在此方向不断延伸,直到碰到己方棋子,或空位,
{
xx += dxy[k][0]; yy += dxy[k][1];
if (chess[xx][yy] == '-') break; // 夹住对方棋子的条件:两端都是己方棋子,不能是空位
if (chess[xx][yy] != c) continue; // 如果是对方棋子,继续循环
flag = true; break; //如果是己方棋子,标记一下这个起点(i,j)可以放置,于是就可以退出了,将这个位置赋值pair数组
}
}
}
}
if (flag)
{
res++;
store[res].first = i; store[res].second = j;
}
}
}
return res;
}
void change (int x, int y, char c)
{
chess[x][y] = c;
for (int i = 0; i < 8; i++)
{
int xx = x + dxy[i][0], yy = y + dxy[i][1];
bool flag = false;
if (xx >= 1 && xx <= 8 && yy >= 1 && yy <= 8 && chess[xx][yy] != c && chess[xx][yy] != '-') //注意,有2个x的变量,有2个y的变量,不要写漏为1个了,我在这个地方WA了几次,找了很久,真的很难发现
{
while (xx >= 1&& xx <= 8 && yy >= 1 && yy <= 8)
{
xx += dxy[i][0]; yy += dxy[i][1];
if (chess[xx][yy] == '-') break;
if (chess[xx][yy] != c) continue;
flag = true; break; //确认当前方向的确可以替换己方棋子
}
}
if (flag)
{
xx = x + dxy[i][0]; yy = y + dxy[i][1];
while (xx >= 1&& xx <= 8 && yy >= 1 && yy <= 8)
{
chess[xx][yy] = c;
xx += dxy[i][0]; yy += dxy[i][1];
if (chess[xx][yy] == c) break; // 等到遇到己方棋子,该方向的替换也就结束了
}
}
}
}
void showchess()
{
for (int i = 1; i <= 8; i++)
{
for (int j = 1; j <= 8; j++) cout << chess[i][j];
cout << endl;
}
}
int main()
{
#ifdef debug
freopen("E:\\in.txt", "r", stdin);
freopen("E:\\out.txt", "w", stdout);
#endif
int t, kase = 0, s; //s表示当前棋局从谁开始下
char player[2] = { 'W', 'B' };
char start, order; //起始选手,指令
cin >> t;
getchar(); //处理末尾的回车符
while (t--)
{
if (kase++) cout << endl;
for (int i = 1; i <= 8; i++)
{
for (int j = 1; j <= 8; j++)
cin >> chess[i][j];
getchar(); //处理末尾的回车符
}
cin >> start; getchar(); //处理回车
if (start == 'W')s = 0; else s = 1;
while (cin >> order)
{
if (order == 'Q')
{
showchess();
getchar();
break;
}
else if (order == 'M')
{
int r, c, rc; // row, colunm
cin >> rc;
r = rc / 10;
c = rc % 10;
if (is_legal(player[s]))
change(r, c, player[s]);
else
{
s ^= 1;
change(r, c, player[s]);
}
s ^= 1; //别忘了为M时,是真正的两人下棋的情况,一定要记得一人下完以后,更换选手了!!!
count();
}
else
{
int ans = is_legal(player[s]);
if (!ans) cout << "No legal move." << endl;
else
{
printf("(%d,%d)", store[1].first, store[1].second);
for (int i = 2; i <= ans; i++)
printf(" (%d,%d)", store[i].first, store[i].second);
cout << endl;
}
}
getchar();
}
}
#ifdef debug
fclose(stdin);
fclose(stdout);
#endif
return 0;
}