P5380 [THUPC2019] 鸭棋 题解

一道大模拟题。

分析

做这道题之前,我们首先需要捋一捋思路。

对于每一个操作,我们需要做的就是下面几点:

  1. 判断是否可行
  2. 如可行,则移动棋子
  3. 判断是否移除了对方的棋子
  4. 判断是否形成了将军局面
  5. 判断是否结束了游戏

就下面五点。

可行性

首先我们分析一下有哪些情况会导致操作不可行:

  1. 游戏已经结束。
    这个在所有操作之前进行一个判断即可。
  2. 移动的起止点不在棋盘内。
    这个在移动之前判断即可。
  3. 开始移动的地方没有己方棋子。
    同上。
  4. 移动的目的地已经有了己方棋子。
    同上。
  5. 移动的方式不符合棋子的可达位置。
    对于每一种棋子分类判断。
  6. (象、马、鸭)被绊住。
    与上方情况一起判断。

所有的情况只有这六种。

将军与否

这个与上面判断目的地是否符合棋子的可达位置相似。
但是,我采用的是判断一个王是否能被棋子吃掉的方法,与大部分人的不太一样,注意坐标的不同。
(就这个让我调了好长时间)

游戏结束

一旦有一方的王被移除,那么游戏就结束了。
这个判断移除的棋子类型的时候就顺便判断了。


实现

下面是代码实现部分:

定义

我们将七种棋子用数字表示,红方为1-7,蓝方为11-17。

顺序就是按照题目给的顺序,从1到7分别是:王士象马车鸭兵。

初始化

我一开始以为棋盘长10宽9,就按照这样写了下去,结果反了,所以注意这里的坐标问题。

void initMap()
{
	memset(base, 0, sizeof(base));
	base[4][0] = 1;
	base[4][9] = 11;
	base[3][0] = base[5][0] = 2;
	base[3][9] = base[5][9] = 12;
	base[2][0] = base[6][0] = 3;
	base[2][9] = base[6][9] = 13;
	base[1][0] = base[7][0] = 4;
	base[1][9] = base[7][9] = 14;
	base[0][0] = base[8][0] = 5;
	base[0][9] = base[8][9] = 15;
	base[0][2] = base[8][2] = 6;
	base[0][7] = base[8][7] = 16;
	base[0][3] = base[2][3] = base[4][3] = base[6][3] = base[8][3] = 7;
	base[0][6] = base[2][6] = base[4][6] = base[6][6] = base[8][6] = 17;
}

是否越过边界

棋盘长为9,。宽为10,坐标从 \((0,0)\) 开始,到 \((8,9)\) 结束。

void checkOut()
{
	bool flag = false;
	if (sx < 0)flag = true;
	if (sx > 8)flag = true;
	if (sy < 0)flag = true;
	if (sy > 9)flag = true;
	if (tx < 0)flag = true;
	if (tx > 8)flag = true;
	if (ty < 0)flag = true;
	if (ty > 9)flag = true;
	if (flag)
	{
		puts("Invalid command");
		isInvalid = true;
	}
}

(其实本来可以写紧凑些的)

移动

我们这里直接对棋子的类型进行分析。

首先,我们需要判断我们的起止点是否合法,即起始点有没有棋子、目的地有没有己方棋子什么的。

	if (base[sx][sy] / 10 != side)
	{
		puts("Invalid command");
		isInvalid = true;
		return;
	}
	else if (base[sx][sy] == 0)
	{
		puts("Invalid command");
		isInvalid = true;
		return;
	}
	else if (base[tx][ty] / 10 == side && base[tx][ty] != 0)
	{
		puts("Invalid command");
		isInvalid = true;
		return;
	}

(其实本来可以写紧凑些的)

然后就是对每一种棋子的类型分开讨论:

王的可达范围是与其相邻的四个格子:

[pic here]

判定方法比较简单:

	if (type == 1)
	{
		if (abs(sx - tx) + abs(sy - ty) > 1)
		{
			puts("Invalid command");
			isInvalid = true;
			return;
		}
	}	

士的可达范围为其四角的格子:

[pic here]

判定方法也很简单:

	else if (type == 2)
	{
		if (abs(sx - tx) != 1 || abs(sy - ty) != 1)
		{
			puts("Invalid command");
			isInvalid = true;
			return;
		}
	}

象在没有被绊住的情况下可以到达其四角距其两格的格子:

[pic here]

这时候需要判定两种情况,一是目的地不合法,二是目的地合法,但被绊住不能动。

	else if (type == 3)
	{
		if (abs(sx - tx) != 2 || abs(sy - ty) != 2)
		{
			puts("Invalid command");
			isInvalid = true;
			return;
		}
		if (base[(sx + tx) / 2][(sy + ty) / 2] != 0)
		{
			puts("Invalid command");
			isInvalid = true;
			return;
		}
	}

车能在当前行和当前列中随意移动,直到遇到了一个棋子。
如果遇到的是敌方棋子,那就可以吃掉对方;
如果遇到的是己方棋子就会被判定不合法。

(这里就不放图了)

