UVa1589 - Xiangqi

题目

UVa1589

题解

这是我做的第一题非水题,可以明显感觉到水题与非水题之间的差别...
题目是以象棋为背景的,问题就是比较典型(?)的棋盘上的问题。
拿到题第一步是处理输入,照常做就好,毕竟做水题的时候对各种状况都有了尝试。不过需要注意的一点是,这里读入棋子 'C', 'R' 等时如果采用 getchar + %c 很可能过不了(即使测试的时候能过),笔者就是在这里n多次WA了,最后换成 %s 才终于AC

接下来是对数据的处理。

我一开始想到的也是把红棋所能到的地方都作标记来处理。不过后来想这好像有点麻烦,因为这种做法应该(我没具体尝试)只能在把全部红棋读入后,再遍历一次才能开始判断。而且遍历的过程貌似也不算简单,起码代码量繁多。再之这样做就会需要结构体的辅助,按顺序紫书只是到函数了而已。

所以我想了另一种方法:每次数据读入都立刻把棋子储存到棋盘里,在全部都读完了再开始对黑将的可走路径进行是否被击杀的判断。最终我对比其他作者的代码,代码量都是要少了不小的(一般都用了一百起步甚至两百行代码,笔者只有90行不到)。

在判断的时候由于同一条轴(比如x轴)是要分两个方向(正方)遍历的。这里就有一个小技巧,写第一层的for用于操控方向(-1或者1),然后第二层则只需令j += i即可按方向遍历整个轴,同时代码量减少,不必写过多重复的代码(这会令我烦躁)。

代码

#include <stdio.h>
#include <string.h>

char Map[12][11];
void solve(int x, int y);
int G(int x, int y);  //判断会不会被红帅击杀
int H(int x, int y);  //判断会不会被红马击杀
int RL(int x, int y);  //判断会不会被红炮、车、帅击杀

int main() {
#ifdef TEST
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    
    int n, bx, by, rx, ry; char ch[3];

    while (scanf("%d%d%d", &n, &bx, &by) && by) {
        for (int i = 0; i < 11; i++) memset(Map[i], '0', sizeof(Map[i]));
        for (int i = 0; i < n; i++) 
            scanf("%s%d%d", ch, &rx, &ry), Map[rx][ry] = ch[0];
    
        solve(bx, by);
    }

    return 0;
}

void solve(int x, int y) {
    int flag = 1;
    //直接飞将获得胜利
    if (G(x, y)) { printf("NO\n"); return; }  
    //i控制方向,判断黑将四个方位中可走的路径是否被击杀
    for (int i = -1; i <= 1; i += 2) {
        if (x + i >= 1 && x + i <= 3){
            if (!RL(x + i, y) && !H(x + i, y)) 
                flag = 0;
        }
        if (y + i <= 6 && y + i >= 4) {
            if (!RL(x, y + i) && !H(x, y + i))
                flag = 0;
        }
    }
    if (flag) printf("YES\n");
    else printf("NO\n");
}

int RL(int x, int y) {
    int flag = 0;
    //i控制方向,j遍历,考虑路上所有情况共5种
    for (int i = -1; i <= 1; i += 2, flag = 0) for (int j = x + i; j <= 10 && j >= 1; j += i) {
        if (Map[j][y] == '0') continue;
        else if (flag) {
            if (Map[j][y] == 'C') return 1;
            else break;
        }
        else if (Map[j][y] == 'H' || Map[j][y] == 'C') flag = 1;
        else return 1;
    }
    for (int i = -1; i <= 1; i += 2, flag = 0) for (int j = y + i; j <= 9 && j >= 1; j += i) {
        if (Map[x][j] == '0') continue;
        else if (flag) {
            if (Map[x][j] == 'C') return 1;
            else break;
        }
        else if (Map[x][j] == 'H' || Map[x][j] == 'C') flag = 1;
        else return 1;
    }
    return 0;
}

int H(int x, int y) {
    for (int i = -1; i <= 1; i += 2) for (int j = -1; j <= 1; j += 2)
        if (x + i && Map[x + i][y + j] == '0') {
            if (Map[x + i][y + 2 * j] == 'H')
                return 1;
            else if (x + 2 * i && Map[x + 2 * i][y + j] == 'H')
                return 1;
        }
    return 0;
}

int G(int x, int y){
    for (int i = x + 1; i <= 10; i++)
        if (Map[i][y] == '0') continue;
        else if (Map[i][y] == 'G') return 1;
        else return 0;
    return 0;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 快速小测试:如何重写下面的语句?要求不使用条件判断语句交换两个常量的值。 if (x == a) x= b; el...
    Colay阅读 4,434评论 0 0
  • 象棋文化中的科学意蕴 作为中华民族优秀文化遗产的象棋,自古即为广大民众喜闻乐见,在训练人的思维方式上起到了潜移默化...
    三毛毛子阅读 3,408评论 0 0
  • 1924年4月27日下午,时钟即将敲响2:00,在纽约市阿拉玛克酒店的一间大房里,俄罗斯国际象棋特级大师亚历山大·...
    速兔阅读 4,310评论 0 0
  • 地点:四川成都温度:9摄氏度~18摄氏度 成都游学第五天,我们的目的地有:四川大学、四川大学博物馆、杜甫草...
    Sandm浅笑阅读 2,394评论 0 1
  • 我会喜欢多久 我会忘记多久 我会想起多久 我觉得世事凉薄 我觉得情比纸薄 我觉得没有人爱我 转过头 原来我不爱任何人
    花花生xue阅读 2,929评论 3 5

友情链接更多精彩内容