算法習題---4-1象棋(UVa1589)

一:題目

在黑方只有一個「將」的狀況下,紅方只有(車、馬、炮)(能夠多個)、帥的狀況下,判斷黑方是否被將死

(一)題目詳解

其中棋盤按照座標方式表示,左上角爲(1,1),列數最大9,行數最大10
G  表示  將帥
R  表示  車
H  表示  馬
C  表示  炮

(二)樣例輸入

2 1 4  //第一行第一個數字:表示紅方有2個棋子  第二三個表示黑方「將」位置在(1,4)
G 10 5  //表示紅方「帥」在(10,5) 
R 6 4  //表示紅方「車」在(6,4)
  空行表示一次輸入結束
3 1 5  //第一行第一個數字:表示紅方有3個棋子 第二三個表示黑方「將」位置在(1,5)
H 4 5  //表示紅方「馬」在(4,5)
G 10 5  //表示紅方「帥」在(10,5)
C 7 5  //表示紅方「炮」在(7,5)

0 0 0  //全0表示結束

二:代碼實現

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define N 7
int Num;    //用於保存獲取的個數
int xq[N][3];    //棋盤數據

進行棋盤、座標數據獲取

int getData(int* r,int* c)
{
    int n;
    int i=0;

    //進行數據獲取
    while (1)
    {
        //獲取數據起始位置
        scanf("%d %d %d", &n, r, c);    //n在(2,7)之間
        Num = n;
        if (n == 0)
            return -1;    //所有結束

        //獲取數據,填充棋盤
        while (n--)
        {
            getchar();
            scanf("%c %d %d", (char*)&xq[i][0], &xq[i][1], &xq[i][2]);
            i++;
        }
        return 1;    //本次輸入結束
    }
}

判斷中間是否有棋子,返回棋子個數

int judgeCaseInMid(int r1,int c1, int r2, int c2)
{
    int j,min,max,count=0;
    min = max = 0;

    if (r1 == r2)    //判斷行上是否同行中間有棋子
    {
        c1 > c2 ? min = c2, max = c1 : min = c1, max = c2;
        for (j = 0; j < Num; j++)
            if (xq[j][1] == r1 && (xq[j][2]>min&&xq[j][2] < max))
                count++;    //有中間棋子
    }
    if (c1 == c2)    //判斷列上是否同列中間有棋子
    {
        r1 > r2 ? min = r2, max = r1 : min = r1, max = r2;
        for (j = 0; j < Num; j++)
            if (xq[j][2] == c1 && (xq[j][1]>min&&xq[j][1] < max))
                count++;    //有中間棋子
    }

    return count;    //返回棋子個數
}

單獨將馬拿出來處理:由於馬特殊

//判斷馬是否將死黑方    (r1,c1)爲馬,(r2,c2)爲敵將
bool judgeCaseForHorse(int r1, int c1, int r2, int c2)
{
    //利用勾股定理
    int a, b;
    a = r1 - r2;
    b = c1 - c2;

    if (a*a + b*b == 5)
    {
        //考慮別馬腿
        if ((r1 - r2) == 2)
        {
            for (int i = 0; i < Num; i++)
                if (xq[i][1] == r1 - 1 && xq[i][2] == c1)
                    return false;
        }

        if ((r1 - r2) == -2)
        {
            for (int i = 0; i < Num; i++)
                if (xq[i][1] == r1 + 1 && xq[i][2] == c1)
                    return false;
        }

        if ((c1 - c2) == 2)
        {
            for (int i = 0; i < Num; i++)
                if (xq[i][1] == c1 - 1 && xq[i][2] == r1)
                    return false;
        }

        if ((c1 - c2) == -2)
        {
            for (int i = 0; i < Num; i++)
                if (xq[i][1] == c1 + 1 && xq[i][2] == r1)
                    return false;
        }

        return true;
    }

    return false;
}

判斷黑方將下一步是否能夠走

//G是將 R是車 C是炮 H是馬
int judgeCKByNextByte(int r, int c)
{
    int i;
    //遍歷棋盤紅方數據,判斷是否將死這一步
    for (i = 0; i < Num;i++)
    {
        switch (xq[i][0])
        {
        case 'G':    //判斷將
            //判斷黑方是否在同一列
            if (xq[i][2] == c)
                if (!judgeCaseInMid(r, c, xq[i][1], xq[i][2]))
                    return 1;    //將死
            break;
        case 'R':    //判斷車
            //車能夠橫向縱向走
            //先判斷是否在同一行或者同一列
            if (xq[i][1] == r || xq[i][2] == c)    //同行/列
                //判斷是否中間有棋子
                if (!judgeCaseInMid(r, c, xq[i][1], xq[i][2]))
                    return 1;    //將死
            break;
        case 'C':    //判斷炮
            if (xq[i][1] == r || xq[i][2] == c)    //同行/列
                //判斷是否中間有棋子
                if (1==judgeCaseInMid(r, c, xq[i][1], xq[i][2]))
                    return 1;    //將死
            break;
        case 'H':    //判斷馬
            if (judgeCaseForHorse(xq[i][1], xq[i][2], r, c))
                return 1;
            break;
        }
    }
    return 0;
}

判斷是否將死黑方

bool judgeCK(int r, int c)
{
    //判斷將的運行空間(1,4)->(1,6) 
    //                  (2,4)->(2,6)
    //                (3,4)->(3,6)

    if (r >= 1 && r < 3)//向下走
        if (judgeCKByNextByte(r+1, c) == 0)
            return false;    //未將死
    
    if (r > 1 && r <= 3)//向上走
        if (judgeCKByNextByte(r - 1, c) == 0)
            return false;    //未將死

    if (c >= 4 && c < 6)//向右走
        if (judgeCKByNextByte(r, c + 1) == 0)
            return false;    //未將死

    if (c > 4 && c <= 6)//向左走
        if (judgeCKByNextByte(r, c - 1) == 0)
            return false;    //未將死

    if ((r == 1 && c == 4) || (r == 2 && c == 5))//右下走
        if (judgeCKByNextByte(r + 1, c + 1) == 0)
            return false;    //未將死

    if ((r == 3 && c == 6) || (r == 2 && c == 5))//左上走
        if (judgeCKByNextByte(r - 1, c - 1) == 0)
            return false;    //未將死

    if ((r == 1 && c == 6) || (r == 2 && c == 5))//左下走
        if (judgeCKByNextByte(r + 1, c - 1) == 0)
            return false;    //未將死

    if ((r == 3 && c == 4) || (r == 2 && c == 5))//右上走
        if (judgeCKByNextByte(r - 1, c + 1) == 0)
            return false;    //未將死

    return true;    //將死
}

主函數

int main()
{
    int row, col;

    freopen("data.in", "r", stdin);
    freopen("data.out", "w", stdout);

    while (1)
    {
        //進行數據輸入
        if (getData(&row, &col) == -1)
            return 0;
        //進行數據處理,判斷是否將死
        if (judgeCK(row, col))
            printf("YES\n");
        else
            printf("NO\n");
    }

    freopen("CON", "r", stdin);
    freopen("CON", "w", stdout);

    return 0;
}
相關文章
相關標籤/搜索