uva_1589象棋模拟题

输入] 输入数据≤40组,对于每组数据,第一行有三个数:第一个数代表红方棋数 N(2≤N≤7),第二三个数代表黑将的坐标 接下来N行每行一个字符两个数,代表每个红子的详细信息,字符为棋子种类车(®,马(H),炮©),数字为坐标. 输入所有棋子的位置,保证局面合法并且红方已经将军。
[输出] 对于每组输出数据,如已经将死 ,输出‘YES’,反之输出‘No’

模拟类问题的问题解决思路很重要,根据题意要求的模拟步骤一步步地做,通过循环结构实现每一步,不需要一次性将全部情况表现出来,这样会导致代码的杂乱。

重点问题

  1. 蹩马腿的判断可以用数组实现,详见代码。
  2. 棋子车和炮是否将军的判断可以根据棋子与将之间棋子的个数来判断,车与将之间为0,或炮与将之间为1都是将军(核心思想为两棋子间棋子个数的判断车为0,炮为1)。

细节代码:

int cnt(Chess p1, Chess p2)//数棋子的个数
{
    int cnt = 0;
    if (p1.x == p2.x)
    {
        int add = (p1.y < p2.y ? 1 : -1);
        for (int j = p1.y+add; j != p2.y; j += add)
        {
            if (tab[p1.x][j] != '0') cnt ++;
        }
    }
    else if (p1.y == p2.y) 
    {
        int add = (p1.x < p2.x ? 1 : -1);
        for (int j = p1.x+add; j != p2.x; j += add) 
        {
            if (tab[j][p1.y] != '0') cnt ++;
        }
    } 
    else
        cnt = 10;
    return cnt;
}

//下面的代码用于四类棋子的将军判断
if (pos[i].t == 'G' || pos[i].t == 'R')
{
      if (cnt(pos[0], pos[i]) == 0) return false;
}
else if (pos[i].t == 'C')
{
      if (cnt(pos[0], pos[i]) == 1) return false;
}
else
{
    for (int j = 0; j < 8; j ++)
	{
		if (pos[i].x + movH[j][0] == pos[0].x
		&& pos[i].y + movH[j][1] == pos[0].y
		&& tab[pos[i].x + mov[j/2][0]][pos[i].y + mov[j/2][1]] == '0')
	    return false;
	}
}

完整代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<bits/stdc++.h>
using namespace std;

char b[11][10];
struct chess
{
    int x,y;
    char type;
};
chess ch[20];

int mov[4][2]={0,-1,-1,0,0,1,1,0};
int hmov[8][2]={-1,-2,1,-2,-2,-1,-2,1,-1,2,1,2,2,-1,2,1};

bool legal_g(int x,int y)
{
    if(x<1||x>3||y<4||y>6)
        return false;
    return true;
}

bool legal(int x,int y)
{
    if(x<1||x>10||y<1||y>9)
        return false;
    return true;
}

int cnt(chess c1,chess c2)
{
    int cnt = 0;
    if(c1.x==c2.x)//在同一行
    {
        int dif = c1.y>c2.y?-1:1;
        for(int i=c1.y+dif;i!=c2.y;i+=dif)
        {
            if(b[c1.x][i]!='0')
                cnt++;
        }
    }

    else  if(c1.y==c2.y)
    {
        int dif = c1.x>c2.x?-1:1;
        for(int i=c1.x+dif;i!=c2.x;i+=dif)
        {
            if(b[i][c1.y]!='0')
                cnt++;
        }
    }
    else
        cnt=10;
    return cnt;
}

int main()
{
    /*#ifdef ONLINE_JUDGE
    #else
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
    #endif*/
    int n,x0,y0;
    while(cin>>n>>x0>>y0&&n)
    {
        memset(b,'0',sizeof(b));
        ch[0].x=x0,ch[0].y=y0,ch[0].type='g';
        for(int i=1;i<=n;i++)
        {
            cin>>ch[i].type>>ch[i].x>>ch[i].y;
            b[ch[i].x][ch[i].y]=ch[i].type;
        }

        bool ans = false;//判断是否能够存活
        for(int k=0;k<4;k++)
        {

            int nx = x0+mov[k][0];ch[0].x=nx;
            int ny = y0+mov[k][1];ch[0].y=ny;
            if(legal_g(nx,ny))
            {
                bool success = true;
                char tmp = b[nx][ny];
                b[nx][ny]='g';b[x0][y0]='0';
                for(int x=1;x<=n;x++)
                {
                    chess c = ch[x];
                    if(c.type=='G'||c.type=='R')
                    {
                        if(!(c.x==nx&&c.y==ny))
                        {
                            int cc = cnt(ch[0],c);
                            if(cc==0){success=false;}
                        }
                    }

                    if(c.type=='C')
                    {
                        if(!(c.x==nx&&c.y==ny))
                        {
                            int cc = cnt(ch[0],c);
                            if(cc==1)success=false;
                        }
                    }

                    if(c.type=='H'){
                        if(!(c.x==nx&&c.y==ny)){
                            for(int i=0;i<4;i++){
                                int hx=c.x+mov[i][0],hy=c.y+mov[i][1];
                                if(legal(hx,hy)&&b[hx][hy]=='0'){
                                    for(int j=i*2;j<=i*2+1;j++){
                                        hx=c.x+hmov[j][0];
                                        hy=c.y+hmov[j][1];
                                        if(legal(hx,hy)&&hx==nx&&hy==ny){
                                            i=4;
                                            success=false;
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                b[x0][y0]='g';b[nx][ny]=tmp;//恢复棋子
                if(success)
                {
                    //cout<<nx<<" "<<ny<<endl;
                    ans=true;
                }
            }
        }

        if(ans)
            cout<<"NO"<<endl;
        else
            cout<<"YES"<<endl;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值