洛谷P5380 [THUPC2019] 鸭棋 题解

洛谷P5380 [THUPC2019] 鸭棋 题解

闲话

其实之前我没想碰大模拟的……这次的起因是 wjy同学 那天提到了要卷点大模拟,而猪国杀感觉太过复杂,于是我就选了鸭棋(

这是我第一道,大概也是最后一道大模拟了……

然后还是对着数据点二一点点改出来的 qwq,调试代码的过程真的好痛苦……当然,发现问题,改正问题的感觉还是蛮欣喜的。同时这次我也懂得了变量命名的重要性,以后会更加小心重复变量的出现。

题解

好了进入正题。首先我想说说我写这道题的思路。因为是模拟,所以我们要先理清整个游戏的流程。这道题比猪国杀简单就是因为它的回合并不复杂,最大的转换就是红蓝角色的变更,因此,很多东西都是相似甚至一样的。我们可以利用这一点进行函数封装,以达到模块化的目的,同时也可以让后期的调试更加便利。

我们发现,每一个回合其实总结下来,就是需要实现以下四个函数:判定移动是否合法,移除棋子,移动棋子,判定将军,伪代码如下:

if(!is_allowed()) puts("Invalid command");
//非法移动
move_a_piece(x, y);
//移除被吃掉的棋子
movexy(x, y, tx, ty);
//移动当前棋子
if(check()) puts("yes");
else puts("no");
//判定是否形成将军局面

然后我们来讨论如何实现。首先,我们可以用一个二维数组来记录棋盘,用编号来代替棋子,再让每个编号映射上种类。

我们可以把种类和编号处理成如下的矩阵(当然得自己打qwq):

5 4 3 2 1 2 3 4 5 1 2 3 4 5 6 7 8 9
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
6 0 0 0 0 0 0 0 6 10 0 0 0 0 0 0 0 11
7 0 7 0 7 0 7 0 7 12 0 13 0 14 0 15 0 16
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
7 0 7 0 7 0 7 0 7 17 0 18 0 19 0 20 0 21
6 0 0 0 0 0 0 0 6 22 0 0 0 0 0 0 0 23
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
5 4 3 2 1 2 3 4 5 24 25 26 27 28 29 30 31 32

然后就是棋子了。值得注意的是,虽然各个棋子要记录的信息大体相似,但是在移动方式上,我们并不能很方便地去统一封装。这里我选择的是,对每个棋子分别封装。这样做的好处就是特别清晰,方便调试,也方便处理,坏处就是我们没办法去做到映射(因为变量从属不同),所以如果我们要对某个棋子进行操作,只能是把所有的在场同类棋子都扫一遍;同样是因为变量不同,所以我们得写扫七个不同变量的循环……

我们对于每种棋子,都需要记录以下内容:

  • 当前的坐标;
  • 移动坐标要用到的数组 dxdy
  • 棋子的编号(这个很重要,因为只有通过这个才能去定位棋子!)

那么,我们要封装什么函数呢?

其实每个棋子只需要两个就够:判定移动是否合法,和判定能否将军。但是有七种棋子,所以其实是要写十四个差不多的函数。由于细节比较多,这里就不在赘述,最后的代码中会有相应注释。

然后,我们来考虑主函数中需要调用的东西。

对于判定非法移动的这个总函数,我们的解决方案是,先把共同的条件判掉,也就是判断起点是否合法(有无棋子和棋子颜色),终点是否合法(棋子颜色),然后去处理每个棋子不同的条件。这里就得把所有的同类棋子扫一遍,找到我们需要判定的棋子,然后调用该棋子对应的函数即可。

对于移动被吃掉棋子这个函数,我们需要加一个数组来标记不在棋盘上的棋子,来防止后边被遍历到,然后注意清空地图上该棋子即可。同时我们要注意记录游戏是否结束(王是否被吃掉)。

对于移动棋子这个函数,我们也是要扫一遍所有棋子,找到我们要移动的棋子,然后直接移动即可(我们已经判断了移动合法)。注意棋盘上的编号和棋子自己记录的 xy 都要相应改变。

然后就是将军局面这个东西了。这个看起来挺麻烦,但是因为数据范围不是很大,所以我们直接暴力扫!没错,我们直接扫描棋盘上所有的棋子(这也就是为啥要记录被吃掉的棋子,死人可不能诈尸),然后看他是否会攻击对方的王就行了。注意,这里的攻击也是建立在能合法移动的前提之上的。还有一点,就是游戏结束了就没有将军了。

大模拟的特点就是说起来容易写起来难,上面的思路我相信并不难想,但是想要很好地实现真的需要很大的功夫(我大概花了一晚上和一下午写完的这个题)。下面给出来代码,大概 600 行,可能是我 OI 生涯里写过最长的一份代码了。

友情提醒,该代码过于冗长,博客阅读可能不太方便,建议放到编译器中,把当前不看的函数折叠,一个函数一个函数看,可能会好一点(估计没人会读这份代码hhh)。

代码戳这里👇

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N = 20;
bool is_end, winner;//游戏是否结束,赢家
bool is_dead[50];//死人标记(
int mp[10][9] = {
1, 2, 3, 4, 5, 6, 7, 8, 9,
0, 0, 0, 0, 0, 0, 0, 0, 0,
10,0, 0, 0, 0, 0, 0, 0,11,
12,0,13, 0,14, 0,15, 0,16,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
17,0,18, 0,19, 0,20, 0,21,
22,0, 0, 0, 0, 0, 0, 0,23,
0, 0, 0, 0, 0, 0, 0, 0, 0,
24,25,26,27,28,29,30,31,32
};
int type[50] = {0,5,4,3,2,1,2,3,4,5,6,6,7,7,7,7,7,7,7,7,7,7,6,6,5,4,3,2,1,2,3,4,5};
//棋盘(记录编号)和编号对种类的映射
//这里做一个统一,所有的sx, sy表示起点;tx, ty表示终点
inline int read() {
int x = 0;
char ch = getchar();
while(ch<'0' || ch>'9') ch = getchar();
while(ch>='0'&&ch<='9') x = x*10+ch-48, ch = getchar();
return x;
}//都什么题了还写快读(
//—————————————— 棋子↓ ————————————————————
struct Captain {
int x, y, id, itype;//这里的itype就是不小心重复变量的一个例子:之前itype是type, 而全局变量中有一个type, 导致两个type冲突了。
//当然,itype并没有什么卵用……
int dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, -1, 1};//方向数组
//is_available 用来判断移动是否合法,check 用来判断能否将军,以下的所有棋子都按这个规则来命名函数
bool is_available(int tx, int ty) {//变量和函数名都最好别懒省事了,千万别调试的时候自己都看不懂
int dir = -1;//记录移动对应的是哪一对 dx dy
for(int i = 0; i<4; ++i) {
if(x+dx[i]==tx && y+dy[i]==ty) {
dir = i;
break;
}
}
if(dir == -1) return 0;//发现移动的方式不在记录的方向数组中,说明不合法
else return 1;
}
bool check() {
int tx, ty;
for(int i = 0; i<4; ++i) {
tx = x+dx[i];
ty = y+dy[i];
bool is_red = (id<=16);//记录当前棋子的阵营
if(tx<0 || tx>=10 || ty<0 || ty>=9) continue;//判断移动是否合法
if(!is_available(tx, ty)) continue;
bool enemy = (mp[tx][ty]<=16);//记录目标点棋子的阵营
if((type[mp[tx][ty]]==1)&&(is_red^enemy)) return 1;//只有吃掉对方王才算将军(
}
return 0;
}
} captain[5]; //编号1,对应王
struct Guard {//和王基本一致
int x, y, id, itype;
int dx[4] = {1, 1, -1, -1}, dy[4] = {1, -1, 1, -1};
bool is_available(int tx, int ty) {
int dir = -1;
for(int i = 0; i<4; ++i) {
if(x+dx[i]==tx && y+dy[i]==ty) {
dir = i;
break;
}
}
if(dir == -1) return 0;
else return 1;
}
bool check() {
int tx, ty;
for(int i = 0; i<4; ++i) {
tx = x+dx[i];
ty = y+dy[i];
bool is_red = (id<=16);
if(tx<0 || tx>=10 || ty<0 || ty>=9) continue;
if(!is_available(tx, ty)) continue;
bool enemy = (mp[tx][ty]<=16);
if((type[mp[tx][ty]]==1)&&(is_red^enemy)) return 1;
}
return 0;
}
} guard[10]; //编号2,对应士
struct Elephant {
int x, y, id, itype;
int dx[4] = {2, 2, -2, -2}, dy[4] = {2, -2, 2, -2};
bool is_available(int tx, int ty) {
int dir = -1;
for(int i = 0; i<4; ++i) {
if(x+dx[i]==tx && y+dy[i]==ty) {
dir = i;
break;
}
}
if(dir == -1) return 0;
return !mp[x+dx[dir]/2][y+dy[dir]/2];//判断路径上是否有其他棋子
}
bool check() {//一致
int tx, ty;
for(int i = 0; i<4; ++i) {
tx = x+dx[i];
ty = y+dy[i];
bool is_red = (id<=16);
if(tx<0 || tx>=10 || ty<0 || ty>=9) continue;
if(!is_available(tx, ty)) continue;
bool enemy = (mp[tx][ty]<=16);
if((type[mp[tx][ty]]==1)&&(is_red^enemy)) return 1;
}
return 0;
}
} elephant[10]; //编号3,对应象
struct Horse {
int x, y, id, itype;
int dx[8] = {2, 2, -2, -2, 1, 1, -1, -1};
int dy[8] = {1, -1, 1, -1, 2, -2, 2, -2};
bool is_available(int tx, int ty) {
int dir = -1;
for(int i = 0; i<8; ++i) {
if(x+dx[i]==tx && y+dy[i]==ty) {
dir = i;
break;
}
}
if(dir == -1) return 0;
if(dir<4) {//这里小细节,把2*x的移动方式放在数组左侧,方便判断
return !mp[x+dx[dir]/2][y];
} else {
return !mp[x][y+dy[dir]/2];
}
}
bool check() {
int tx, ty;
for(int i = 0; i<8; ++i) {//依然一致
tx = x+dx[i];
ty = y+dy[i];
bool is_red = (id<=16);
if(tx<0 || tx>=10 || ty<0 || ty>=9) continue;
if(!is_available(tx, ty)) continue;
bool enemy = (mp[tx][ty]<=16);
if((type[mp[tx][ty]]==1)&&(is_red^enemy)) return 1;
}
return 0;
}
} horse[10]; //编号4,对应马
struct Car {//注意这个是最特殊的一类棋子了,它没有方向数组,所有两个函数都不太一样
int x, y, id, itype;
bool is_available(int tx, int ty) {
if(tx != x && ty != y) return 0;//车只能横向或竖向移动
if(tx ^ x) {
for(int i = min(x, tx)+1; i<max(x, tx); ++i) {//判断起点和终点之间(不包括两端)有没有棋子即可
if(mp[i][y]) return 0;
}
return 1;
} else {
for(int i = min(y, ty)+1; i<max(y, ty); ++i) {
if(mp[x][i]) return 0;
}
return 1;
}
}
bool check() {
int tx, ty;
bool is_red = (id<=16);
for(tx = x+1, ty = y; tx<10; ++tx) {//这里要判断车向四个方向移动碰到的第一个棋子是否为对方的王
if(mp[tx][ty]) {
bool enemy = (mp[tx][ty]<=16);
if((type[mp[tx][ty]]==1)&&(is_red^enemy)) return 1;
break;
}
}
for(tx = x-1, ty = y; tx>=0; --tx) {
if(mp[tx][ty]) {
bool enemy = (mp[tx][ty]<=16);
if((type[mp[tx][ty]]==1)&&(is_red^enemy)) return 1;
break;
}
}
for(tx = x, ty = y+1; ty<9; ++ty) {
if(mp[tx][ty]) {
bool enemy = (mp[tx][ty]<=16);
if((type[mp[tx][ty]]==1)&&(is_red^enemy)) return 1;
break;
}
}
for(tx = x, ty = y-1; ty>=0; --ty) {
if(mp[tx][ty]) {
bool enemy = (mp[tx][ty]<=16);
if((type[mp[tx][ty]]==1)&&(is_red^enemy)) return 1;
break;
}
}
return 0;
}
} car[10]; //编号5,对应车
struct Duck {
int x, y, id, itype;
int dx[8] = {3, 3, -3, -3, 2, 2, -2, -2};
int dy[8] = {2, -2, 2, -2, 3, -3, 3, -3};
bool is_available(int tx, int ty) {
int dir = -1;
for(int i = 0; i<8; ++i) {
if(x+dx[i] == tx && y+dy[i] == ty) {
dir = i;
break;
}
}
if(dir == -1) return 0;
if(dir < 4) {//和马类似
return (!mp[x+dx[dir]/3*2][y+dy[dir]/2])&&(!mp[x+dx[dir]/3][y]);
} else {
return (!mp[x+dx[dir]/2][y+dy[dir]/3*2])&&(!mp[x][y+dy[dir]/3]);
}
}
bool check() {
int tx, ty;
for(int i = 0; i<8; ++i) {
tx = x+dx[i];
ty = y+dy[i];
bool is_red = (id<=16);
if(tx<0 || tx>=10 || ty<0 || ty>=9) continue;
if(!is_available(tx, ty)) continue;
bool enemy = (mp[tx][ty]<=16);
if((type[mp[tx][ty]]==1)&&(is_red^enemy)) return 1;
}
return 0;
}
} duck[10]; //编号6,对应鸭
struct Soldier {
int x, y, id, itype;
int dx[8] = {1, -1, 0, 0, 1, -1, 1, -1};
int dy[8] = {0, 0, 1, -1, 1, -1, -1, 1};
bool is_available(int tx, int ty){//和王与士基本一致
int dir = -1;
for(int i = 0; i<8; ++i){
if(x+dx[i] == tx && y+dy[i] == ty){
dir = i;
break;
}
}
return dir!=-1;
}
bool check() {
int tx, ty;
for(int i = 0; i<8; ++i) {
tx = x+dx[i];
ty = y+dy[i];
bool is_red = (id<=16);
if(tx<0 || tx>=10 || ty<0 || ty>=9) continue;
if(!is_available(tx, ty)) continue;
bool enemy = (mp[tx][ty]<=16);
if((type[mp[tx][ty]]==1)&&(is_red^enemy)) return 1;
}
return 0;
}
} soldier[22]; //编号7,对应兵
//—————————————————————— 函数部分 ↓ ——————————————————
bool is_red(int x) {//棋子是否为红方
return x<=16;
}
string team[5], nameoftype[10];//记录队伍颜色与种类名称,便于输出。
int SumofCaptain, SumofGuard, SumofElephant, SumofHorse, SumofCar, SumofDuck, SumofSoldier;//各个棋子的数量
void init() {//初始化,注意我们要把所有棋子初始化
//各个名称
nameoftype[1] = "captain";
nameoftype[2] = "guard";
nameoftype[3] = "elephant";
nameoftype[4] = "horse";
nameoftype[5] = "car";
nameoftype[6] = "duck";
nameoftype[7] = "soldier";
team[1] = "red ";//细节空格
team[0] = "blue ";
SumofCaptain = 0;
SumofGuard = 0;
SumofElephant = 0;
SumofHorse = 0;
SumofCar = 0;
SumofDuck = 0;
SumofSoldier = 0;//没必要的清零(bush
for(int i = 0; i<10; ++i) {
for(int j = 0; j<9; ++j) {
int id = mp[i][j], ty = type[mp[i][j]];
//特别注意,这里不小心写了一个ty(可能重复的变量),因为函数里没有用到我才没有改,但这是应该极力避免的。
if(ty == 1) {//这里写switch明显更清晰,但是这里忘了……下一个函数才想起来
SumofCaptain++;
captain[SumofCaptain].x = i, captain[SumofCaptain].y = j;
captain[SumofCaptain].id = id;
captain[SumofCaptain].itype = ty;
} else if(ty == 2) {
SumofGuard++;
guard[SumofGuard].x = i, guard[SumofGuard].y = j;
guard[SumofGuard].id = id;
guard[SumofGuard].itype = ty;
} else if(ty == 3) {
SumofElephant++;
elephant[SumofElephant].x = i, elephant[SumofElephant].y = j;
elephant[SumofElephant].id = id;
elephant[SumofElephant].itype = ty;
} else if(ty == 4) {
SumofHorse++;
horse[SumofHorse].x = i, horse[SumofHorse].y = j;
horse[SumofHorse].id = id;
horse[SumofHorse].itype = ty;
} else if(ty == 5) {
SumofCar++;
car[SumofCar].x = i, car[SumofCar].y = j;
car[SumofCar].id = id;
car[SumofCar].itype = ty;
} else if(ty == 6) {
SumofDuck++;
duck[SumofDuck].x = i, duck[SumofDuck].y = j;
duck[SumofDuck].id = id;
duck[SumofDuck].itype = ty;
} else if(ty == 7) {
SumofSoldier++;
soldier[SumofSoldier].x = i, soldier[SumofSoldier].y = j;
soldier[SumofSoldier].id = id;
soldier[SumofSoldier].itype = ty;
}
}
}
}
//需要注意,有操作叫做将军,游戏结束需要真正实现吃掉对方王。
bool is_allowed(int x, int y, int tx, int ty) {
if(is_end) {
return 0;
}
int id = mp[x][y], typ = type[mp[x][y]];
switch (typ) {//去对应种类的棋子里找目标棋子
case 1: {
int tid;
for(int i = 1; i<=SumofCaptain; ++i) {
if(captain[i].id == id) {
tid = i;
break;
}
}
return captain[tid].is_available(tx, ty);
break;
}
case 2: {
int tid;
for(int i = 1; i<=SumofGuard; ++i) {
if(guard[i].id == id) {
tid = i;
break;
}
}
return guard[tid].is_available(tx, ty);//调用判定函数
break;
}
case 3: {
int tid;
for(int i = 1; i<=SumofElephant; ++i) {
if(elephant[i].id == id) {
tid = i;
break;
}
}
return elephant[tid].is_available(tx, ty);
break;
}
case 4: {
int tid;
for(int i = 1; i<=SumofHorse; ++i) {
if(horse[i].id == id) {
tid = i;
break;
}
}
return horse[tid].is_available(tx, ty);
break;
}
case 5: {
int tid;
for(int i = 1; i<=SumofCar; ++i) {
if(car[i].id == id) {
tid = i;
break;
}
}
return car[tid].is_available(tx, ty);
break;
}
case 6: {
int tid;
for(int i = 1; i<=SumofDuck; ++i) {
if(duck[i].id == id) {
tid = i;
break;
}
}
return duck[tid].is_available(tx, ty);
break;
}
case 7: {
int tid;
for(int i = 1; i<=SumofSoldier; ++i) {
if(soldier[i].id == id) {
tid = i;
break;
}
}
return soldier[tid].is_available(tx, ty);
break;
}
}
return 0;
}
void print_mp() {//输出当前局面,用于调试
for(int i = 0; i<10; ++i, puts("")) {
for(int j = 0; j<9; ++j) {
printf("%d ", type[mp[i][j]]);
}
putchar(' ');
for(int j = 0; j<9; ++j){
printf("%-3d", mp[i][j]);
}
}
putchar('\n');
}
bool check() {//将军判定函数
if(is_end) return 0;
for(int i = 1; i<=SumofCaptain; ++i) {
if(is_dead[captain[i].id]) continue;//死人不会说话(
if(captain[i].check()) return 1;
}
for(int i = 1; i<=SumofGuard; ++i) {
if(is_dead[guard[i].id]) continue;
if(guard[i].check()) return 1;
}
for(int i = 1; i<=SumofElephant; ++i) {
if(is_dead[elephant[i].id]) continue;
if(elephant[i].check()) return 1;
}
for(int i = 1; i<=SumofHorse; ++i) {
if(is_dead[horse[i].id]) continue;
if(horse[i].check()) return 1;
}
for(int i = 1; i<=SumofCar; ++i) {
if(is_dead[car[i].id]) continue;
if(car[i].check()) return 1;
}
for(int i = 1; i<=SumofDuck; ++i) {
if(is_dead[duck[i].id]) continue;
if(duck[i].check()) return 1;
}
for(int i = 1; i<=SumofSoldier; ++i) {
if(is_dead[soldier[i].id]) continue;
if(soldier[i].check()) return 1;
}
return 0;
}
bool current_round = 1;//当前轮到哪一方,1为红色,0为蓝色
void movexy(int x, int y, int tx, int ty) {//移动棋子
int id = mp[x][y], typ = type[mp[x][y]];
switch (typ) {
case 1: {
int tid;
for(int i = 1; i<=SumofCaptain; ++i) {
if(captain[i].id == id) {
tid = i;
break;
}
}
captain[tid].x = tx;//注意每个棋子的坐标也要同时修改
captain[tid].y = ty;
break;
}
case 2: {
int tid;
for(int i = 1; i<=SumofGuard; ++i) {
if(guard[i].id == id) {
tid = i;
break;
}
}
guard[tid].x = tx;
guard[tid].y = ty;
break;
}
case 3: {
int tid;
for(int i = 1; i<=SumofElephant; ++i) {
if(elephant[i].id == id) {
tid = i;
break;
}
}
elephant[tid].x = tx;
elephant[tid].y = ty;
break;
}
case 4: {
int tid;
for(int i = 1; i<=SumofHorse; ++i) {
if(horse[i].id == id) {
tid = i;
break;
}
}
horse[tid].x = tx;
horse[tid].y = ty;
break;
}
case 5: {
int tid;
for(int i = 1; i<=SumofCar; ++i) {
if(car[i].id == id) {
tid = i;
break;
}
}
car[tid].x = tx;
car[tid].y = ty;
break;
}
case 6: {
int tid;
for(int i = 1; i<=SumofDuck; ++i) {
if(duck[i].id == id) {
tid = i;
break;
}
}
duck[tid].x = tx;
duck[tid].y = ty;
break;
}
case 7: {
int tid;
for(int i = 1; i<=SumofSoldier; ++i) {
if(soldier[i].id == id) {
tid = i;
break;
}
}
soldier[tid].x = tx;
soldier[tid].y = ty;
break;
}
}
mp[tx][ty] = id;//更新棋盘状态
mp[x][y] = 0;
}
void move_a_piece(int x, int y, bool red_round) { //移走x,y处的棋子并输出结果。
int id = mp[x][y], typ = type[mp[x][y]];
if(typ == 1) {//判定是否游戏结束
is_end = 1;
winner = red_round;
}
cout << team[red_round^1] << nameoftype[typ]<<";";
mp[x][y] = 0;//更新棋盘状态
is_dead[id] = 1;//标记吃掉的棋子
}
//—————————————— 主函数 ↓——————————————————
int Q;
int main() {
init();
Q = read();
for(int round = 1; round<=Q; ++round) {
int sx = read(), sy = read(), tx = read(), ty = read();
bool red_round = (current_round&1);
//判定移动是否合法
if((!mp[sx][sy]) || (is_red(mp[sx][sy])^red_round) ||((is_red(mp[tx][ty])^(red_round^1))&&mp[tx][ty]) ) {//起点合法与终点合法(终点注意要有棋子才能继续判断)
puts("Invalid command");
continue;
}
int CurrentType = type[mp[sx][sy]];
if(!is_allowed(sx, sy, tx, ty)) {
puts("Invalid command");
continue;
}
//输出当前移动棋子是什么
cout << team[red_round] << nameoftype[CurrentType] <<";";
if(!mp[tx][ty]) cout << "NA;";
else move_a_piece(tx, ty, red_round);//移除棋子
movexy(sx, sy, tx, ty);//移动棋子
if(check()) cout << "yes;";//判断将军
else cout <<"no;";
if(is_end) puts("yes");//判断游戏结束与否
else puts("no");
current_round^=1;//只有合法操作之后才会切换红蓝
}
return 0;
}//完结撒花!加上注释610行的代码,也感谢您能读到这里www。

