P5380 [THUPC2019] 鸭棋 题解

这是我写出的第一道紫题。纪念一下。

题目

我们用数字代表棋子。对于这个数字的个位,让 1代表 car2代表 horse3代表 guard4代表 elephant5代表 captain6 代表 duck7代表 soldier。对于这个数字的十位,让 0代表蓝方,让1代表红方。

我们先写好判断棋子移动是否合法的函数,由于有 7 7 7 种棋子,所以就有 7 7 7 个函数:

bool movecar(int sx, int sy, int ex, int ey) {
	if (sx != ex && sy != ey) return 0;
	if (m[ex][ey] && m[sx][sy] / 10 == m[ex][ey] / 10)
		return 0;
	if (sx == ex) {
		for (int i = sy + dir(ey - sy); i != ey; i += dir(ey - sy)) {
			if (m[sx][i]) return 0;
		}
		return 1;
	}
	else {
		for (int i = sx + dir(ex - sx); i != ex; i += dir(ex - sx)) {
			if (m[i][sy]) return 0;
		}
		return 1;
	}
	return 0;
}
bool movecaptain(int sx, int sy, int ex, int ey) {
	if (m[ex][ey] && m[sx][sy] / 10 == m[ex][ey] / 10)
		return 0;
	if (abs(ex - sx) + abs(ey - sy) == 1) {
		return 1;
	}
	return 0;
}
bool moveguard(int sx, int sy, int ex, int ey) {
	if (m[ex][ey] && m[sx][sy] / 10 == m[ex][ey] / 10) {
		return 0;
	}
	if (abs(sx - ex) == 1 && abs(ey - sy) == 1) {
		return 1;
	}
	return 0;
}
bool moveelephant(int sx, int sy, int ex, int ey) {
	if (m[ex][ey] && m[sx][sy] / 10 == m[ex][ey] / 10)
		return 0;
	if (abs(ex - sx) == 2 && abs(ey - sy) == 2) {
		int dx = dir(ex - sx), dy = dir(ey - sy);
		if (!m[sx + dx][sy + dy]) {
			return 1;
		}
	}
	return 0;
}
bool movehorse(int sx, int sy, int ex, int ey) {
	if (m[ex][ey] && m[sx][sy] / 10 == m[ex][ey] / 10)
		return 0;
	if (abs(sx - ex) && abs(sy - ey)
		&& abs(sx - ex) + abs(sy - ey) == 3) {
		int dx = abs(ex - sx) - 1,
		dy = abs(ey - sy) - 1;
		dx *= dir(ex - sx);
		dy *= dir(ey - sy);
		if (!m[sx + dx][sy + dy]) {
			return 1;
		}
	}
	return 0;
}
bool moveduck(int sx, int sy, int ex, int ey) {
	int dx = dir(ex - sx), dy = dir(ey - sy);
	if (m[ex][ey] && m[sx][sy] / 10 == m[ex][ey] / 10)
		return 0;
	if ((abs(ex - sx) == 2 && abs(ey - sy) == 3)) {
		if (!m[sx + dx][sy + dy * 2]) {
			if (!m[sx][sy + dy]) {
				return 1;
			}
		}
	}
	else if (abs(ex - sx) == 3 && abs(ey - sy) == 2){
		if (!m[sx + dx * 2][sy + dy]) {
			if (!m[sx + dx][sy]) {
				return 1;
			}
		}
	}
	return 0;
}
bool movesoldier(int sx, int sy, int ex, int ey) {
	if (m[ex][ey] && m[sx][sy] / 10 == m[ex][ey] / 10)
		return 0;
	if (abs(sx - ex) <= 1 && abs(sy - ey) <= 1) {
		return 1;
	}
	return 0;
}

写好这 7 7 7 个函数之后,我们判断输入的棋子是不是我们自己的,如果不是,就代表这个命令不合法。如果是,就判断棋子类型,把我们写的函数丢进去。如果合法,就执行移动步骤,然后就是判断将军。我用了一个很粗暴的方法:找到每一个captain,然后枚举另一方的棋子,如果这个棋子移动到captain位置是合法的,就代表将军了。