首先,因为我们有了起止点,我们就可以先判断车所要到的地方是否是己方棋子。如果是的话就直接判定不合法。
然后我们需要判定起止点是否在同一行或同一列上,否则就不合法。
最后,我们从起始点向目的地扫,看中间有没有棋子,任何一方的都算,因为车不能跨过棋子。

	else if (type == 5)
	{
		if (sx != tx && sy != ty)
		{
			puts("Invalid command");
			isInvalid = true;
			return;
		}
		bool collide = false;
		if (sx != tx)
		{
			int tmpx = min(sx, tx);
			for (int i = tmpx + 1; i < max(sx, tx); i++)
			{
				if (base[i][sy] != 0)
				{
					collide = true;
					break;
				}
			}
		}
		else if (sy != ty)
		{
			int tmpy = min(sy, ty);
			for (int i = tmpy + 1; i < max(sy, ty); i++)
			{
				if (base[sx][i] != 0)
				{
					collide = true;
					break;
				}
			}
		}
		if (collide)
		{
			puts("Invalid command");
			isInvalid = true;
			return;
		}
	}

马可以到的位置是日字形的地方,同时还需要注意绊住的情况:

[pic here]

	else if (type == 4)
	{
		if (!(abs(sx - tx) == 2 && abs(sy - ty) == 1) && !(abs(sx - tx) == 1 && abs(sy - ty) == 2))
		{
			puts("Invalid command");
			isInvalid = true;
			return;
		}
		if (abs(sx - tx) > abs(sy - ty))
		{
			if (base[sx + (tx - sx) / 2][sy] != 0)
			{
				puts("Invalid command");
				isInvalid = true;
				return;
			}
		}
		else
		{
			if (base[sx][sy + (ty - sy) / 2] != 0)
			{
				puts("Invalid command");
				isInvalid = true;
				return;
			}
		}
	}

鸭的判定是最麻烦的一步,因为其需要注意的地方比较多。(主要是绊脚的地方多)
鸭可以走到的地方如下图:

[pic here]

	else if (type == 6)
	{
		if (!(abs(sx - tx) == 3 && abs(sy - ty) == 2) && !(abs(sx - tx) == 2 && abs(sy - ty) == 3))
		{
			puts("Invalid command");
			isInvalid = true;
			return;
		}
		int kx = (tx - sx > 0) ? 1 : -1;
		int ky = (ty - sy > 0) ? 1 : -1;
		if (abs(sx - tx) > abs(sy - ty))
		{
			if (base[sx + kx][sy] != 0 || base[sx + 2 * kx][sy + ky] != 0)
			{
				puts("Invalid command");
				isInvalid = true;
				return;
			}
		}
		else
		{
			if (base[sx][sy + ky] != 0 || base[sx + kx][sy + 2 * ky] != 0)
			{
				puts("Invalid command");
				isInvalid = true;
				return;
			}
		}
	}

兵能走到的地方是与其八联通的格子:

[pic here]

	else if (type == 7)
	{
		if (abs(sx - tx) > 1 || abs(sy - ty) > 1)
		{
			puts("Invalid command");
			isInvalid = true;
			return;
		}
	}

判定是否将军

我们判断是否将军的函数其实与移动的函数差不多,但是我不会写(雾)

我这里用的是判断王能不能被攻击到的方法。

一个让我调了很长时间的一点就是,我这里还需要转化一下参考系,所以绊脚的位置不一样了。

