You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

223 lines
7.1 KiB

2 years ago
#include <bits/stdc++.h>
using namespace std;
//小黄鸭调试法他不是精神分裂他只是在debug
//https://www.jianshu.com/p/9317572c438c
// 算法竞赛入门经典(第二版)-刘汝佳-第四章 函数与递归 例题+习题
//https://vjudge.net/contest/106163#overview
//定义初始化数组的简化版本
#define mms(a, b) memset(a,b,sizeof(a))
//递增循环
#define rep(i, n, t) for(int i=(n);i<(t);i++)
//递减循环
#define per(i, n, t) for(int i=(n);i>(t);i--)
#define N 11 //棋盘的高度
#define M 10 //棋盘的宽度
//似乎还有问题,比如黑方将走时,可能吃掉了红方的棋子,这样整个棋盘需要进行一些修改,但这个程序没有进行处理。
//棋盘
char chessboard[N][M];
//是不是被将死
bool cheakmeat = true;
//是不是出界
bool cheak(int x, int y) {
if (x < N && x >= 1 && y < M && y >= 1) return true;
return false;
}
//判断黑方的将是不是可以走到这个位置因为虽然象棋中的将可以向周边四个方向走动但不能出了九宫格也就是有X,Y的范围限定。
bool cheakjiang(int x, int y) {
if (x <= 3 && x >= 1 && y <= 6 && y >= 4) return true;
return false;
}
//判帅
bool judgeG(int x, int y) {
rep(i, x + 1, N) {
if (chessboard[i][y] == 0) {} //这一行的这一列没有棋子
else if (chessboard[i][y] == 'G') return true; //如果存在红方的帅,直接返回吧,不用继续判断,
// 这个其实实现的不怎么样因为1浪费红的就帅不用从x+1判断因为棋盘的最下方三行是红方帅的势力范围出不了界。
// 2实现的不怎么清晰
else return false;
}
return false;
}
//判马
bool judgeH(int x, int y) {
//马能走的8个方向
int temp[8][8]{{1, -2},//右1下
{-1, -2}, //左1下
{2, -1},//右2上
{-2, -1},//左2上
{-2, 1}, //左2下
{2, 1}, //右2上
{-1, 2}, //左1下
{1, 2}}; //右1下
//遍历8个方向
rep(i, 0, 8) {
int xx = x + temp[i][0];
int yy = y + temp[i][1];
//如果没有出界的话
if (cheak(xx, yy)) {
if (chessboard[xx][yy] == 0) {} //这个位置没有棋子,可以走
else if (chessboard[xx][yy] == 'H') //如果进入马的攻击范围
{
//判断是不是别马腿
int x2 = (temp[i][0] * -1) / 2;
int y2 = (temp[i][1] * -1) / 2;
if (chessboard[xx + x2][yy + y2] == 0) //不存在别马腿的
return true;
return false;
}
}
}
return false;
}
//判车
bool judgeR(int x, int y) {
//上方每一行y这一列是不是有车
per(i, x - 1, 0) {
if (chessboard[i][y] == 0) {}
else if (chessboard[i][y] == 'R') return true;
else break;
}
//下方每一行y这一列是不是有车
rep(i, x + 1, N) {
if (chessboard[i][y] == 0) {}
else if (chessboard[i][y] == 'R') return true;
else break;
}
//行上是不是有车?从右向左找车车
per(j, y - 1, 0) {
if (chessboard[x][j] == 0) {}
else if (chessboard[x][j] == 'R' && j != y) return true;
else break;
}
//行上是不是有车?从左向右找车车
rep(j, y + 1, M) {
if (chessboard[x][j] == 0) {}
else if (chessboard[x][j] == 'R' && j != y) return true;
else return false;
}
return false;
}
//判炮(隔山打所以cnt==2才能形成攻击力量也是四个方向两横两纵)
bool judgeC(int x, int y) {
int cnt = 0;
per(i, x - 1, 0) {
if (chessboard[i][y] == 0) {}
else {
cnt++;
if (chessboard[i][y] == 'C') { if (cnt == 2) return true; }
}
}
cnt = 0;
rep(i, x + 1, N) {
if (chessboard[i][y] == 0) {}
else {
cnt++;
if (chessboard[i][y] == 'C') { if (cnt == 2) return true; }
}
}
cnt = 0;
per(j, y - 1, 0) {
if (chessboard[x][j] == 0) {}
else {
cnt++;
if (chessboard[x][j] == 'C') { if (cnt == 2) return true; }
}
}
cnt = 0;
rep(j, y + 1, M) {
if (chessboard[x][j] == 0) {}
else {
cnt++;
if (chessboard[x][j] == 'C') { if (cnt == 2) return true; }
}
}
return false;
}
//功能:判断的主体函数,是至顶向下进行梳理逻辑的主体
void judge(int x, int y) // x+y-->黑方将的位置
{
int temp[4][4]
{
{0, -1}, //向上
{0, 1}, //向下
{-1, 0}, //向左
{1, 0} //向右
};
//如果是与红方帅对脸了,那么被将死
if (judgeG(x, y)) {
cheakmeat = false;
return;
}
//向四个方向逐个尝试
rep(i, 0, 4) {
if (cheakjiang(x + temp[i][0], y + temp[i][1])) //判断这个将,是不是可以走到这个位置,不能走的不进行循环体
{
//如果被对方红棋的帅将死,那么不用继续判断,尝试其它方向去吧~
if (judgeG(x + temp[i][0], y + temp[i][1])) continue;
else if (judgeH(x + temp[i][0], y + temp[i][1])) continue; //判断是不是被马将死
else if (judgeR(x + temp[i][0], y + temp[i][1])) continue; //判断是不是被车将死
else if (judgeC(x + temp[i][0], y + temp[i][1])) continue; //判断是不是被炮将死
//都没有被将死那么是可以走这个位置的所以cheakmeat=false,而且,一旦找到方法,就没有必要继续检查其它位置了~
cheakmeat = false;
break;
}
}
}
//结果向量
vector<string> V;
int main() {
//读入红棋的个数n; x+y-->黑棋将的位置
int x, y, n;
while (cin >> n >> x >> y) {
if (!n && !x && !y) break; //如果有0或负数出现则退出
else {
//初始化
cheakmeat = true;
//初始化棋盘
mms(chessboard, 0);
//输入
rep(i, 0, n) //递增循环,第一个参数是递增变量,第二个参数是开始值,第三个变量是结束值
{
int a, b;
char size;
// size--> 炮,马,车
// a+b--> 棋子的位置
cin >> size >> a >> b;
//放入棋盘中
chessboard[a][b] = size;
}
//判断是不是将死了,如果将死了修改全局变量cheakmeat-->true,否则修改为false
judge(x, y);
//输出
if (cheakmeat) V.push_back("YES"); //之所有用向量vector来装每一局的结果是因为输入的残局数量不一定用数组之类不方便动态的容器方便些
else V.push_back("NO");
}
}
//输出结果
rep(i, 0, V.size()) {
//输出结果
cout << V[i] << endl;
}
return 0;
}