您的位置:首页 > 其它

象棋

2016-04-09 19:53 211 查看
[align=left]Problem Description[/align]
Xiangqi is one of the most popular two-player board games in China. The game represents a battle between two armies with the goal of capturing the enemy’s “general” piece. In this problem, you are given a situation of later stage in the game. Besides, the red side has already “delivered a check”. Your work is to check whether the situation is “checkmate”.
Now we introduce some basic rules of Xiangqi. Xiangqi is played on a 10×9 board and the pieces are placed on the intersections (points). The top left point is (1,1) and the bottom right point is (10,9). There are two groups of pieces marked by black or red Chinese characters, belonging to the two players separately. During the game, each player in turn moves one piece from the point it occupies to another point. No two pieces can occupy the same point at the same time. A piece can be moved onto a point occupied by an enemy piece, in which case the enemy piece is "captured" and removed from the board. When the general is in danger of being captured by the enemy player on the enemy player’s next move, the enemy player is said to have "delivered a check". If the general's player can make no move to prevent the general's capture by next enemy move, the situation is called “checkmate”.

We only use 4 kinds of pieces introducing as follows:

General: the generals can move and capture one point either vertically or horizontally and cannot leave the “palace” unless the situation called “flying general” (see the figure above). “Flying general” means that one general can “fly” across the board to capture the enemy general if they stand on the same line without intervening pieces.

Chariot: the chariots can move and capture vertically and horizontally by any distance, but may not jump over intervening pieces

Cannon: the cannons move like the chariots, horizontally and vertically, but capture by jumping exactly one piece (whether it is friendly or enemy) over to its target.

Horse: the horses have 8 kinds of jumps to move and capture shown in the left figure. However, if there is any pieces lying on a point away from the horse horizontally or vertically it cannot move or capture in that direction (see the figure below), which is called “hobbling the horse’s leg”.

Now you are given a situation only containing a black general, a red general and several red chariots, cannons and horses, and the red side has delivered a check. Now it turns to black side’s move. Your job is to determine that whether this situation is “checkmate”.

[align=left]Input[/align]
The input contains no more than 40 test cases. For each test case, the first line contains three integers representing the number of red pieces N (2<=N<=7) and the position of the black general. The following n lines contain details of N red pieces. For each line, there are a char and two integers representing the type and position of the piece (type char ‘G’ for general, ‘R’ for chariot, ‘H’ for horse and ‘C’ for cannon). We guarantee that the situation is legal and the red side has delivered the check. There is a blank line between two test cases. The input ends by 0 0 0.

[align=left]Output[/align]
For each test case, if the situation is checkmate, output a single word ‘YES’, otherwise output the word ‘NO’.

[align=left]Sample Input[/align]

2 1 4
G 10 5
R 6 4

3 1 5

H 4 5

G 10 5

C 7 5

0 0 0

[align=left]Sample Output[/align]

YES
NO

Hint



In the first situation, the black general is checked by chariot and “flying general”.
In the second situation, the black general can move to (1, 4) or (1, 6) to stop check.
See the figure above.

情况很多!加油!!!
定义一个新的棋盘所有元素为0,将红方可以到达的地方设定为1,然后若黑方走到的地方元素都为1,则黑方失败。
WA代码

#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
char chu[12][11];
int hong[15][15];       //初始棋盘为chu,红方棋子能到达的地方为hong
int x[8],y[8];
void GorR(int x,int y)
{
for(int i=y+1;i<10;i++){
if(chu[x][i]!='0')break;
hong[x][i]=1;
}
for(int i=y-1;i>0;i--){
if(chu[x][i]!='0')break;
hong[x][i]=1;
}
for(int j=x+1;j<11;j++){
if(chu[j][y]!='0')break;
hong[j][y]=1;
}
for(int j=x-1;j>0;j--){
if(chu[j][y]!='0')break;
hong[j][y]=1;
}
}

void C(int x,int y)
{
bool flag=false;
for(int i=x-1;i>0;i--){
if(flag==false){
if(chu[i][y]!='0')flag=true;
}
else{
if(chu[i][y]=='0'||chu[i][y]=='J')hong[i][y]=1;
else flag=false;
}
}
flag=false;
for(int i=x+1;i<11;i++){
if(flag==false){
if(chu[i][y]!='0')flag=true;
}
else{
if(chu[i][y]=='0'||chu[i][y]=='J')hong[i][y]=1;
else flag=false;
}
}
flag=false;
for(int i=y-1;i>0;i--){
if(flag==false){
if(chu[x][i]!='0')flag=true;
}
else{
if(chu[x][i]=='0'||chu[i][y]=='J')hong[x][i]=1;
else flag=false;
}
}
flag=false;
for(int i=y+1;i<10;i++){
if(flag==false){
if(chu[x][i]!='0')flag=true;
}
else{
if(chu[x][i]=='0'||chu[i][y]=='J')hong[x][i]=1;
else flag=false;
}
}
}