啊啊啊累死了累死了 qwq以后再不写大模拟了 xwx。

updated 2023/7/11

这里给出 鸭棋Virtual 的代码~可以与小伙伴对战辣(很粗糙就是了,仅仅是在原题基础上搞了个输出 xwx)。

点击查看代码
#include<iostream>
#include<windows.h>
#define RED 4
#define PINK 13
#define WHITE 7
#define YELLOW 6
#define B_YELLOW 14
#define BLUE 1
#define B_BLUE 9
#define BB_BLUE 11
using namespace std;
const int N = 20;
bool is_end, winner;
bool is_dead[50];
int mp[10][9] = {
1, 2, 3, 4, 5, 6, 7, 8, 9,
0, 0, 0, 0, 0, 0, 0, 0, 0,
10,0, 0, 0, 0, 0, 0, 0,11,
12,0,13, 0,14, 0,15, 0,16,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
17,0,18, 0,19, 0,20, 0,21,
22,0, 0, 0, 0, 0, 0, 0,23,
0, 0, 0, 0, 0, 0, 0, 0, 0,
24,25,26,27,28,29,30,31,32
};
int type[50] = {0,5,4,3,2,1,2,3,4,5,6,6,7,7,7,7,7,7,7,7,7,7,6,6,5,4,3,2,1,2,3,4,5};
inline int read() {
int x = 0;
char ch = getchar();
while(ch<'0' || ch>'9') ch = getchar();
while(ch>='0'&&ch<='9') x = x*10+ch-48, ch = getchar();
return x;
}
struct Captain {
int x, y, id, itype;
int dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, -1, 1};
bool is_available(int tx, int ty) {
int dir = -1;
for(int i = 0; i<4; ++i) {
if(x+dx[i]==tx && y+dy[i]==ty) {
dir = i;
break;
}
}
if(dir == -1) return 0;
else return 1;
}
bool check() {
int tx, ty;
for(int i = 0; i<4; ++i) {
tx = x+dx[i];
ty = y+dy[i];
bool is_red = (id<=16);
if(tx<0 || tx>=10 || ty<0 || ty>=9) continue;
if(!is_available(tx, ty)) continue;
bool enemy = (mp[tx][ty]<=16);
if((type[mp[tx][ty]]==1)&&(is_red^enemy)) return 1;
}
return 0;
}
} captain[5]; //1
struct Guard {
int x, y, id, itype;
int dx[4] = {1, 1, -1, -1}, dy[4] = {1, -1, 1, -1};
bool is_available(int tx, int ty) {
int dir = -1;
for(int i = 0; i<4; ++i) {
if(x+dx[i]==tx && y+dy[i]==ty) {
dir = i;
break;
}
}
if(dir == -1) return 0;
else return 1;
}
bool check() {
int tx, ty;
for(int i = 0; i<4; ++i) {
tx = x+dx[i];
ty = y+dy[i];
bool is_red = (id<=16);
if(tx<0 || tx>=10 || ty<0 || ty>=9) continue;
if(!is_available(tx, ty)) continue;
bool enemy = (mp[tx][ty]<=16);
if((type[mp[tx][ty]]==1)&&(is_red^enemy)) return 1;
}
return 0;
}
} guard[10]; //2
struct Elephant {
int x, y, id, itype;
int dx[4] = {2, 2, -2, -2}, dy[4] = {2, -2, 2, -2};
bool is_available(int tx, int ty) {
int dir = -1;
for(int i = 0; i<4; ++i) {
if(x+dx[i]==tx && y+dy[i]==ty) {
dir = i;
break;
}
}
if(dir == -1) return 0;
return !mp[x+dx[dir]/2][y+dy[dir]/2];
}
bool check() {
int tx, ty;
for(int i = 0; i<4; ++i) {
tx = x+dx[i];
ty = y+dy[i];
bool is_red = (id<=16);
if(tx<0 || tx>=10 || ty<0 || ty>=9) continue;
if(!is_available(tx, ty)) continue;
bool enemy = (mp[tx][ty]<=16);
if((type[mp[tx][ty]]==1)&&(is_red^enemy)) return 1;
}
return 0;
}
} elephant[10]; //3
struct Horse {
int x, y, id, itype;
int dx[8] = {2, 2, -2, -2, 1, 1, -1, -1};
int dy[8] = {1, -1, 1, -1, 2, -2, 2, -2};
bool is_available(int tx, int ty) {
int dir = -1;
for(int i = 0; i<8; ++i) {
if(x+dx[i]==tx && y+dy[i]==ty) {
dir = i;
break;
}
}
if(dir == -1) return 0;
if(dir<4) {
return !mp[x+dx[dir]/2][y];
} else {
return !mp[x][y+dy[dir]/2];
}
}
bool check() {
int tx, ty;
for(int i = 0; i<8; ++i) {
tx = x+dx[i];
ty = y+dy[i];
bool is_red = (id<=16);
if(tx<0 || tx>=10 || ty<0 || ty>=9) continue;
if(!is_available(tx, ty)) continue;
bool enemy = (mp[tx][ty]<=16);
if((type[mp[tx][ty]]==1)&&(is_red^enemy)) return 1;
}
return 0;
}
} horse[10]; //4
struct Car {
int x, y, id, itype;
bool is_available(int tx, int ty) {
if(tx != x && ty != y) return 0;
if(tx ^ x) {
for(int i = min(x, tx)+1; i<max(x, tx); ++i) {
if(mp[i][y]) return 0;
}
return 1;
} else {
for(int i = min(y, ty)+1; i<max(y, ty); ++i) {
if(mp[x][i]) return 0;
}
return 1;
}
}
bool check() {
int tx, ty;
bool is_red = (id<=16);
for(tx = x+1, ty = y; tx<10; ++tx) {
if(mp[tx][ty]) {
bool enemy = (mp[tx][ty]<=16);
if((type[mp[tx][ty]]==1)&&(is_red^enemy)) return 1;
break;
}
}
for(tx = x-1, ty = y; tx>=0; --tx) {
if(mp[tx][ty]) {
bool enemy = (mp[tx][ty]<=16);
if((type[mp[tx][ty]]==1)&&(is_red^enemy)) return 1;
break;
}
}
for(tx = x, ty = y+1; ty<9; ++ty) {
if(mp[tx][ty]) {
bool enemy = (mp[tx][ty]<=16);
if((type[mp[tx][ty]]==1)&&(is_red^enemy)) return 1;
break;
}
}
for(tx = x, ty = y-1; ty>=0; --ty) {
if(mp[tx][ty]) {
bool enemy = (mp[tx][ty]<=16);
if((type[mp[tx][ty]]==1)&&(is_red^enemy)) return 1;
break;
}
}
return 0;
}
} car[10]; //5
struct Duck {
int x, y, id, itype;
int dx[8] = {3, 3, -3, -3, 2, 2, -2, -2};
int dy[8] = {2, -2, 2, -2, 3, -3, 3, -3};
bool is_available(int tx, int ty) {
int dir = -1;
for(int i = 0; i<8; ++i) {
if(x+dx[i] == tx && y+dy[i] == ty) {
dir = i;
break;
}
}
if(dir == -1) return 0;
if(dir < 4) {
return (!mp[x+dx[dir]/3*2][y+dy[dir]/2])&&(!mp[x+dx[dir]/3][y]);
} else {
return (!mp[x+dx[dir]/2][y+dy[dir]/3*2])&&(!mp[x][y+dy[dir]/3]);
}
}
bool check() {
int tx, ty;
for(int i = 0; i<8; ++i) {
tx = x+dx[i];
ty = y+dy[i];
bool is_red = (id<=16);
if(tx<0 || tx>=10 || ty<0 || ty>=9) continue;
if(!is_available(tx, ty)) continue;
bool enemy = (mp[tx][ty]<=16);
if((type[mp[tx][ty]]==1)&&(is_red^enemy)) return 1;
}
return 0;
}
} duck[10]; //6
struct Soldier {
int x, y, id, itype;
int dx[8] = {1, -1, 0, 0, 1, -1, 1, -1};
int dy[8] = {0, 0, 1, -1, 1, -1, -1, 1};
bool is_available(int tx, int ty){
int dir = -1;
for(int i = 0; i<8; ++i){
if(x+dx[i] == tx && y+dy[i] == ty){
dir = i;
break;
}
}
return dir!=-1;
}
bool check() {
int tx, ty;
for(int i = 0; i<8; ++i) {
tx = x+dx[i];
ty = y+dy[i];
bool is_red = (id<=16);
if(tx<0 || tx>=10 || ty<0 || ty>=9) continue;
if(!is_available(tx, ty)) continue;
bool enemy = (mp[tx][ty]<=16);
if((type[mp[tx][ty]]==1)&&(is_red^enemy)) return 1;
}
return 0;
}
} soldier[22]; //7
bool is_red(int x) {
return x<=16;
}
string team[5], nameoftype[10], ch_name[10];
int SumofCaptain, SumofGuard, SumofElephant, SumofHorse, SumofCar, SumofDuck, SumofSoldier;
void init() {
nameoftype[1] = "王";
nameoftype[2] = "士";
nameoftype[3] = "象";
nameoftype[4] = "马";
nameoftype[5] = "车";
nameoftype[6] = "鸭";
nameoftype[7] = "兵";
team[1] = "红方 ";
team[0] = "蓝方 ";
SumofCaptain = 0;
SumofGuard = 0;
SumofElephant = 0;
SumofHorse = 0;
SumofCar = 0;
SumofDuck = 0;
SumofSoldier = 0;
for(int i = 0; i<10; ++i) {
for(int j = 0; j<9; ++j) {
int id = mp[i][j], ty = type[mp[i][j]];
if(ty == 1) {
SumofCaptain++;
captain[SumofCaptain].x = i, captain[SumofCaptain].y = j;
captain[SumofCaptain].id = id;
captain[SumofCaptain].itype = ty;
} else if(ty == 2) {
SumofGuard++;
guard[SumofGuard].x = i, guard[SumofGuard].y = j;
guard[SumofGuard].id = id;
guard[SumofGuard].itype = ty;
} else if(ty == 3) {
SumofElephant++;
elephant[SumofElephant].x = i, elephant[SumofElephant].y = j;
elephant[SumofElephant].id = id;
elephant[SumofElephant].itype = ty;
} else if(ty == 4) {
SumofHorse++;
horse[SumofHorse].x = i, horse[SumofHorse].y = j;
horse[SumofHorse].id = id;
horse[SumofHorse].itype = ty;
} else if(ty == 5) {
SumofCar++;
car[SumofCar].x = i, car[SumofCar].y = j;
car[SumofCar].id = id;
car[SumofCar].itype = ty;
} else if(ty == 6) {
SumofDuck++;
duck[SumofDuck].x = i, duck[SumofDuck].y = j;
duck[SumofDuck].id = id;
duck[SumofDuck].itype = ty;
} else if(ty == 7) {
SumofSoldier++;
soldier[SumofSoldier].x = i, soldier[SumofSoldier].y = j;
soldier[SumofSoldier].id = id;
soldier[SumofSoldier].itype = ty;
}
}
}
}
bool is_allowed(int x, int y, int tx, int ty) {
if(is_end) {
return 0;
}
int id = mp[x][y], typ = type[mp[x][y]];
switch (typ) {
case 1: {
int tid;
for(int i = 1; i<=SumofCaptain; ++i) {
if(captain[i].id == id) {
tid = i;
break;
}
}
return captain[tid].is_available(tx, ty);
break;
}
case 2: {
int tid;
for(int i = 1; i<=SumofGuard; ++i) {
if(guard[i].id == id) {
tid = i;
break;
}
}
return guard[tid].is_available(tx, ty);
break;
}
case 3: {
int tid;
for(int i = 1; i<=SumofElephant; ++i) {
if(elephant[i].id == id) {
tid = i;
break;
}
}
return elephant[tid].is_available(tx, ty);
break;
}
case 4: {
int tid;
for(int i = 1; i<=SumofHorse; ++i) {
if(horse[i].id == id) {
tid = i;
break;
}
}
return horse[tid].is_available(tx, ty);
break;
}
case 5: {
int tid;
for(int i = 1; i<=SumofCar; ++i) {
if(car[i].id == id) {
tid = i;
break;
}
}
return car[tid].is_available(tx, ty);
break;
}
case 6: {
int tid;
for(int i = 1; i<=SumofDuck; ++i) {
if(duck[i].id == id) {
tid = i;
break;
}
}
return duck[tid].is_available(tx, ty);
break;
}
case 7: {
int tid;
for(int i = 1; i<=SumofSoldier; ++i) {
if(soldier[i].id == id) {
tid = i;
break;
}
}
return soldier[tid].is_available(tx, ty);
break;
}
}
return 0;
}
void print_mp() {
for(int i = 0; i<10; ++i, puts("")) {
for(int j = 0; j<9; ++j) {
printf("%d ", type[mp[i][j]]);
}
putchar(' ');
for(int j = 0; j<9; ++j){
printf("%-3d", mp[i][j]);
}
}
putchar('\n');
}
bool check() {
if(is_end) return 0;
for(int i = 1; i<=SumofCaptain; ++i) {
if(is_dead[captain[i].id]) continue;
if(captain[i].check()) return 1;
}
for(int i = 1; i<=SumofGuard; ++i) {
if(is_dead[guard[i].id]) continue;
if(guard[i].check()) return 1;
}
for(int i = 1; i<=SumofElephant; ++i) {
if(is_dead[elephant[i].id]) continue;
if(elephant[i].check()) return 1;
}
for(int i = 1; i<=SumofHorse; ++i) {
if(is_dead[horse[i].id]) continue;
if(horse[i].check()) return 1;
}
for(int i = 1; i<=SumofCar; ++i) {
if(is_dead[car[i].id]) continue;
if(car[i].check()) return 1;
}
for(int i = 1; i<=SumofDuck; ++i) {
if(is_dead[duck[i].id]) continue;
if(duck[i].check()) return 1;
}
for(int i = 1; i<=SumofSoldier; ++i) {
if(is_dead[soldier[i].id]) continue;
if(soldier[i].check()) return 1;
}
return 0;
}
bool current_round = 1;
void movexy(int x, int y, int tx, int ty) {
int id = mp[x][y], typ = type[mp[x][y]];
switch (typ) {
case 1: {
int tid;
for(int i = 1; i<=SumofCaptain; ++i) {
if(captain[i].id == id) {
tid = i;
break;
}
}
captain[tid].x = tx;
captain[tid].y = ty;
break;
}
case 2: {
int tid;
for(int i = 1; i<=SumofGuard; ++i) {
if(guard[i].id == id) {
tid = i;
break;
}
}
guard[tid].x = tx;
guard[tid].y = ty;
break;
}
case 3: {
int tid;
for(int i = 1; i<=SumofElephant; ++i) {
if(elephant[i].id == id) {
tid = i;
break;
}
}
elephant[tid].x = tx;
elephant[tid].y = ty;
break;
}
case 4: {
int tid;
for(int i = 1; i<=SumofHorse; ++i) {
if(horse[i].id == id) {
tid = i;
break;
}
}
horse[tid].x = tx;
horse[tid].y = ty;
break;
}
case 5: {
int tid;
for(int i = 1; i<=SumofCar; ++i) {
if(car[i].id == id) {
tid = i;
break;
}
}
car[tid].x = tx;
car[tid].y = ty;
break;
}
case 6: {
int tid;
for(int i = 1; i<=SumofDuck; ++i) {
if(duck[i].id == id) {
tid = i;
break;
}
}
duck[tid].x = tx;
duck[tid].y = ty;
break;
}
case 7: {
int tid;
for(int i = 1; i<=SumofSoldier; ++i) {
if(soldier[i].id == id) {
tid = i;
break;
}
}
soldier[tid].x = tx;
soldier[tid].y = ty;
break;
}
}
mp[tx][ty] = id;
mp[x][y] = 0;
}
void move_a_piece(int x, int y, bool red_round) { //移走x,y处的棋子并输出结果。
int id = mp[x][y], typ = type[mp[x][y]];
if(typ == 1) {
is_end = 1;
winner = red_round;
}
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BB_BLUE);
cout <<"吃掉" <<team[red_round^1] << nameoftype[typ]<<";";
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),WHITE);
mp[x][y] = 0;
is_dead[id] = 1;
}
int Q;
void print_now(){
printf(" ");
for(int i = 0; i<9; ++i) printf("%-2d ", i);
printf("y轴");
putchar('\n');
for(int i = 0; i<10; ++i, puts("")){
printf("%-2d ", i);
for(int j = 0; j<9; ++j){
// printf("%-2d ", mp[i][j]);
if(mp[i][j] && (!is_dead[mp[i][j]])){
if(mp[i][j]<=16){
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),4);
cout << nameoftype[type[mp[i][j]]] << " " ;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),7);
}
else {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),1);
cout << nameoftype[type[mp[i][j]]] << " " ;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),7);
}
}
else printf("0 ");
}
}
puts("x");
puts("轴") ;
putchar('\n');
if(!is_end){
if(current_round) puts("-----------红方回合-----------");
else puts("-----------蓝方回合-----------");
}
}
int main() {
init();
Q = read();
for(int round = 1; round<= Q; ++round) {
print_now();
int sx = read(), sy = read(), tx = read(), ty = read();
bool red_round = (current_round&1);
if((!mp[sx][sy]) || (is_red(mp[sx][sy])^red_round) ||((is_red(mp[tx][ty])^(red_round^1))&&mp[tx][ty]) ) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), B_YELLOW);
puts("操作不合法!");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),WHITE);
continue;
}
int CurrentType = type[mp[sx][sy]];
if(!is_allowed(sx, sy, tx, ty)) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), B_YELLOW);
puts("操作不合法!");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),WHITE);
continue;
}
cout << team[red_round] << nameoftype[CurrentType] <<";";
if(mp[tx][ty]) move_a_piece(tx, ty, red_round);
movexy(sx, sy, tx, ty);
if(check()) cout << "将军!;";
putchar('\n');
if(is_end){
print_now();
putchar('\n');
putchar('\n');
puts("游戏结束!");
if(winner){
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), RED);
puts("红方胜利!");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),WHITE);
} else{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BLUE);
puts("蓝方胜利!");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),WHITE);
}
system("pause");
return 0;
}
current_round^=1;
}
return 0;
}
posted @   霜木_Atomic  阅读(86)  评论(4编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
点击右上角即可分享
微信分享提示