bool checkMate(int k)
{
	int x = 0, y = 0;
	for (int i = 0; i <= 8; i++)
		for (int j = 0; j <= 9; j++)
			if (base[i][j] == (k ^ 1) * 10 + 1)
			{
				x = i;
				y = j;
				break;
			}
	bool flag = false;
	for (int i = x + 1; i <= 8; i++)
	{
		if (base[i][y] == k * 10 + 5)
		{
			flag = true;
			break;
		}
		else if (base[i][y] != 0)break;
	}
	for (int i = x - 1; i >= 0; i--)
	{
		if (base[i][y] == k * 10 + 5)
		{
			flag = true;
			break;
		}
		else if (base[i][y] != 0)break;
	}
	for (int i = y + 1; i <= 9; i++)
	{
		if (base[x][i] == k * 10 + 5)
		{
			flag = true;
			break;
		}
		else if (base[x][i] != 0)break;
	}
	for (int i = y - 1; i >= 0; i--)
	{
		if (base[x][i] == k * 10 + 5)
		{
			flag = true;
			break;
		}
		else if (base[x][i] != 0)break;
	}
	if (flag)return flag;
	if (x <= 7 && base[x + 1][y] == k * 10 + 1)flag = true;
	if (y <= 8 && base[x][y + 1] == k * 10 + 1)flag = true;
	if (x >= 1 && base[x - 1][y] == k * 10 + 1)flag = true;
	if (y >= 1 && base[x][y - 1] == k * 10 + 1)flag = true;
	if (flag)return flag;
	if (x <= 7 && y <= 8 && base[x + 1][y + 1] == k * 10 + 2)flag = true;
	if (x >= 1 && y <= 8 && base[x - 1][y + 1] == k * 10 + 2)flag = true;
	if (x <= 7 && y >= 1 && base[x + 1][y - 1] == k * 10 + 2)flag = true;
	if (x >= 1 && y >= 1 && base[x - 1][y - 1] == k * 10 + 2)flag = true;
	if (flag)return flag;
	if (x <= 7 && y <= 8 && base[x + 1][y + 1] == k * 10 + 7)flag = true;
	if (x >= 1 && y <= 8 && base[x - 1][y + 1] == k * 10 + 7)flag = true;
	if (x <= 7 && y >= 1 && base[x + 1][y - 1] == k * 10 + 7)flag = true;
	if (x >= 1 && y >= 1 && base[x - 1][y - 1] == k * 10 + 7)flag = true;
	if (x <= 7 && base[x + 1][y] == k * 10 + 7)flag = true;
	if (y <= 8 && base[x - 1][y] == k * 10 + 7)flag = true;
	if (x >= 1 && base[x][y + 1] == k * 10 + 7)flag = true;
	if (y >= 1 && base[x][y - 1] == k * 10 + 7)flag = true;
	if (flag)return flag;
	if (x <= 6 && y <= 8 && base[x + 2][y + 1] == k * 10 + 4 && base[x + 1][y + 1] == 0)flag = true;
	if (x >= 2 && y <= 8 && base[x - 2][y + 1] == k * 10 + 4 && base[x - 1][y + 1] == 0)flag = true;
	if (x <= 6 && y >= 1 && base[x + 2][y - 1] == k * 10 + 4 && base[x + 1][y - 1] == 0)flag = true;
	if (x >= 2 && y >= 1 && base[x - 2][y - 1] == k * 10 + 4 && base[x - 1][y - 1] == 0)flag = true;
	if (x <= 7 && y <= 7 && base[x + 1][y + 2] == k * 10 + 4 && base[x + 1][y + 1] == 0)flag = true;
	if (x >= 1 && y <= 7 && base[x - 1][y + 2] == k * 10 + 4 && base[x - 1][y + 1] == 0)flag = true;
	if (x <= 7 && y >= 2 && base[x + 1][y - 2] == k * 10 + 4 && base[x + 1][y - 1] == 0)flag = true;
	if (x >= 1 && y >= 2 && base[x - 1][y - 2] == k * 10 + 4 && base[x - 1][y - 1] == 0)flag = true;
	if (flag)return flag;
	if (x <= 6 && y <= 7 && base[x + 2][y + 2] == k * 10 + 3 && base[x + 1][y + 1] == 0)flag = true;
	if (x >= 2 && y <= 7 && base[x - 2][y + 2] == k * 10 + 3 && base[x - 1][y + 1] == 0)flag = true;
	if (x <= 6 && y >= 2 && base[x + 2][y - 2] == k * 10 + 3 && base[x + 1][y - 1] == 0)flag = true;
	if (x >= 2 && y >= 2 && base[x - 2][y - 2] == k * 10 + 3 && base[x - 1][y - 1] == 0)flag = true;
	if (flag)return flag;
	if (x <= 5 && y <= 7 && base[x + 3][y + 2] == k * 10 + 6 && base[x + 1][y + 1] == 0 && base[x + 2][y + 2] == 0)flag = true;
	if (x >= 3 && y <= 7 && base[x - 3][y + 2] == k * 10 + 6 && base[x - 1][y + 1] == 0 && base[x - 2][y + 2] == 0)flag = true;
	if (x <= 5 && y >= 2 && base[x + 3][y - 2] == k * 10 + 6 && base[x + 1][y - 1] == 0 && base[x + 2][y - 2] == 0)flag = true;
	if (x >= 3 && y >= 2 && base[x - 3][y - 2] == k * 10 + 6 && base[x - 1][y - 1] == 0 && base[x - 2][y - 2] == 0)flag = true;
	if (x <= 6 && y <= 6 && base[x + 2][y + 3] == k * 10 + 6 && base[x + 1][y + 1] == 0 && base[x + 2][y + 2] == 0)flag = true;
	if (x >= 2 && y <= 6 && base[x - 2][y + 3] == k * 10 + 6 && base[x - 1][y + 1] == 0 && base[x - 2][y + 2] == 0)flag = true;
	if (x <= 6 && y >= 3 && base[x + 2][y - 3] == k * 10 + 6 && base[x + 1][y - 1] == 0 && base[x + 2][y - 2] == 0)flag = true;
	if (x >= 2 && y >= 3 && base[x - 2][y - 3] == k * 10 + 6 && base[x - 1][y - 1] == 0 && base[x - 2][y - 2] == 0)flag = true;
	return flag;
}

然后就没有大的操作了。
判断是否结束游戏就看被移除的棋子类型即可。
输出的时候直接switch case就可以了。


全部加起来:

C++:

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int base[20][20];
bool isCaptured = false;
bool isInvalid = false;
bool isCheckmate = false;
int side = 0;
int sx, sy, tx, ty;
int knockOut = 0;
int cnt = 0;
void initMap()
{
	memset(base, 0, sizeof(base));
	base[4][0] = 1;
	base[4][9] = 11;
	base[3][0] = base[5][0] = 2;
	base[3][9] = base[5][9] = 12;
	base[2][0] = base[6][0] = 3;
	base[2][9] = base[6][9] = 13;
	base[1][0] = base[7][0] = 4;
	base[1][9] = base[7][9] = 14;
	base[0][0] = base[8][0] = 5;
	base[0][9] = base[8][9] = 15;
	base[0][2] = base[8][2] = 6;
	base[0][7] = base[8][7] = 16;
	base[0][3] = base[2][3] = base[4][3] = base[6][3] = base[8][3] = 7;
	base[0][6] = base[2][6] = base[4][6] = base[6][6] = base[8][6] = 17;
}

void init()
{
	isInvalid = false;
	isCheckmate = false;
	knockOut = 0;
}

void checkOut()
{
	bool flag = false;
	if (sx < 0)flag = true;
	if (sx > 8)flag = true;
	if (sx < 0)flag = true;
	if (sy > 9)flag = true;
	if (tx < 0)flag = true;
	if (tx > 8)flag = true;
	if (tx < 0)flag = true;
	if (ty > 9)flag = true;
	if (flag)
	{
		puts("Invalid command");
		isInvalid = true;
	}
}