void H(int x,int y)
{
cout<<x-1<<" "<<y<<" "<<chu[x-1][y]<<endl;
if(chu[x-1][y]=='0'){
hong[x-2][y-1]=1;
hong[x-2][y+1]=1;
}
if(chu[x+1][y]=='0'){
hong[x+2][y-1]=1;
hong[x+2][y+1]=1;
}
if(chu[x][y-1]=='0'){
hong[x-1][y-2]=1;
hong[x+1][y-2]=1;
}
if(chu[x][y+1]=='0'){
hong[x-1][y+2]=1;
hong[x+1][y+2]=1;
}
}

void hong_get(int n)
{
for(int i=0;i<n;i++){
if(chu[x[i]][y[i]]=='H')H(x[i],y[i]);
if(chu[x[i]][y[i]]=='G'||chu[x[i]][y[i]]=='R')GorR(x[i],y[i]);
if(chu[x[i]][y[i]]=='C')C(x[i],y[i]);
}
}

int J_get(int x,int y)
{
if(x-1>0){
if(hong[x-1][y]==0)return 0;
}
if(x+1<4){
if(hong[x+1][y]==0)return 0;
}
if(y-1>3){
if(hong[x][y-1]==0)return 0;
}
if(y+1<7){
if(hong[x][y+1]==0)return 0;
}
return 1;
}

int main()
{
int n,x0,y0,x1,y1,result;                   //n个红方和一个黑方的位置
while(scanf("%d%d%d",&n,&x0,&y0)&&n!=0){
memset(chu,'0',sizeof(chu));
memset(hong,0,sizeof(hong));
chu[x0][y0]='J';                //黑方的将存为J
for(int i=0;i<n;i++){
char ch;
cin>>ch>>x[i]>>y[i];        //G为帅,R为车,H为马,C为炮
chu[x[i]][y[i]]=ch;
}
/*for(int j=1;j<11;j++){
for(int i=1;i<10;i++)cout<<chu[j][i]<<" ";
cout<<endl;
}*/
hong_get(n);
result=J_get(x0,y0);
/*cout<<"***"<<endl<<endl;
for(int j=1;j<11;j++){
for(int i=1;i<10;i++)cout<<hong[j][i]<<" ";
cout<<endl;
}*/
if(result==0)cout<<"NO"<<endl;
else cout<<"YES"<<endl;
}
//system("pause");
return 0;
}


思路关键:::要想到设定一个新棋盘来标志红方可以走到的地方!

以上代码细节错误很多!!

AC代码以下

#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
char chu[12][11];
int hong[15][15];       //初始棋盘为chu,红方棋子能到达的地方为hong
int x[8],y[8];

void GorR(int x,int y)
{
for(int i=y+1;i<10;i++){
hong[x][i]=1;
if(chu[x][i]!='0'&&chu[x][i]!='J')break;

}
for(int i=y-1;i>0;i--){
hong[x][i]=1;
if(chu[x][i]!='0'&&chu[x][i]!='J')break;

}
for(int j=x+1;j<11;j++){
hong[j][y]=1;
if(chu[j][y]!='0'&&chu[x][j]!='J')break;

}
for(int j=x-1;j>0;j--){
hong[j][y]=1;
if(chu[j][y]!='0'&&chu[x][j]!='J')break;

}
}

void C(int x,int y)
{
bool flag=false;
if(y>=4&&y<=6&&x==1)
if(chu[2][y]!='0'&&chu[2][y]!='J') hong[3][y]=1;
for(int i=x-1;i>0;i--){
if(flag==false){
if(chu[i][y]=='J')return;
if(chu[i][y]!='0')flag=true;
}
else{
if(chu[i][y]=='0'||chu[i][y]=='J')hong[i][y]=1;
else break;
}
}
flag=false;
for(int i=x+1;i<11;i++){
if(flag==false){
if(chu[i][y]=='J')return;
if(chu[i][y]!='0')flag=true;
}
else{
if(chu[i][y]=='0'||chu[i][y]=='J')hong[i][y]=1;
else break;
}
}
flag=false;
for(int i=y-1;i>0;i--){
if(flag==false){
if(chu[i][y]=='J')return;
if(chu[x][i]!='0')flag=true;
}
else{
if(chu[x][i]=='0'||chu[i][y]=='J')hong[x][i]=1;
else break;
}
}
flag=false;
for(int i=y+1;i<10;i++){
if(flag==false){
if(chu[i][y]=='J')return;
if(chu[x][i]!='0')flag=true;
}
else{
if(chu[x][i]=='0'||chu[i][y]=='J')hong[x][i]=1;
else break;
}
}
}

