几点小提醒 (其实只是想发下代码,有没有人看无所谓) :
我自己做得挺顺的,虽然写了很久就是了……
因为中途有打印调试,提前排除了几个低级bug(包括棋子放错位置,函数传错参数等),最后提交只有两个问题:
思路还是很清晰的,但很容易犯一些小错误,不过看来题解区大佬的解答感觉自己写得还是复杂了些
#include <bits/stdc++.h>
using namespace std;
// 阵营
#define Camp bool
#define RED true
#define BLUE false
// 棋类
#define PIECE int // 棋子
#define CAPTAIN 0 // 王
#define GUARD 1 // 士
#define ELEPHANT 2 // 象
#define HORSE 3 // 马
#define CAR 4 // 车
#define DUCK 5 // 鸭
#define SOLDIER 6 // 兵
// 棋子
class piece {
public:
piece(Camp _color = RED, PIECE _p = CAPTAIN, int _x = 0, int _y = 0);
int get_x(); // 返回当前横坐标
int get_y(); // 返回当前纵坐标
bool isLive(); // 返回是否还在棋盘上,若被吃掉了返回false
void dead(); // 被吃
bool eat(piece* p); // 吃掉对方一个棋子
Camp camp(); // 返回所属阵营
PIECE type(); // 返回当前是哪一种棋子
string print_piece(); // 返回类型对应的单个中文字符
string tostring(); // 返回 [阵营] [类型] 的字符串
bool move(int x, int y); // 移动棋子到指定位置
private:
Camp color; // 所属阵营,true 表示红方,false 表示黑方
PIECE p; // 棋子类型
int x, y; // 当前坐标
bool save; // 是否还在棋盘上
};
// 双方阵营基类
class player {
public:
piece* p[16]; // 指针数组
};
// 红方阵营
class red : public player {
public:
red() {
p[0] = new piece(RED, CAPTAIN, 0, 4);
p[1] = new piece(RED, GUARD, 0, 3);
p[2] = new piece(RED, GUARD, 0, 5);
p[3] = new piece(RED, ELEPHANT, 0, 2);
p[4] = new piece(RED, ELEPHANT, 0, 6);
p[5] = new piece(RED, HORSE, 0, 1);
p[6] = new piece(RED, HORSE, 0, 7);
p[7] = new piece(RED, CAR, 0, 0);
p[8] = new piece(RED, CAR, 0, 8);
p[9] = new piece(RED, DUCK, 2, 0);
p[10] = new piece(RED, DUCK, 2, 8);
p[11] = new piece(RED, SOLDIER, 3, 0);
p[12] = new piece(RED, SOLDIER, 3, 2);
p[13] = new piece(RED, SOLDIER, 3, 4);
p[14] = new piece(RED, SOLDIER, 3, 6);
p[15] = new piece(RED, SOLDIER, 3, 8);
}
~red() {
for (int i = 0; i < 16; ++i) {
delete p[i];
}
}
};
// 蓝方阵营
class blue : public player {
public:
blue() {
p[0] = new piece(BLUE, CAPTAIN, 9, 4);
p[1] = new piece(BLUE, GUARD, 9, 3);
p[2] = new piece(BLUE, GUARD, 9, 5);
p[3] = new piece(BLUE, ELEPHANT, 9, 2);
p[4] = new piece(BLUE, ELEPHANT, 9, 6);
p[5] = new piece(BLUE, HORSE, 9, 1);
p[6] = new piece(BLUE, HORSE, 9, 7);
p[7] = new piece(BLUE, CAR, 9, 0);
p[8] = new piece(BLUE, CAR, 9, 8);
p[9] = new piece(BLUE, DUCK, 7, 0);
p[10] = new piece(BLUE, DUCK, 7, 8);
p[11] = new piece(BLUE, SOLDIER, 6, 0);
p[12] = new piece(BLUE, SOLDIER, 6, 2);
p[13] = new piece(BLUE, SOLDIER, 6, 4);
p[14] = new piece(BLUE, SOLDIER, 6, 6);
p[15] = new piece(BLUE, SOLDIER, 6, 8);
}
~blue() {
for (int i = 0; i < 16; ++i) {
delete p[i];
}
}
};
// 棋盘
class board {
public:
board(); // 初始化棋盘上的棋子
bool canMove(int x1, int y1, int x2, int y2); // 能否将棋子移动到对应位置
bool Move(int x1, int y1, int x2, int y2, Camp cap); // 移动棋子
bool isEnd(); // 本局游戏是否结束
bool isDanger(); // 当前棋局是否处于将军局面
piece* Lasteat(); // 返回最后一步被吃掉的棋子
piece* get_piece(int x, int y); // 获取某个位置的棋子
void printBoard(); // 打印棋盘
private:
piece* b[10][9]; // 10x9 的网格棋盘
red player_red; // 红方玩家
blue player_blue; // 蓝方玩家
piece* d = nullptr; // 最后一步被吃的棋子
// 玩家 p1 是否被玩家 p2 将军
bool check(player* p1, player* p2);
// 能否将对应棋子移动到对应位置
bool canMoveCaptain(int x1, int y1, int x2, int y2);
bool canMoveGuard(int x1, int y1, int x2, int y2);
bool canMoveElephant(int x1, int y1, int x2, int y2);
bool canMoveHorse(int x1, int y1, int x2, int y2);
bool canMoveCar(int x1, int y1, int x2, int y2);
bool canMoveDuck(int x1, int y1, int x2, int y2);
bool canMoveSoldier(int x1, int y1, int x2, int y2);
};
// ------------------- 棋盘的方法成员 -----------------------
// 初始化棋盘
board::board()
: d(nullptr) {
// 棋盘初始化
for (int i = 0; i < 10; ++i) {
for (int j = 0; j < 9; ++j) {
b[i][j] = nullptr;
}
}
// 红方棋子摆上棋盘
for (int i = 0; i < 16; ++i) {
piece* cur = player_red.p[i];
int x = cur->get_x(), y = cur->get_y();
b[x][y] = cur;
}
// 蓝方棋子摆上棋盘
for (int i = 0; i < 16; ++i) {
piece* cur = player_blue.p[i];
int x = cur->get_x(), y = cur->get_y();
b[x][y] = cur;
}
}
// 能否将棋子移动到对应位置(假设起始位置合法且有一枚棋子)
bool board::canMove(int x1, int y1, int x2, int y2) {
// 目标位置不合法
if (x2 < 0 || x2 > 9 || y2 < 0 || y2 > 8) return false;
// 目标位置有己方棋子
if (b[x2][y2] != nullptr && b[x1][y1]->camp() == b[x2][y2]->camp())
return false;
// 根据当前位置棋子类型调用判断函数
switch (b[x1][y1]->type()) {
case CAPTAIN: return canMoveCaptain(x1, y1, x2, y2);
case GUARD: return canMoveGuard(x1, y1, x2, y2);
case ELEPHANT: return canMoveElephant(x1, y1, x2, y2);
case HORSE: return canMoveHorse(x1, y1, x2, y2);
case CAR: return canMoveCar(x1, y1, x2, y2);
case DUCK: return canMoveDuck(x1, y1, x2, y2);
case SOLDIER: return canMoveSoldier(x1, y1, x2, y2);
default: return false;
}
}
// 移动棋子,移动成功返回 true,否则返回 false
bool board::Move(int x1, int y1, int x2, int y2, Camp cap) {
// 游戏已经结束不可移动
if (isEnd()) return false;
// 检查起始位置是否合法,是否有一个棋子
if (x1 < 0 || x1 > 9 || y1 < 0 || y1 > 8 || b[x1][y1] == nullptr)
return false;
// 起始位置的棋子是否是所给的阵营
if (b[x1][y1]->camp() != cap) return false;
// 检查目的地是否可达
if (canMove(x1, y1, x2, y2)) {
// 目的地可达那就移动
if (b[x2][y2] != nullptr) {
// 吃掉目的地的棋子
b[x2][y2]->dead();
d = b[x2][y2];
}
else
d = nullptr;
// 移动棋子
b[x1][y1]->move(x2, y2);
b[x2][y2] = b[x1][y1];
b[x1][y1] = nullptr;
return true;
}
else
return false;
}
// 游戏是否结束
inline bool board::isEnd() {
// 判断双方王是否存活即可
if (player_red.p[0]->isLive() && player_blue.p[0]->isLive())
return false;
else
return true;
}
// 玩家 p1 是否被玩家 p2 将军
bool board::check(player* p1, player* p2) {
// p1 王的位置
int x = p1->p[0]->get_x(), y = p1->p[0]->get_y();
// 逐个棋子检查能否攻击到王
for (int i = 0; i < 16; ++i) {
if (p2->p[i]->isLive() && canMove(p2->p[i]->get_x(), p2->p[i]->get_y(), x, y))
return true;
}
return false;
}
inline bool board::isDanger() {
// 结束局面不可能是将军局面
if (isEnd()) return false;
return check(&player_red, &player_blue) || check(&player_blue, &player_red);
}
inline piece* board::Lasteat() {
return d;
}
inline piece* board::get_piece(int x, int y) {
return b[x][y];
}
// 能否将 王 移动到对应位置(假设当前位置有王且目标位置合法)
inline bool board::canMoveCaptain(int x1, int y1, int x2, int y2) {
// 王只能上下左右移动
if (x1 == x2 && (y1 - y2 == 1 || y2 - y1 == 1)) return true;
if (y1 == y2 && (x1 - x2 == 1 || x2 - x1 == 1)) return true;
return false;
}
// 能否将 士 移动到对应位置(假设当前位置有士且目标位置合法)
inline bool board::canMoveGuard(int x1, int y1, int x2, int y2) {
// 士只能斜着移动
if (x1 + 1 == x2 && y1 + 1 == y2)
return true;
else if (x1 - 1 == x2 && y1 - 1 == y2)
return true;
else if (x1 + 1 == x2 && y1 - 1 == y2)
return true;
else if (x1 - 1 == x2 && y1 + 1 == y2)
return true;
return false;
}
// 能否将 象 移动到对应位置(假设当前位置有象且目标位置合法)
inline bool board::canMoveElephant(int x1, int y1, int x2, int y2) {
// 象只能走田字且中间不能有棋子
if (x1 + 2 == x2 && y1 + 2 == y2 && b[x1 + 1][y1 + 1] == nullptr)
return true;
else if (x1 - 2 == x2 && y1 + 2 == y2 && b[x1 - 1][y1 + 1] == nullptr)
return true;
else if (x1 + 2 == x2 && y1 - 2 == y2 && b[x1 + 1][y1 - 1] == nullptr)
return true;
else if (x1 - 2 == x2 && y1 - 2 == y2 && b[x1 - 1][y1 - 1] == nullptr)
return true;
return false;
}
// 能否将 马 移动到对应位置(假设当前位置有马且目标位置合法)
inline bool board::canMoveHorse(int x1, int y1, int x2, int y2) {
// 马走日字且中间不能有其他棋子
for (int i = -1; i <= 1; i += 2) {
for (int j = -1; j <= 1; j += 2) {
if (x1 + i * 2 == x2 && y1 + j == y2 && b[x1 + i][y1] == nullptr)
return true;
if (x1 + i == x2 && y1 + j * 2 == y2 && b[x1][y1 + j] == nullptr)
return true;
}
}
return false;
}
// 能否将 车 移动到对应位置(假设当前位置有车且目标位置合法)
inline bool board::canMoveCar(int x1, int y1, int x2, int y2) {
// 车可以在不跨越其他棋子的情况下到达同行或同列的任意位置
if (x1 == x2) {
int dir = y2 - y1 > 0 ? 1 : -1; // 向左还是向右
bool tmp = true;
for (int i = y1 + dir; i != y2; i += dir) {
if (b[x1][i] != nullptr) {
tmp = false;
break;
}
}
if (tmp) return true;
}
if (y1 == y2) {
int dir = x2 - x1 > 0 ? 1 : -1;
bool tmp = true;
for (int i = x1 + dir; i != x2; i += dir) {
if (b[i][y1] != nullptr) {
tmp = false;
break;
}
}
if (tmp) return true;
}
return false;
}
// 能否将 鸭 移动到对应位置(假设当前位置有鸭且目标位置合法)
inline bool board::canMoveDuck(int x1, int y1, int x2, int y2) {
// 不懂,照本宣科
for (int i = -1; i <= 1; i += 2) {
for (int j = -1; j <= 1; j += 2) {
if (x1 + i * 3 == x2 && y1 + j * 2 == y2 && b[x1 + i * 2][y1 + j] == nullptr && b[x1 + i][y1] == nullptr)
return true;
if (x1 + i * 2 == x2 && y1 + j * 3 == y2 && b[x1 + i][y1 + j * 2] == nullptr && b[x1][y1 + j] == nullptr)
return true;
}
}
return false;
}
// 能否将 兵 移动到对应位置(假设当前位置有兵且目标位置合法)
inline bool board::canMoveSoldier(int x1, int y1, int x2, int y2) {
// 周围八个位置
for (int i = -1; i <= 1; ++i) {
for (int j = -1; j <= 1; ++j) {
if (x1 + i == x2 && y1 + j == y2)
return true;
}
}
return false;
}
// 格式化输出棋盘
inline void board::printBoard() {
for (int i = 9; i >= 0; --i) {
for (int j = 8; j >= 0; --j) {
if (b[i][j] == nullptr)
cout << "十 ";
else {
cout << b[i][j]->print_piece() << ' ';
}
}
putchar('\n');
}
}
// ------------------- END - 棋盘的方法成员 -----------------------
// ------------------- 棋子的方法成员 -----------------------
// 构造函数,传入阵营,类型,坐标
piece::piece(Camp _color, PIECE _p, int _x, int _y)
: color(_color), p(_p), x(_x), y(_y) {
save = true;
}
// 返回当前横坐标
inline int piece::get_x() {
return this->x;
}
// 返回当前纵坐标
inline int piece::get_y() {
return this->y;
}
// 是否还在棋盘上
inline bool piece::isLive() {
return this->save;
}
// 被吃
inline void piece::dead() {
this->save = false;
}
// 吃掉棋子
inline bool piece::eat(piece* p) {
p->dead();
return true;
}
// 移动棋子到指定位置
inline bool piece::move(int x, int y) {
this->x = x;
this->y = y;
return true;
}
// 返回所属阵营
inline Camp piece::camp() {
return this->color;
}
// 返回棋子类型
inline PIECE piece::type() {
return this->p;
}
inline string piece::print_piece() {
switch (p) {
case CAPTAIN: return "王";
case GUARD: return "士";
case ELEPHANT: return "象";
case HORSE: return "马";
case CAR: return "车";
case DUCK: return "鸭";
case SOLDIER: return "兵";
default: return "无";
}
}
// 返回 [阵营] [类型] 的字符串
inline string piece::tostring() {
string c = color == RED ? "red " : "blue ";
string t;
switch (p) {
case CAPTAIN: t = "captain"; break;
case GUARD: t = "guard"; break;
case ELEPHANT: t = "elephant"; break;
case HORSE: t = "horse"; break;
case CAR: t = "car"; break;
case DUCK: t = "duck"; break;
case SOLDIER: t = "soldier"; break;
default: t = "err";
}
return c + t;
}
// ------------------- END - 棋子的方法成员 -----------------------
int Q; // 操作序列的长度
int x_s, y_s, x_t, y_t;
Camp c;
int main() {
// freopen("luogu.in", "r", stdin); // 输入流重定向
// freopen("luogu.out", "w", stdout); // 输出流重定向
board b;
c = RED; // 红方先动
// b.printBoard();
scanf("%d", &Q);
for (int i = 0; i < Q; ++i) {
scanf("%d%d%d%d", &x_s, &y_s, &x_t, &y_t);
if (b.Move(x_s, y_s, x_t, y_t, c)) {
// 这步操作移动了哪个棋子
cout << b.get_piece(x_t, y_t)->tostring() << ';';
// 这步操作后,是否存在棋子被移出游戏,如有则还需求出被移出游戏的棋子
cout << (b.Lasteat() == nullptr ? "NA" : b.Lasteat()->tostring()) << ';';
// 这步操作后,是否形成将军局面
cout << (b.isDanger() ? "yes" : "no") << ';';
// 这步操作后,游戏是否结束
cout << (b.isEnd() ? "yes" : "no");
cout << '\n';
c = c == RED ? BLUE : RED;
}
else {
cout << "Invalid command\n";
}
// cout << '\n';
// b.printBoard();
// cout << '\n';
}
return 0;
}