void move()
{
	if (base[sx][sy] / 10 != side)
	{
		puts("Invalid command");
		isInvalid = true;
		return;
	}
	else if (base[sx][sy] == 0)
	{
		puts("Invalid command");
		isInvalid = true;
		return;
	}
	else if (base[tx][ty] / 10 == side && base[tx][ty] != 0)
	{
		puts("Invalid command");
		isInvalid = true;
		return;
	}
	int type = base[sx][sy] % 10;
	if (type == 1)
	{
		if (abs(sx - tx) + abs(sy - ty) > 1)
		{
			puts("Invalid command");
			isInvalid = true;
			return;
		}
	}
	else if (type == 2)
	{
		if (abs(sx - tx) != 1 || abs(sy - ty) != 1)
		{
			puts("Invalid command");
			isInvalid = true;
			return;
		}
	}
	else if (type == 3)
	{
		if (abs(sx - tx) != 2 || abs(sy - ty) != 2)
		{
			puts("Invalid command");
			isInvalid = true;
			return;
		}
		if (base[(sx + tx) / 2][(sy + ty) / 2] != 0)
		{
			puts("Invalid command");
			isInvalid = true;
			return;
		}
	}
	else if (type == 4)
	{
		if (!(abs(sx - tx) == 2 && abs(sy - ty) == 1) && !(abs(sx - tx) == 1 && abs(sy - ty) == 2))
		{
			puts("Invalid command");
			isInvalid = true;
			return;
		}
		if (abs(sx - tx) > abs(sy - ty))
		{
			if (base[sx + (tx - sx) / 2][sy] != 0)
			{
				puts("Invalid command");
				isInvalid = true;
				return;
			}
		}
		else
		{
			if (base[sx][sy + (ty - sy) / 2] != 0)
			{
				puts("Invalid command");
				isInvalid = true;
				return;
			}
		}
	}
	else if (type == 5)
	{
		if (sx != tx && sy != ty)
		{
			puts("Invalid command");
			isInvalid = true;
			return;
		}
		bool collide = false;
		if (sx != tx)
		{
			int tmpx = min(sx, tx);
			for (int i = tmpx + 1; i < max(sx, tx); i++)
			{
				if (base[i][sy] != 0)
				{
					collide = true;
					break;
				}
			}
		}
		else if (sy != ty)
		{
			int tmpy = min(sy, ty);
			for (int i = tmpy + 1; i < max(sy, ty); i++)
			{
				if (base[sx][i] != 0)
				{
					collide = true;
					break;
				}
			}
		}
		if (collide)
		{
			puts("Invalid command");
			isInvalid = true;
			return;
		}
	}
	else if (type == 6)
	{
		if (!(abs(sx - tx) == 3 && abs(sy - ty) == 2) && !(abs(sx - tx) == 2 && abs(sy - ty) == 3))
		{
			puts("Invalid command");
			isInvalid = true;
			return;
		}
		int kx = (tx - sx > 0) ? 1 : -1;
		int ky = (ty - sy > 0) ? 1 : -1;
		if (abs(sx - tx) > abs(sy - ty))
		{
			if (base[sx + kx][sy] != 0 || base[sx + 2 * kx][sy + ky] != 0)
			{
				puts("Invalid command");
				isInvalid = true;
				return;
			}
		}
		else
		{
			if (base[sx][sy + ky] != 0 || base[sx + kx][sy + 2 * ky] != 0)
			{
				puts("Invalid command");
				isInvalid = true;
				return;
			}
		}
	}
	else if (type == 7)
	{
		if (abs(sx - tx) > 1 || abs(sy - ty) > 1)
		{
			puts("Invalid command");
			isInvalid = true;
			return;
		}
	}

	knockOut = base[tx][ty];
	base[tx][ty] = base[sx][sy];
	base[sx][sy] = 0;
}

bool checkMate(int k)
{
	int x = 0, y = 0;
	for (int i = 0; i <= 8; i++)
		for (int j = 0; j <= 9; j++)
			if (base[i][j] == (k ^ 1) * 10 + 1)
			{
				x = i;
				y = j;
				break;
			}
	bool flag = false;
	for (int i = x + 1; i <= 8; i++)
	{
		if (base[i][y] == k * 10 + 5)
		{
			flag = true;
			break;
		}
		else if (base[i][y] != 0)break;
	}
	for (int i = x - 1; i >= 0; i--)
	{
		if (base[i][y] == k * 10 + 5)
		{
			flag = true;
			break;
		}
		else if (base[i][y] != 0)break;
	}
	for (int i = y + 1; i <= 9; i++)
	{
		if (base[x][i] == k * 10 + 5)
		{
			flag = true;
			break;
		}
		else if (base[x][i] != 0)break;
	}
	for (int i = y - 1; i >= 0; i--)
	{
		if (base[x][i] == k * 10 + 5)
		{
			flag = true;
			break;
		}
		else if (base[x][i] != 0)break;
	}
	if (flag)return flag;
	if (x <= 7 && base[x + 1][y] == k * 10 + 1)flag = true;
	if (y <= 8 && base[x][y + 1] == k * 10 + 1)flag = true;
	if (x >= 1 && base[x - 1][y] == k * 10 + 1)flag = true;
	if (y >= 1 && base[x][y - 1] == k * 10 + 1)flag = true;
	if (flag)return flag;
	if (x <= 7 && y <= 8 && base[x + 1][y + 1] == k * 10 + 2)flag = true;
	if (x >= 1 && y <= 8 && base[x - 1][y + 1] == k * 10 + 2)flag = true;
	if (x <= 7 && y >= 1 && base[x + 1][y - 1] == k * 10 + 2)flag = true;
	if (x >= 1 && y >= 1 && base[x - 1][y - 1] == k * 10 + 2)flag = true;
	if (flag)return flag;
	if (x <= 7 && y <= 8 && base[x + 1][y + 1] == k * 10 + 7)flag = true;
	if (x >= 1 && y <= 8 && base[x - 1][y + 1] == k * 10 + 7)flag = true;
	if (x <= 7 && y >= 1 && base[x + 1][y - 1] == k * 10 + 7)flag = true;
	if (x >= 1 && y >= 1 && base[x - 1][y - 1] == k * 10 + 7)flag = true;
	if (x <= 7 && base[x + 1][y] == k * 10 + 7)flag = true;
	if (y <= 8 && base[x - 1][y] == k * 10 + 7)flag = true;
	if (x >= 1 && base[x][y + 1] == k * 10 + 7)flag = true;
	if (y >= 1 && base[x][y - 1] == k * 10 + 7)flag = true;
	if (flag)return flag;
	if (x <= 6 && y <= 8 && base[x + 2][y + 1] == k * 10 + 4 && base[x + 1][y + 1] == 0)flag = true;
	if (x >= 2 && y <= 8 && base[x - 2][y + 1] == k * 10 + 4 && base[x - 1][y + 1] == 0)flag = true;
	if (x <= 6 && y >= 1 && base[x + 2][y - 1] == k * 10 + 4 && base[x + 1][y - 1] == 0)flag = true;
	if (x >= 2 && y >= 1 && base[x - 2][y - 1] == k * 10 + 4 && base[x - 1][y - 1] == 0)flag = true;
	if (x <= 7 && y <= 7 && base[x + 1][y + 2] == k * 10 + 4 && base[x + 1][y + 1] == 0)flag = true;
	if (x >= 1 && y <= 7 && base[x - 1][y + 2] == k * 10 + 4 && base[x - 1][y + 1] == 0)flag = true;
	if (x <= 7 && y >= 2 && base[x + 1][y - 2] == k * 10 + 4 && base[x + 1][y - 1] == 0)flag = true;
	if (x >= 1 && y >= 2 && base[x - 1][y - 2] == k * 10 + 4 && base[x - 1][y - 1] == 0)flag = true;
	if (flag)return flag;
	if (x <= 6 && y <= 7 && base[x + 2][y + 2] == k * 10 + 3 && base[x + 1][y + 1] == 0)flag = true;
	if (x >= 2 && y <= 7 && base[x - 2][y + 2] == k * 10 + 3 && base[x - 1][y + 1] == 0)flag = true;
	if (x <= 6 && y >= 2 && base[x + 2][y - 2] == k * 10 + 3 && base[x + 1][y - 1] == 0)flag = true;
	if (x >= 2 && y >= 2 && base[x - 2][y - 2] == k * 10 + 3 && base[x - 1][y - 1] == 0)flag = true;
	if (flag)return flag;
	if (x <= 5 && y <= 7 && base[x + 3][y + 2] == k * 10 + 6 && base[x + 1][y + 1] == 0 && base[x + 2][y + 2] == 0)flag = true;
	if (x >= 3 && y <= 7 && base[x - 3][y + 2] == k * 10 + 6 && base[x - 1][y + 1] == 0 && base[x - 2][y + 2] == 0)flag = true;
	if (x <= 5 && y >= 2 && base[x + 3][y - 2] == k * 10 + 6 && base[x + 1][y - 1] == 0 && base[x + 2][y - 2] == 0)flag = true;
	if (x >= 3 && y >= 2 && base[x - 3][y - 2] == k * 10 + 6 && base[x - 1][y - 1] == 0 && base[x - 2][y - 2] == 0)flag = true;
	if (x <= 6 && y <= 6 && base[x + 2][y + 3] == k * 10 + 6 && base[x + 1][y + 1] == 0 && base[x + 2][y + 2] == 0)flag = true;
	if (x >= 2 && y <= 6 && base[x - 2][y + 3] == k * 10 + 6 && base[x - 1][y + 1] == 0 && base[x - 2][y + 2] == 0)flag = true;
	if (x <= 6 && y >= 3 && base[x + 2][y - 3] == k * 10 + 6 && base[x + 1][y - 1] == 0 && base[x + 2][y - 2] == 0)flag = true;
	if (x >= 2 && y >= 3 && base[x - 2][y - 3] == k * 10 + 6 && base[x - 1][y - 1] == 0 && base[x - 2][y - 2] == 0)flag = true;
	return flag;
}

void write()
{
	switch (base[tx][ty])
	{
		case 1: { printf("red captain;"); break; }
		case 2: { printf("red guard;"); break; }
		case 3: { printf("red elephant;"); break; }
		case 4: { printf("red horse;"); break; }
		case 5: { printf("red car;"); break; }
		case 6: { printf("red duck;"); break; }
		case 7: { printf("red soldier;"); break; }
		case 11: { printf("blue captain;"); break; }
		case 12: { printf("blue guard;"); break; }
		case 13: { printf("blue elephant;"); break; }
		case 14: { printf("blue horse;"); break; }
		case 15: { printf("blue car;"); break; }
		case 16: { printf("blue duck;"); break; }
		case 17: { printf("blue soldier;"); break; }
	}
	switch (knockOut)
	{
		case 0: { printf("NA;"); break; }
		case 1: { printf("red captain;"); break; }
		case 2: { printf("red guard;"); break; }
		case 3: { printf("red elephant;"); break; }
		case 4: { printf("red horse;"); break; }
		case 5: { printf("red car;"); break; }
		case 6: { printf("red duck;"); break; }
		case 7: { printf("red soldier;"); break; }
		case 11: { printf("blue captain;"); break; }
		case 12: { printf("blue guard;"); break; }
		case 13: { printf("blue elephant;"); break; }
		case 14: { printf("blue horse;"); break; }
		case 15: { printf("blue car;"); break; }
		case 16: { printf("blue duck;"); break; }
		case 17: { printf("blue soldier;"); break; }
	}
	if (knockOut == 1 || knockOut == 11)isCaptured = true;
	if (!isCaptured && isCheckmate)printf("yes;");
	else printf("no;");
	if (isCaptured)printf("yes\n");
	else printf("no\n");
}