void H(int x,int y)
{
if(chu[x][y+1]=='0'&&y+2<=9&&x-1>=1)hong[x-1][y+2]=1;
if(chu[x][y+1]=='0'&&y+2<=9&&x+1<11)hong[x+1][y+2]=1;
if(chu[x][y-1]=='0'&&y-2>=1&&x-1>=1)hong[x-1][y-2]=1;
if(chu[x][y-1]=='0'&&y-2>=1&&x+1<11)hong[x+1][y-2]=1;
if(chu[x+1][y]=='0'&&y-1>=1&&x+2<11)hong[x+2][y-1]=1;
if(chu[x+1][y]=='0'&&y+1<=9&&x+2<11)hong[x+2][y+1]=1;
if(chu[x-1][y]=='0'&&y-1>=1&&x-2>=1)hong[x-2][y-1]=1;
if(chu[x-1][y]=='0'&&y+1<=9&&x-2>=1)hong[x-2][y+1]=1;
}

void hong_get(int n)
{
for(int i=0;i<n;i++){
if(chu[x[i]][y[i]]=='H')H(x[i],y[i]);
else if(chu[x[i]][y[i]]=='G'||chu[x[i]][y[i]]=='R')GorR(x[i],y[i]);
else if(chu[x[i]][y[i]]=='C')C(x[i],y[i]);
}
}

int J_get(int x,int y)
{
if(x-1>0&&hong[x-1][y]==0)return 0;
if(x+1<4&&hong[x+1][y]==0)return 0;
if(y-1>3&&hong[x][y-1]==0)return 0;
if(y+1<7&&hong[x][y+1]==0)return 0;
return 1;
}

int main()
{
int n,x0,y0,result;                   //n个红方和一个黑方的位置
while(scanf("%d%d%d",&n,&x0,&y0)&&n!=0){
memset(chu,'0',sizeof(chu));
memset(hong,0,sizeof(hong));
chu[x0][y0]='J';                //黑方的将存为J
for(int i=0;i<n;i++){
char ch;
cin>>ch>>x[i]>>y[i];        //G为帅,R为车,H为马,C为炮
chu[x[i]][y[i]]=ch;
}
/* for(int j=1;j<11;j++){
for(int i=1;i<10;i++)cout<<chu[j][i]<<" ";
cout<<endl;
}*/
hong_get(n);
result=J_get(x0,y0);
/*cout<<"***"<<endl<<endl;
for(int j=1;j<11;j++){
for(int i=1;i<10;i++)cout<<hong[j][i]<<" ";
cout<<endl;
}*/
if(result==0)cout<<"NO"<<endl;
else cout<<"YES"<<endl;
}
//system("pause");
return 0;
}


比较结果错误的代码 和 AC代码

Ⅰ void GorR(int x,int y)

WA代码中,先判断条件chu[x][i]!='0' ,若成立,退出循环,那么chu[x][i]这一项的hong未被变为1,而这一项被一个棋子占用,黑方的将根本无法到达,所以该项的hong也应该被设定为1。

Ⅱ void C(int x,int y)

首先,炮只能隔一个棋子吃对方的棋子,WA代码中将这个概念理解错误,使炮隔一个,三个,五个....棋子时都可以吃棋子,即代码中同一循环中flag变为true时,不应再将其还原为false,还原的话就实现了炮的“连吃”。

第二点,当炮与黑方的将之间无其他棋子时,就可直接退出炮函数,因为他两相邻,红方走一步不可能用炮打败黑方,因此添加代码 if(chu[i][y]=='J')return;

第三点,当炮的一方向已有一个棋子时即flag=true后继续向这一方向检索,若检索到的下一个棋子不是黑方的将,也可直接退出循环,同样红方走一步不可能用炮打败黑方,因此AC代码中添加 else break;

Ⅲ void H(int x,int y)

马的一侧被一个棋子挡住,不能向这一侧的两个位置走,而这两个位置是否在棋盘内是独立的关系,所以不能将两种情况用一个条件判断,将其分开写即可,各自的条件对应各自的操作。

细心细心细心!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: