黑白棋问题
原英文题意.
题意翻译
你的任务是模拟黑白棋游戏的进程。黑白棋的规则为:黑白双方轮流放棋子,每次必 须让新放的棋子“夹住”至少一枚对方棋子,然后把所有被新放棋子“夹住”的对方棋子 替换成己方棋子。一段连续(横、竖或者斜向)的同色棋子被“夹住”的条件是两端都是 对方棋子(不能是空位)。如图所示,白棋有6个合法操作,分别为(2,3),(3,3),(3,5),(6,2),(7,3),(7,4)。选择在(7,3)放白棋后变成如图所示效果(注意有竖向和斜向的共两枚黑棋变白)。注意(4,6)的黑色棋子虽然被夹住,但不是被新放的棋子夹住,因此不变白。
输入一个8*8的棋盘以及当前下一次操作的游戏者,处理3种指令:
L指令打印所有合法操作,从左到右的顺序排列(无合法操作时输出No legal move)。
Mrc指令放一枚棋子在(r,c)。如果当前游戏者没有合法操作,则是先切换游戏者再操作。保证输入合法。输出操作后的黑白棋子总数。
Q指令退出游戏,并打印当前棋盘(同输入格式)。
需要注意的问题点:
1、注意题意中不存在合法下棋位置时的操作
2、对与合法位置的判断,尽量保持原意,判断坐标是否在范围内
3、对合法下棋位置的判断:对棋盘上每个可下点,对其8个方向进行扩展判断,判断时带上方向作为参数,这样方便之后进行吃棋时对该方向上的棋进行吃操作
4、获取输入时,如果有多类型输入(单纯字母和字母加数字,可以用数组存储)
具体思路见下面的代码:
#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
using namespace std;
typedef pair<int, int> P;
char s[10][10];//棋盘
char c;
int d[8][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1},
{1, 1}, {1, -1}, {-1, 1}, {-1, -1}}; //可以延伸的八个方向
bool legal(int x, int y)//判断棋子位置是否合法
{
return 1 <= x && x <= 8 && 1 <= y && y <= 8;
}
char next()//每次行动后更换玩家
{
return c == 'W' ? 'B' : 'W';
}
bool check_dir(int x, int y, int i) //判断在(x,y)位置处向i方向是否合法
{
if (s[x][y] != '-') return false;
int nx = x + d[i][0];
int ny = y + d[i][1];//延伸
if (s[nx][ny] != next())
return false;
while (true)//不断沿此方向判断是否为敌棋颜色
{
nx += d[i][0];
ny += d[i][1];
if (s[nx][ny] == c) return true;
if (s[nx][ny] != next())
return false;
}
}
bool can_set(int x, int y)//判断(x,y)能否置子
{
for (int i = 0; i < 8; i ++) {
if (check_dir(x, y, i)) {
return true;
}
}
return false;
}
void set(int x, int y)//下子并从八个方向吃敌棋
{
for (int i = 0; i < 8; i ++) {
if (check_dir(x, y, i)) {
int nx = x+d[i][0], ny = y+d[i][1];
while (s[nx][ny] == next()) {//不断吃棋,直到遇到非敌棋
s[nx][ny] = c;
nx += d[i][0];
ny += d[i][1];
}
}
}
s[x][y] = c;
}
P cnt()//数场上的黑白棋数量
{
P res(0, 0);
for (int i = 1; i <= 8; i ++) {
for (int j = 1; j <= 8; j ++) {
if (s[i][j] == 'B') res.first ++;
if (s[i][j] == 'W') res.second ++;
}
}
return res;
}
void print_chess()
{
for (int i = 1; i <= 8; i ++) {
for (int j = 1; j <= 8; j ++) {
printf("%c", s[i][j]);
}
printf("\n");
}
}
int main(void)
{
int kase;
char op[4];
cin >> kase;
for (int t = 1; t <= kase; t++)
{
memset(s,'n',sizeof(s));
for (int i = 1; i <= 8; i ++)
scanf("%s", s[i]+1);
scanf("%s", op);
c = op[0];
if (t > 1) printf("\n");
while (scanf("%s", op))
{
if (op[0] == 'L')//三种输入,按要求模拟
{
bool flag = false;
bool first = true;
for (int i = 1; i <= 8; i ++) {
for (int j = 1; j <= 8; j ++) {
if (can_set(i, j)) {
flag = true;
if (!first) printf(" ");
printf("(%d,%d)", i, j);
first = false;
}
}
}
if (flag == false) printf("No legal move.");
printf("\n");
}
else if(op[0] == 'M')
{
int x = op[1]-'0', y = op[2]-'0';
if (can_set(x, y)) { set(x, y);}
else { c = next(); set(x, y); }
c = next();
P num = cnt();
printf("Black - %2d White - %2d\n", num.first, num.second);
}
else {
print_chess();
break;
}
}
}
return 0;
}