int main()
{
	initMap();
	int Q;
	scanf("%d", &Q);
	for (int i = 1; i <= Q; i++)
	{
		init();
		scanf("%d%d%d%d", &sy, &sx, &ty, &tx);
		cnt++;
		if (isCaptured)
		{
			puts("Invalid command");
			continue;
		}
		checkOut();
		move();
		if (isInvalid)continue;
		isCheckmate = checkMate(0) || checkMate(1);
		write();
		side ^= 1;
	}
	return 0;
}

C#:

using System;

namespace Main
{
	class Map
	{
		public int[,] m = new int[20, 20];
		public int side;
		public bool isCaptured;
		public bool isInvalid;
		public bool isCheckmate;
		public int knockOut;
		public int sx, sy, tx, ty;

		public Map()
		{
			Array.Clear(m, 0, m.Length);
			side = 0;
			isCaptured = false;
			isInvalid = false;
			isCheckmate = false;
			knockOut = 0;
			sx = 0; sy = 0; tx = 0; ty = 0;
		}
		public void Init()
		{
			m[4, 0] = 1;
			m[4, 9] = 11;
			m[3, 0] = m[5, 0] = 2;
			m[3, 9] = m[5, 9] = 12;
			m[2, 0] = m[6, 0] = 3;
			m[2, 9] = m[6, 9] = 13;
			m[1, 0] = m[7, 0] = 4;
			m[1, 9] = m[7, 9] = 14;
			m[0, 0] = m[8, 0] = 5;
			m[0, 9] = m[8, 9] = 15;
			m[0, 2] = m[8, 2] = 6;
			m[0, 7] = m[8, 7] = 16;
			m[0, 3] = m[2, 3] = m[4, 3] = m[6, 3] = m[8, 3] = 7;
			m[0, 6] = m[2, 6] = m[4, 6] = m[6, 6] = m[8, 6] = 17;
		}
		public void Clear()
		{
			isInvalid = false;
			isCheckmate = false;
			knockOut = 0;
		}

		public void CheckOut()
		{
			bool flag = false;
			if (sx < 0 || sx > 8) flag = true;
			if (sy < 0 || sy > 9) flag = true;
			if (tx < 0 || tx > 8) flag = true;
			if (ty < 0 || ty > 9) flag = true;
			if (flag)
			{
				Console.WriteLine("Invalid command");
				isInvalid = true;
			}
		}

		public void Move()
		{
			if (m[sx, sy] / 10 != side)
			{
				Console.WriteLine("Invalid command");
				isInvalid = true;
				return;
			}
			else if (m[sx, sy] == 0)
			{
				Console.WriteLine("Invalid command");
				isInvalid = true;
				return;
			}
			else if (m[tx, ty] / 10 == side && m[tx, ty] != 0)
			{
				Console.WriteLine("Invalid command");
				isInvalid = true;
				return;
			}

			int type = m[sx, sy] % 10;
			if (type == 1)
			{
				if (Math.Abs(sx - tx) + Math.Abs(sy - ty) > 1)
				{
					Console.WriteLine("Invalid command");
					isInvalid = true;
					return;
				}
			}
			else if (type == 2)
			{
				if (Math.Abs(sx - tx) != 1 || Math.Abs(sy - ty) != 1)
				{
					Console.WriteLine("Invalid command");
					isInvalid = true;
					return;
				}
			}
			else if (type == 3)
			{
				if (Math.Abs(sx - tx) != 2 || Math.Abs(sy - ty) != 2)
				{
					Console.WriteLine("Invalid command");
					isInvalid = true;
					return;
				}
				if (m[(sx + tx) / 2, (sy + ty) / 2] != 0)
				{
					Console.WriteLine("Invalid command");
					isInvalid = true;
					return;
				}
			}
			else if (type == 4)
			{
				if (!(Math.Abs(sx - tx) == 2 && Math.Abs(sy - ty) == 1) && !(Math.Abs(sx - tx) == 1 && Math.Abs(sy - ty) == 2))
				{
					Console.WriteLine("Invalid command");
					isInvalid = true;
					return;
				}
				if (Math.Abs(sx - tx) > Math.Abs(sy - ty))
				{
					if (m[sx + (tx - sx) / 2, sy] != 0)
					{
						Console.WriteLine("Invalid command");
						isInvalid = true;
						return;
					}
				}
				else
				{
					if (m[sx, sy + (ty - sy) / 2] != 0)
					{
						Console.WriteLine("Invalid command");
						isInvalid = true;
						return;
					}
				}
			}
			else if (type == 5)
			{
				if (sx != tx && sy != ty)
				{
					Console.WriteLine("Invalid command");
					isInvalid = true;
					return;
				}
				bool RookCollide = false;
				if (sx != tx)
				{
					for (int i = Math.Min(sx, tx) + 1; i < Math.Max(sx, tx); i++)
					{
						if (m[i, sy] != 0)
						{
							RookCollide = true;
							break;
						}
					}
				}
				else
				{
					for (int i = Math.Min(sy, ty) + 1; i < Math.Max(sy, ty); i++)
					{
						if (m[sx, i] != 0)
						{
							RookCollide = true;
							break;
						}
					}
				}
				if (RookCollide)
				{
					Console.WriteLine("Invalid command");
					isInvalid = true;
					return;
				}
			}
			else if (type == 6)
			{
				if (!(Math.Abs(sx - tx) == 3 && Math.Abs(sy - ty) == 2) && !(Math.Abs(sx - tx) == 2 && Math.Abs(sy - ty) == 3))
				{
					Console.WriteLine("Invalid command");
					isInvalid = true;
					return;
				}
				int kx = (tx - sx > 0) ? 1 : -1;
				int ky = (ty - sy > 0) ? 1 : -1;
				if (Math.Abs(sx - tx) > Math.Abs(sy - ty))
				{
					if (m[sx + kx, sy] != 0 || m[sx + 2 * kx, sy + ky] != 0)
					{
						Console.WriteLine("Invalid command");
						isInvalid = true;
						return;
					}
				}
				else
				{
					if (m[sx, sy + ky] != 0 || m[sx + kx, sy + 2 * ky] != 0)
					{
						Console.WriteLine("Invalid command");
						isInvalid = true;
						return;
					}
				}
			}
			else if (type == 7)
			{

				if (Math.Abs(sx - tx) > 1 || Math.Abs(sy - ty) > 1)
				{
					Console.WriteLine("Invalid command");
					isInvalid = true;
					return;
				}
			}

			knockOut = m[tx, ty];
			m[tx, ty] = m[sx, sy];
			m[sx, sy] = 0;
		}

