2013年1月4日 星期五

[ZJ] d368. 10196 - Check the Check


內容 :
你的任務是寫一個程式,讀入一西洋棋盤的狀態,然後回答是否有國王(king)正處於可以攻擊(check)的狀態。
(像中國象棋的"將軍")
白方以大寫字元來表達各個角色,黑方以小寫字元來表達各個角色。棋賽一開始時白方在棋盤下方,黑方在棋盤上方。
如果你對西洋棋不熟的話,以下是各棋子角色的說明:
  • Pawn(士兵,以p或P表示)一次只能往前走一步,但是攻擊時卻是往左前方或右前方一格攻擊。
  • Knight(騎士,以n或N表示)走法比較特別,是走L形的,像中國象棋的馬,參考下面的圖。
  • Bishop(主教,以b或B表示)可以走對角線任意格。
  • Rook(城堡,以r或R表示)可以走直線任意格。
  • Queen(皇后,以q或Q表示)可以走對角線及直線任意格。像Bishop及Rook的綜合體。
  • King(國王,以k或K表示)可以走前後左右及對角線一格。
下圖就是各棋子的走法(*表示該棋子可以攻擊的格子)

Pawn...................................p......*.*...................
Rook...*.......*.......*.......*....***r****...*.......*.......*....
Bishop.......**.....*..*...*....*.*......b......*.*....*...*..*.....*.
Queen...*...**..*..*..*.*.*....***...***q****..***....*.*.*..*..*..*.
King..........................***.....*k*.....***...................
Knight..................*.*....*...*.....n.....*...*....*.*...........

記住:只有騎士可以跨過棋子攻擊,而士兵的攻擊是有方向性的
(白士兵只能向左上、右上攻擊,黑士兵只能向左下、右下攻擊)
輸入說明 :
每組測試資料8列,每列有8個字元。
'.' 代表空白格子而其他英文字元則代表上面說明的各角色。
不會有不該出現的字元出現,而且我們也保證不會有黑白雙方的國王均處於被check的狀態。
測試資料間有一空白列。輸入的最後一組測試資料內容全為'.',代表輸入結束。
(此組測試不需有輸出)
輸出說明 :
每組測試資料請輸出下列3種其中之一:
Game #d: white king is in check.
Game #d: black king is in check.
Game #d: no king is in check.
這裡d代表第幾組測試資料,從1開始。
範例輸入 :
..k.....ppp.pppp.........R...B..................PPPPPPPPK.......rnbqkbnrpppppppp................................PPPPPPPPRNBQKBNRrnbqk.nrppp..ppp....p......p.....bPP.........N..PP..PPPPRNBQKB.R................................................................
範例輸出 :
Game #1: black king is in check.Game #2: no king is in check.Game #3: white king is in check.
提示 :
出處 :
UVa ACM 10196 (管理:pcshic)

作法 : 模擬

/**********************************************************************************/
/*  Problem: d368 "10196 - Check the Check" from UVa ACM 10196                    */
/*  Language: C                                                                   */
/*  Result: AC (4ms, 266KB) on ZeroJudge                                          */
/*  Author: morris1028 at 2011-05-29 20:22:08                                     */
/**********************************************************************************/


#include<stdio.h>
#include<stdlib.h>
/*black 1a white 0A*/
char Map[8][9];
int bkx, bky, wkx, wky;
int D[8][2]={{0,1},{0,-1},
             {1,0},{-1,0},
             {1,1},{1,-1},
             {-1,1},{-1,-1}
            };
int S[8][2]={{2,1},{2,-1},
             {-2,1},{-2,-1},
             {1,2},{1,-2},
             {-1,2},{-1,-2}
            };
int find(int x, int y, int Dx, int Dy, int w, int a) {
    int t = 1;
    do {
        if(Map[x][y] != '.') {
            int p = (Map[x][y] >= 'a');
            if(p != w) return 0;
            else {
                int tp = Map[x][y] - p * ('a'-'A');
                switch(tp) {
                    case 'P':{if(w == 0) {
                                    if((a == 4 || a == 5) && t == 1)
                                        return 1;
                                }
                            else {
                                    if((a == 6 || a == 7) && t == 1)
                                        return 1;
                                }
                            }break;
                    case 'R':if(a < 4) return 1;break;
                    case 'B':if(a > 3) return 1;break;
                    case 'Q':return 1;break;
                }
                return 0;
            }
        }
        x += Dx, y += Dy, t++;
    }
    while(x >=0 && y >=0 && x < 8 && y < 8);
    return 0;
}
int Check(int x, int y, int who) {
    if(bkx < 0 || wkx < 0) return 0;
    int a, r = 0;
    for(a = 0; a < 8; a++) {
        r = find (x+D[a][0], y+D[a][1], D[a][0], D[a][1], who, a);
        if(r) break;
    }
    for(a = 0; a< 8; a++) {
        int xx = x + S[a][0], yy = y + S[a][1];
        if(xx < 0 || xx > 7 || yy < 0 || yy > 7) continue;
        if(Map[xx][yy] == 'n' || Map[xx][yy] == 'N') {
            int p = Map[xx][yy] == 'n';
            if(p == who) return 1;
        }
    }
    return r;
}
main() {
    int C = 0, a, b;
    while(1) {
        char flag = 1;
        int bkx = -1, bky = -1, wkx = -1, wky = -1;
        for(a = 0; a < 8; a++) {
            scanf("%s", &Map[a]);
            for(b = 0; b < 8; b++) {
                if(Map[a][b] != '.') flag = 0;
                if(Map[a][b] == 'k') bkx = a, bky = b;
                if(Map[a][b] == 'K') wkx = a, wky = b;
            }
        }
        if(flag == 1) break;
        printf("Game #%d: ", ++C);
        if(Check(wkx, wky, 1))
            puts("white king is in check.");
        else if(Check(bkx, bky, 0))
            puts("black king is in check.");
        else puts("no king is in check.");
    }
    return 0;
}

沒有留言:

張貼留言