代码转载自:https://blog.csdn.net/XieNaoban/article/details/52078533
你的任务是模拟黑白棋游戏的进程。黑白棋的规则为:黑白双方轮流放棋子,每次必须
让新放的棋子“夹住”至少一枚对方棋子,然后把所有被新放棋子“夹住”的对方棋子替换成己
方棋子。一段连续(横、竖或者斜向)的同色棋子被“夹住”的条件是两端都是对方棋子(不
能是空位)。如图4-6(a)所示,白棋有6个合法操作,分别为(2,3),(3,3),(3,5), (6,2),(7,3),
(7,4)。选择在(7,3)放白棋后变成如图4-6(b)所示效果(注意有竖向和斜向的共两枚黑棋变
白)。注意(4,6)的黑色棋子虽然被夹住,但不是被新放的棋子夹住,因此不变白。
输入一个8*8的棋盘以及当前下一次操作的游戏者,处理3种指令:
L指令打印所有合法操作,按照从上到下,从左到右的顺序排列(没有合法操作时输出
No legal move)。
Mrc指令放一枚棋子在(r,c)。如果当前游戏者没有合法操作,则是先切换游戏者再操
作。输入保证这个操作是合法的。输出操作完毕后黑白方的棋子总数。
Q指令退出游戏,并打印当前棋盘(格式同输入)。
之前写了很长,将近两百行还没写完,烂的不能再烂了,于是翻了一下博客发现这个老哥写的非常好,代码重用性非常高,就分析一下他的代码:
其实下子的时候也是用到了L操作 需要判断 当前的颜色的棋子是否有地方放 所以用 is_print 控制是否输出结果 , 用Flag判断是否有地方可以放子。
void L(bool is_print)
{
L_Refresh = 1, Flag = 0;
for (int i = 0; i < 8; ++i)
for (int j = 0; j < 8; ++j)
{
if (Board[i][j] != '-') continue;
for (int l = 0; l < 8; ++l)
if (judge(i, j, Rx[l], Ry[l], is_print)) break;
}
if (is_print) Flag ? printf("\n") : printf("No legal move.\n");
}
下子的话 那就比较简单了 直接用L()函数判断能否下子如果能的话分别判断八个方向是否能翻转棋子 如果能的话就翻转。
void M()
{
char i = Command[1] - 49, j = Command[2] - 49;
if (!L_Refresh) L(0);//判断是否可以下子 如果之前查询过是可以下子的话则跳过
if (!Flag) Current = oppo();//没有地方可以下棋
for (int l = 0; l < 8; ++l)
if (judge(i, j, Rx[l], Ry[l], 0)) change(i, j, Rx[l], Ry[l]);
Current == 'W' ? Num[0] += 1 : Num[1] += 1;
Board[i][j] = Current;
Current = oppo();
L_Refresh = 0;
printf("Black - %2d White - %2d\n", Num[1], Num[0]);
}
AC代码如下:
#include
#include
char Board[11][11], Current, Command[5];
bool Flag, L_Refresh;//flag用于空格的输出,同时可以判断出本局是不是当前颜色的棋子无路可走
int Times, Num[2];//Num:0白1黑
int Rx[] = { 0, 0, 1, -1, 1, -1, 1, -1 };
int Ry[] = { 1, -1, 0, 0, 1, -1, -1, 1 };
inline char oppo()
{
return (Current == 'W' ? 'B' : 'W');
}
bool judge(int i, int j, int x, int y, bool is_print)
{
int ii = i, jj = j + 1, flg = 0;
while ((i += x) < 8 && (j += y) < 8 && i >= 0 && j >= 0)
{
if (Board[i][j] == '-') break;
if (Board[i][j] == Current)
{
if (!flg) break;
if (is_print)
{
if (Flag) printf(" ");
printf("(%d,%d)", ii, jj);
}
if (!Flag) Flag = true;
return true;
}
++flg;
}
return false;
}
void change(int i, int j, int x, int y)
{
int n = 0;
while (Board[i += x][j += y] != Current)
{
Board[i][j] = Current, ++n;
}
Current == 'W' ? (Num[0] += n, Num[1] -= n) : (Num[0] -= n, Num[1] += n);
}
void L(bool is_print)
{
L_Refresh = 1, Flag = 0;
for (int i = 0; i < 8; ++i)
for (int j = 0; j < 8; ++j)
{
if (Board[i][j] != '-') continue;
for (int l = 0; l < 8; ++l)
if (judge(i, j, Rx[l], Ry[l], is_print)) break;
}
if (is_print) Flag ? printf("\n") : printf("No legal move.\n");
}
void M()
{
char i = Command[1] - 49, j = Command[2] - 49;
if (!L_Refresh) L(0);//判断是否可以下子 如果之前查询过是可以下子的话则跳过
if (!Flag) Current = oppo();//没有地方可以下棋
for (int l = 0; l < 8; ++l)
if (judge(i, j, Rx[l], Ry[l], 0)) change(i, j, Rx[l], Ry[l]);
Current == 'W' ? Num[0] += 1 : Num[1] += 1;
Board[i][j] = Current;
Current = oppo();
L_Refresh = 0;
printf("Black - %2d White - %2d\n", Num[1], Num[0]);
}
void Q()
{
for (int i = 0; i < 8; ++i) printf("%s\n", Board[i]);
}
int main()
{
scanf("%d", & Times);
while (Times--)
{
for (int i = 0; i < 8; ++i) scanf("%s", Board[i]);
scanf("\n%c", & Current);
L_Refresh = 0;
Num[0] = Num[1] = 0;
for (int i = 0; i < 8; ++i)
for (int j = 0; j < 8; ++j)
{
if (Board[i][j] == 'W') ++Num[0];
else if (Board[i][j] == 'B') ++Num[1];
}
while (scanf("%s", Command) && Command[0] != 'Q')
Command[0] == 'L' ? L(1) : M();
Q();
if (Times) printf("\n");
}
return 0;
}