		public bool CheckMate(int k)
		{
			int x = 0, y = 0;
			for (int i = 0; i <= 8; i++)
			{
				for (int j = 0; j <= 9; j++)
				{
					if (m[i, j] == (k ^ 1) * 10 + 1)
					{
						x = i; y = j;
						break;
					}
				}
			}

			bool flag = false;

			for (int i = x + 1; i <= 8; i++)
			{
				if (m[i, y] == k * 10 + 5)
				{
					flag = true;
					break;
				}
				else if (m[i, y] != 0) break;
			}
			for (int i = x - 1; i >= 0; i--)
			{
				if (m[i, y] == k * 10 + 5)
				{
					flag = true;
					break;
				}
				else if (m[i, y] != 0) break;
			}
			for (int i = y + 1; i <= 9; i++)
			{
				if (m[x, i] == k * 10 + 5)
				{
					flag = true;
					break;
				}
				else if (m[x, i] != 0) break;
			}
			for (int i = y - 1; i >= 0; i--)
			{
				if (m[x, i] == k * 10 + 5)
				{
					flag = true;
					break;
				}
				else if (m[x, i] != 0) break;
			}
			if (flag) return flag;
			if (x <= 7 && m[x + 1, y] == k * 10 + 1) flag = true;
			if (y <= 8 && m[x, y + 1] == k * 10 + 1) flag = true;
			if (x >= 1 && m[x - 1, y] == k * 10 + 1) flag = true;
			if (y >= 1 && m[x, y - 1] == k * 10 + 1) flag = true;
			if (flag) return flag;
			if (x <= 7 && y <= 8 && m[x + 1, y + 1] == k * 10 + 2) flag = true;
			if (x >= 1 && y <= 8 && m[x - 1, y + 1] == k * 10 + 2) flag = true;
			if (x <= 7 && y >= 1 && m[x + 1, y - 1] == k * 10 + 2) flag = true;
			if (x >= 1 && y >= 1 && m[x - 1, y - 1] == k * 10 + 2) flag = true;
			if (flag) return flag;
			if (x <= 7 && m[x + 1, y] == k * 10 + 7) flag = true;
			if (y <= 8 && m[x, y + 1] == k * 10 + 7) flag = true;
			if (x >= 1 && m[x - 1, y] == k * 10 + 7) flag = true;
			if (y >= 1 && m[x, y - 1] == k * 10 + 7) flag = true;
			if (x <= 7 && y <= 8 && m[x + 1, y + 1] == k * 10 + 7) flag = true;
			if (x >= 1 && y <= 8 && m[x - 1, y + 1] == k * 10 + 7) flag = true;
			if (x <= 7 && y >= 1 && m[x + 1, y - 1] == k * 10 + 7) flag = true;
			if (x >= 1 && y >= 1 && m[x - 1, y - 1] == k * 10 + 7) flag = true;
			if (flag) return flag;
			if (x <= 6 && y <= 8 && m[x + 2, y + 1] == k * 10 + 4 && m[x + 1, y + 1] == 0) flag = true;
			if (x >= 2 && y <= 8 && m[x - 2, y + 1] == k * 10 + 4 && m[x - 1, y + 1] == 0) flag = true;
			if (x <= 6 && y >= 1 && m[x + 2, y - 1] == k * 10 + 4 && m[x + 1, y - 1] == 0) flag = true;
			if (x >= 2 && y >= 1 && m[x - 2, y - 1] == k * 10 + 4 && m[x - 1, y - 1] == 0) flag = true;
			if (x <= 7 && y <= 7 && m[x + 1, y + 2] == k * 10 + 4 && m[x + 1, y + 1] == 0) flag = true;
			if (x >= 1 && y <= 7 && m[x - 1, y + 2] == k * 10 + 4 && m[x - 1, y + 1] == 0) flag = true;
			if (x <= 7 && y >= 2 && m[x + 1, y - 2] == k * 10 + 4 && m[x + 1, y - 1] == 0) flag = true;
			if (x >= 1 && y >= 2 && m[x - 1, y - 2] == k * 10 + 4 && m[x - 1, y - 1] == 0) flag = true;
			if (flag) return flag;
			if (x <= 6 && y <= 7 && m[x + 2, y + 2] == k * 10 + 3 && m[x + 1, y + 1] == 0) flag = true;
			if (x >= 2 && y <= 7 && m[x - 2, y + 2] == k * 10 + 3 && m[x - 1, y + 1] == 0) flag = true;
			if (x <= 6 && y >= 2 && m[x + 2, y - 2] == k * 10 + 3 && m[x + 1, y - 1] == 0) flag = true;
			if (x >= 2 && y >= 2 && m[x - 2, y - 2] == k * 10 + 3 && m[x - 1, y - 1] == 0) flag = true;
			if (flag) return flag;
			if (x <= 5 && y <= 7 && m[x + 3, y + 2] == k * 10 + 6 && m[x + 2, y + 2] == 0 && m[x + 1, y + 1] == 0) flag = true;
			if (x >= 3 && y <= 7 && m[x - 3, y + 2] == k * 10 + 6 && m[x - 2, y + 2] == 0 && m[x - 1, y + 1] == 0) flag = true;
			if (x <= 5 && y >= 2 && m[x + 3, y - 2] == k * 10 + 6 && m[x + 2, y - 2] == 0 && m[x + 1, y - 1] == 0) flag = true;
			if (x >= 3 && y >= 2 && m[x - 3, y - 2] == k * 10 + 6 && m[x - 2, y - 2] == 0 && m[x - 1, y - 1] == 0) flag = true;
			if (x <= 6 && y <= 6 && m[x + 2, y + 3] == k * 10 + 6 && m[x + 2, y + 2] == 0 && m[x + 1, y + 1] == 0) flag = true;
			if (x >= 2 && y <= 6 && m[x - 2, y + 3] == k * 10 + 6 && m[x - 2, y + 2] == 0 && m[x - 1, y + 1] == 0) flag = true;
			if (x <= 6 && y >= 3 && m[x + 2, y - 3] == k * 10 + 6 && m[x + 2, y - 2] == 0 && m[x + 1, y - 1] == 0) flag = true;
			if (x >= 2 && y >= 3 && m[x - 2, y - 3] == k * 10 + 6 && m[x - 2, y - 2] == 0 && m[x - 1, y - 1] == 0) flag = true;
			return flag;
		}

		public void Write()
		{
			switch (m[tx, ty])
			{
				case 1: { Console.Write("red captain;"); break; }
				case 2: { Console.Write("red guard;"); break; }
				case 3: { Console.Write("red elephant;"); break; }
				case 4: { Console.Write("red horse;"); break; }
				case 5: { Console.Write("red car;"); break; }
				case 6: { Console.Write("red duck;"); break; }
				case 7: { Console.Write("red soldier;"); break; }
				case 11: { Console.Write("blue captain;"); break; }
				case 12: { Console.Write("blue guard;"); break; }
				case 13: { Console.Write("blue elephant;"); break; }
				case 14: { Console.Write("blue horse;"); break; }
				case 15: { Console.Write("blue car;"); break; }
				case 16: { Console.Write("blue duck;"); break; }
				case 17: { Console.Write("blue soldier;"); break; }
			}
			switch (knockOut)
			{
				case 0: { Console.Write("NA;"); break; }
				case 1: { Console.Write("red captain;"); break; }
				case 2: { Console.Write("red guard;"); break; }
				case 3: { Console.Write("red elephant;"); break; }
				case 4: { Console.Write("red horse;"); break; }
				case 5: { Console.Write("red car;"); break; }
				case 6: { Console.Write("red duck;"); break; }
				case 7: { Console.Write("red soldier;"); break; }
				case 11: { Console.Write("blue captain;"); break; }
				case 12: { Console.Write("blue guard;"); break; }
				case 13: { Console.Write("blue elephant;"); break; }
				case 14: { Console.Write("blue horse;"); break; }
				case 15: { Console.Write("blue car;"); break; }
				case 16: { Console.Write("blue duck;"); break; }
				case 17: { Console.Write("blue soldier;"); break; }
			}
			if (knockOut == 1 || knockOut == 11) isCaptured = true;
			if (!isCaptured && isCheckmate) Console.Write("yes;");
			else Console.Write("no;");
			if (isCaptured) Console.WriteLine("yes");
			else Console.WriteLine("no");
		}
	}

	class MainClass
	{
		static public int Read()
		{
			int x = 0;
			int c = Console.Read();
			while (c < '0' || c > '9') c = Console.Read();
			while (c >= '0' && c <= '9')
			{
				x = (x * 10) + (c - 48);
				c = Console.Read();
			}
			return x;
		}
		public static void Main(string[] args)
		{
			Map map = new Map();
			map.Init();
			int Q = Read();
			for (int i = 1; i <= Q; i++)
			{
				map.Clear();
				map.sy = Read();
				map.sx = Read();
				map.ty = Read();
				map.tx = Read();
				if (map.isCaptured)
				{
					Console.WriteLine("Invalid command");
					continue;
				}
				map.CheckOut();
				map.Move();
				if (map.isInvalid) continue;
				map.isCheckmate = map.CheckMate(0) || map.CheckMate(1);
				map.Write();
				map.side ^= 1;
			}
		}
	}
}
posted @ 2022-07-15 17:04  南陽劉子驥  阅读(63)  评论(0)    收藏  举报