【题解】UVA1589 象棋

题目传送门

究极模拟题。

这是旧文章,当时写的时候还不会用静态数组模拟移动,导致代码写的很繁杂,看看就好。

大体思路:

用一个二维数组记录整个棋盘,一个二维数组记录棋盘上每个点能否被红方棋子吃掉。模拟每个棋子并记录下能吃掉的位置,最后模拟黑将移动判断有没有将死。
红将、车和炮的模拟可以相同,定义一个表示攻击状态的变量,红将和车一开始就是攻击状态,碰到红子后停止该方向的模拟。炮开始不是攻击状态,碰到红子后进入攻击状态,再碰到红子停止该方向模拟。
马单独一个模拟。
黑将单独一个模拟。

几个要注意的点:

  • 棋子本身的位置是默认是不能被吃到的。
  • 车和红将以及炮进入攻击状态后,碰到的红棋子的位置也要记录为可以吃到,碰到黑将则不理会继续记录本方向,因为黑将在该方向上移动仍会被将死。
  • 炮在进入攻击状态前碰到红子,该红子位置不要被记录为可以吃到,如果碰到黑将则无需进入攻击状态,因为黑将能移动。
  • 马写的时候要仔细,我写的时候错了一个符号,debug了好久...

附上代码:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 11;
char board[maxn][maxn];
bool is[maxn][maxn];
struct cmd //存储命令用的结构
{
    char c;
    int a;
    int b;
} cmds[10];

void d(int x, int y, bool attack) //模拟车,炮,红将. attack表示攻击状态
{
    bool attack1 = attack;
    for (int i = x, j = y - 1; j != 0; j--)         //left
        if (board[i][j] != 0 && board[i][j] != 'E') //如果碰到红棋子
        {
            if (attack) //在攻击状态就设为可以吃到,并退出该方向
            {
                is[i][j] = true;
                break;
            }
            else            //不在攻击状态就进入攻击状态(炮)
                attack = 1; //遇到的第一个棋子是黑将不进入攻击状态
        }
        else if (attack) //在攻击状态也没碰到棋子就设为可以吃到
            is[i][j] = true;
    attack = attack1;                        //重置攻击状态
    for (int i = x, j = y + 1; j != 10; j++) //right
        if (board[i][j] != 0 && board[i][j] != 'E')
        {
            if (attack)
            {
                is[i][j] = true;
                break;
            }
            else
                attack = 1;
        }
        else if (attack)
            is[i][j] = true;
    attack = attack1;
    for (int i = x + 1, j = y; i != 11; i++) //down
        if (board[i][j] != 0 && board[i][j] != 'E')
        {
            if (attack)
            {
                is[i][j] = true;
                break;
            }
            else
                attack = 1;
        }
        else if (attack)
            is[i][j] = true;
    attack = attack1;
    for (int i = x - 1, j = y; i != 0; i--) //up
        if (board[i][j] != 0 && board[i][j] != 'E')
        {
            if (attack)
            {
                is[i][j] = true;
                break;
            }
            else
                attack = 1;
        }
        else if (attack)
            is[i][j] = true;
}

void h(int x, int y) //马
{
    //马的代码都差不多,四个方向分别考虑,写好一个复制一下仔细改改就行,记得考虑蹩马腿
    if (x >= 3 && board[x - 1][y] == 0) //up
    {
        if (y != 1)
            is[x - 2][y - 1] = 1;
        if (y != 9)
            is[x - 2][y + 1] = 1;
    }
    if (x <= 8 && board[x + 1][y] == 0) //down
    {
        if (y != 1)
            is[x + 2][y - 1] = 1;
        if (y != 9)
            is[x + 2][y + 1] = 1;
    }
    if (y >= 3 && board[x][y - 1] == 0) //left
    {
        if (x != 1)
            is[x - 1][y - 2] = 1;
        if (x != 10)
            is[x + 1][y - 2] = 1;
    }
    if (y <= 7 && board[x][y + 1] == 0) //right
    {
        if (x != 1)
            is[x - 1][y + 2] = 1;
        if (x != 10)
            is[x + 1][y + 2] = 1;
    }
}

void m(const char type, int x, int y) //命令处理
{
    if (type == 'R' || type == 'G')
        d(x, y, true); //车和红将直接攻击状态
    else if (type == 'C')
        d(x, y, false); //炮先不是攻击状态
    else if (type == 'H')
        h(x, y);
}

bool t(int x, int y) //判断黑将是否将死
{
    if (x == 1 || x == 2) //在1或2行判断能否向下走
        if (is[x + 1][y] == false)
            return 0;
    if (x == 2 || x == 3) //在2或3行判断能否向上走
        if (is[x - 1][y] == false)
            return 0;
    if (y == 4 || y == 5) //在4或5列判断能否向右走
        if (is[x][y + 1] == false)
            return 0;
    if (y == 6 || y == 5) //在5或6列判断能否向左走
        if (is[x][y - 1] == false)
            return 0;
    return 1;
}

int main()
{
    int n, x, y;
    char ch;
    while (cin >> n >> x >> y && n)
    {
        memset(board, 0, sizeof(board));
        memset(is, 0, sizeof(is));  //重置
        board[x][y] = 'E';          //E代表黑将
        int n1 = n, x1 = x, y1 = y; //复制一份信息备用
        while (n--)                 //输入
        {
            cin >> ch >> x >> y;
            cmds[n].c = ch;
            cmds[n].a = x;
            cmds[n].b = y;
            board[x][y] = ch;
        }
        while (n1--)
            m(cmds[n1].c, cmds[n1].a, cmds[n1].b); //执行每一个棋子
        bool bo = t(x1, y1);                       //判断
        if (bo)
            cout << "YES\n";
        else
            cout << "NO\n";
    }
    return 0;
}
posted @ 2021-03-07 11:04  _slb  阅读(104)  评论(0编辑  收藏  举报