判断结束很简单,如果被移走的棋子是 captain,就代表这个游戏结束了。

注意:移走棋子时要把原来的位置设为空白,xy 坐标不要搞反,我因为这个调了 3h。

AC Code:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
int q;
map<int, string> m1, m2;
void init() {
	m1[1] = "car", m1[2] = "horse";
	m1[3] = "guard", m1[4] = "elephant";
	m1[5] = "captain", m1[6] = "duck";
	m1[7] = "soldier";
	m2[0] = "blue", m2[1] = "red";
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> q;
}
int m[15][15] = {
	{11, 12, 14, 13, 15, 13, 14, 12, 11},
	{00, 00, 00, 00, 00, 00, 00, 00, 00},
	{16, 00, 00, 00, 00, 00, 00, 00, 16},
	{17, 00, 17, 00, 17, 00, 17, 00, 17},
	{00, 00, 00, 00, 00, 00, 00, 00, 00},
	{00, 00, 00, 00, 00, 00, 00, 00, 00},
	{07, 00, 07, 00, 07, 00, 07, 00, 07},
	{06, 00, 00, 00, 00, 00, 00, 00, 06},
	{00, 00, 00, 00, 00, 00, 00, 00, 00},
	{01, 02, 04, 03, 05, 03, 04, 02, 01},
};
int dir(int x) {return x > 0 ? 1 : -1;}
bool movecar(int sx, int sy, int ex, int ey) {
	if (sx != ex && sy != ey) return 0;
	if (m[ex][ey] && m[sx][sy] / 10 == m[ex][ey] / 10)
		return 0;
	if (sx == ex) {
		for (int i = sy + dir(ey - sy); i != ey; i += dir(ey - sy)) {
			if (m[sx][i]) return 0;
		}
		return 1;
	}
	else {
		for (int i = sx + dir(ex - sx); i != ex; i += dir(ex - sx)) {
			if (m[i][sy]) return 0;
		}
		return 1;
	}
	return 0;
}
bool movecaptain(int sx, int sy, int ex, int ey) {
	if (m[ex][ey] && m[sx][sy] / 10 == m[ex][ey] / 10)
		return 0;
	if (abs(ex - sx) + abs(ey - sy) == 1) {
		return 1;
	}
	return 0;
}
bool moveguard(int sx, int sy, int ex, int ey) {
	if (m[ex][ey] && m[sx][sy] / 10 == m[ex][ey] / 10) {
		return 0;
	}
	if (abs(sx - ex) == 1 && abs(ey - sy) == 1) {
		return 1;
	}
	return 0;
}
bool moveelephant(int sx, int sy, int ex, int ey) {
	if (m[ex][ey] && m[sx][sy] / 10 == m[ex][ey] / 10)
		return 0;
	if (abs(ex - sx) == 2 && abs(ey - sy) == 2) {
		int dx = dir(ex - sx), dy = dir(ey - sy);
		if (!m[sx + dx][sy + dy]) {
			return 1;
		}
	}
	return 0;
}
bool movehorse(int sx, int sy, int ex, int ey) {
	if (m[ex][ey] && m[sx][sy] / 10 == m[ex][ey] / 10)
		return 0;
	if (abs(sx - ex) && abs(sy - ey)
		&& abs(sx - ex) + abs(sy - ey) == 3) {
		int dx = abs(ex - sx) - 1,
		dy = abs(ey - sy) - 1;
		dx *= dir(ex - sx);
		dy *= dir(ey - sy);
		if (!m[sx + dx][sy + dy]) {
			return 1;
		}
	}
	return 0;
}
bool moveduck(int sx, int sy, int ex, int ey) {
	int dx = dir(ex - sx), dy = dir(ey - sy);
	if (m[ex][ey] && m[sx][sy] / 10 == m[ex][ey] / 10)
		return 0;
	if ((abs(ex - sx) == 2 && abs(ey - sy) == 3)) {
		if (!m[sx + dx][sy + dy * 2]) {
			if (!m[sx][sy + dy]) {
				return 1;
			}
		}
	}
	else if (abs(ex - sx) == 3 && abs(ey - sy) == 2){
		if (!m[sx + dx * 2][sy + dy]) {
			if (!m[sx + dx][sy]) {
				return 1;
			}
		}
	}
	return 0;
}
bool movesoldier(int sx, int sy, int ex, int ey) {
	if (m[ex][ey] && m[sx][sy] / 10 == m[ex][ey] / 10)
		return 0;
	if (abs(sx - ex) <= 1 && abs(sy - ey) <= 1) {
		return 1;
	}
	return 0;
}
int step = 1;
bool is_end = 0;
bool check(int i, int j) {
	int now = m[i][j] / 10;
	for (int x = 0; x < 10; x ++) {
		for (int y = 0; y < 9; y ++) {
			if (x == i && y == j) continue;
			if (m[x][y] / 10 != now) {
				if (m[x][y] % 10 == 1 && movecar(x, y, i, j)) return 1;
				if (m[x][y] % 10 == 2 && movehorse(x, y, i, j)) return 1;
				if (m[x][y] % 10 == 3 && moveguard(x, y, i, j)) return 1;
				if (m[x][y] % 10 == 4 && moveelephant(x, y, i, j)) return 1;
				if (m[x][y] % 10 == 5 && movecaptain(x, y, i, j)) return 1;
				if (m[x][y] % 10 == 6 && moveduck(x, y, i, j)) return 1;
				if (m[x][y] % 10 == 7 && movesoldier(x, y, i, j)) return 1;
			}
		}
	}
	return 0;
}
int main(){
	init();
	while (q --) {
		int xs, ys, xt, yt;
		cin >> xs >> ys >> xt >> yt;
		int s = m[xs][ys], t = m[xt][yt];
//		cout << s << '\n';
		if (is_end || !s) {
			cout << "Invalid command\n";
			continue;
		}
		if (s / 10 != step % 2) {
			cout << "Invalid command\n";
			continue;
		}
		if (s % 10 == 1) {
			if (!movecar(xs, ys, xt, yt)) {
				cout << "Invalid command\n";
				continue;
			}
		}
		else if (s % 10 == 2) {
			if (!movehorse(xs, ys, xt, yt)) {
				cout << "Invalid command\n";
				continue;
			}
		}
		else if (s % 10 == 3) {
			if (!moveguard(xs, ys, xt, yt)) {
				cout << "Invalid command\n";
				continue;
			}
		}
		else if (s % 10 == 4) {
			if (!moveelephant(xs, ys, xt, yt)) {
				cout << "Invalid command\n";
				continue;
			}
		}
		else if (s % 10 == 5) {
			if (!movecaptain(xs, ys, xt, yt)) {
				cout << "Invalid command\n";
				continue;
			}
		}
		else if (s % 10 == 6) {
			if (!moveduck(xs, ys, xt, yt)) {
				cout << "Invalid command\n";
				continue;
			}
		}
		else if (s % 10 == 7) {
			if (!movesoldier(xs, ys, xt, yt)) {
				cout << "Invalid command\n";
				continue;
			}
		}
		m[xt][yt] = m[xs][ys];
		m[xs][ys] = 0;
		cout << m2[s / 10] << ' ' << m1[s % 10];
		cout << ';';
		if (t) {
			cout << m2[t / 10] << ' ' << m1[t % 10];
		}
		else {
			cout << "NA";
		}
		cout << ';';
		if (t % 10 == 5) {
			is_end = 1;
		}
		if (is_end) cout << "no";
		else {
			bool flag = 0;
			for (int i = 0; i < 10; i ++) {
				for (int j = 0; j < 9; j ++) {
					if (m[i][j] % 10 == 5) {
						if (check(i, j)) {
							flag = 1;
							break;
						}
					}
				}
			}
			if (flag) cout << "yes";
			else cout << "no";
		}
		cout << ';';
		if (is_end) cout << "yes";
		else cout << "no";
		cout << '\n';
		step++;
	}
	return 0;
}

你可能感兴趣的:(c++)