象棋 (Xiangqi, ACM/ICPC Fuzhou 2011, UVa1589)

Description

Xiangqi is one of the most popular two-player board games in China. The game represents a battle between two armies with the goal of capturing the enemy’s “general” piece. In this problem, you are given a situation of later stage in the game. Besides, the red side has already “delivered a check”. Your work is to check whether the situation is “checkmate”.

Now we introduce some basic rules of Xiangqi. Xiangqi is played on a 10×9 board and the pieces are placed on the intersections (points). The top left point is (1,1) and the bottom right point is (10,9). There are two groups of pieces marked by black or red Chinese characters, belonging to the two players separately. During the game, each player in turn moves one piece from the point it occupies to another point. No two pieces can occupy the same point at the same time. A piece can be moved onto a point occupied by an enemy piece, in which case the enemy piece is “captured” and removed from the board. When the general is in danger of being captured by the enemy player on the enemy player’s next move, the enemy player is said to have “delivered a check”. If the general’s player can make no move to prevent the general’s capture by next enemy move, the situation is called “checkmate”.
We only use 4 kinds of pieces introducing as follows:
General: the generals can move and capture one point either vertically or horizontally and cannot leave the “palace” unless the situation called “flying general” (see the figure above). “Flying general” means that one general can “fly” across the board to capture the enemy general if they stand on the same line without intervening pieces.
Chariot: the chariots can move and capture vertically and horizontally by any distance, but may not jump over intervening pieces
Cannon: the cannons move like the chariots, horizontally and vertically, but capture by jumping exactly one piece (whether it is friendly or enemy) over to its target.
Horse: the horses have 8 kinds of jumps to move and capture shown in the left figure. However, if there is any pieces lying on a point away from the horse horizontally or vertically it cannot move or capture in that direction (see the figure below), which is called “hobbling the horse sleg”.

Now you are given a situation only containing a black general, a red general and several red chariots, cannons and horses, and the red side has delivered a check. Now it turns to black side’s move. Your job is to determine that whether this situation is “checkmate”.

Input

The input contains no more than 40 test cases. For each test case, the first line contains three integers representing the number of red pieces N (2<=N<=7) and the position of the black general. The following n lines contain details of N red pieces. For each line, there are a char and two integers representing the type and position of the piece (type char ‘G’ for general, ‘R’ for chariot, ‘H’ for horse and ‘C’ for cannon). We guarantee that the situation is legal and the red side has delivered the check.
There is a blank line between two test cases. The input ends by 0 0 0.

Sample Input

2 1 4
G 10 5
R 6 4

3 1 5
H 4 5
G 10 5
C 7 5

0 0 0

Sample Output

YES
NO

题目连接

http://acm.hdu.edu.cn/showproblem.php?pid=4121

大体思路
1,开始棋局的判断,可能红旗正对黑旗
2,模拟黑将走一步
3,写四个将军函数,分别是车,马, 炮, 帅将军函数
注意的地方
1,黑将可能杀死红棋
个人大体想到的暂时只有那么多,写了一部分代码,写完剩余代码在做总结. 2017/2/23

部分代码,还有马,炮的将军函数未写 2017/2/24

更新一下,写了炮的将军函数,改了一个潜在的BUG(模拟将军走路时候,删除模拟走一步的状态,否则下一步产生错误) 2017/2/25

最后跑了一些基本的测试数据,能通过,但是提交还是WA,还是有bug,找些测试数据慢慢改bug吧 2017/2/28

通过自己构建数据又修复了几个BUG,果断还是WA (2017/3/4)

#include 
#include 

using namespace std;

char map[11][10];

//改变黑棋子将军的位置
void change_pos_black(int t, int& x, int& y)
{
    if (t == 3)
    {
        x--;
    } else if (t == 2)
    {
        x++;
    } else if (t == 1)
    {
        y--;
    } else if (t == 0)
    {
        y++;
    }
}

//判断是否越界
bool yuejie_black(int x, int y)
{
    if (x < 1 || x > 3 || y < 4 || y > 6)
    {
        return true;
    }
    return false;
}

//判断两个旗子之间是否有棋子
bool exist_chest(char axis, int pos1, int pos2, int common_axis)
{
    if (axis == 'x')
    {
        for (int i = pos1 + 1; i < pos2; i++)
        {
            if (map[common_axis][i] != '0')
            {
                return true;
            }
        }
        return false;
    } else if (axis == 'y')
    {
        for (int i = pos1 + 1; i < pos2; i++)
        {
            if (map[i][common_axis] != '0')
            {
                return true;
            }
        }
        return false;
    }
}

//车杀死将军函数
bool kill_J_ju(int ju_x, int ju_y, int J_x, int J_y)
{
    int kill_J = 0;
    if (ju_x == J_x)
    {
        if (ju_y == J_y)
        {
            kill_J = 0; //黑将吃掉红棋子
        } else if (ju_y < J_y)
        {
            if (!exist_chest('y', ju_y, J_y, J_x))
            {
                kill_J = 1;
            }
        } else if (ju_y > J_y)
        {
            if (!exist_chest('y', J_y, ju_y, J_x))
            {
                kill_J = 1;
            }
        }
    } else if (ju_y == J_y)
    {
        if (ju_x == J_x)
        {
            kill_J = 0;
        } else if (ju_x < J_x)
        {
            if (!exist_chest('x', ju_x, J_x, J_y))
            {
                kill_J = 1;
            }
        } else if (ju_x > J_x)
        {
            if (!exist_chest('x', J_x, ju_x, J_y))
            {
                kill_J = 1;
            }
        }
    }
    if (kill_J == 1)
    {
        return true;
    } else
    {
        return false;
    }
}

//帅杀死将军函数
bool kill_J_G(int G_x, int G_y, int J_x, int J_y)
{
    int kill_J = 0;
    if (G_y == J_y)
    {
        if (!exist_chest('y', J_x, G_x, J_y))
        {
            kill_J = 1;
        }
    }
    if (kill_J == 1)
    {
        return true;
    } else
    {
        return false;
    }
}

//统计两个棋子之间的其他棋子个数
int count_other_chest(char axis, int pos1, int pos2, int common_chest)
{
    int count_chest = 0;
    if (axis == 'x')
    {
        for (int i = pos1 + 1; i < pos2; i++)
        {
            if (map[common_chest][i] != '0')
            {
                count_chest++;
            }
        }
    } else if (axis == 'y')
    {
        for (int i = pos1 + 1; i < pos2; i++)
        {
            if (map[i][common_chest] != '0')
            {
                count_chest++;
            }
        }
    }
    return count_chest;
}

//炮杀死将军
bool kill_J_pao(int J_x, int J_y, int pao_x, int pao_y)
{
    int kill_J = 0;
    int count_not_zero = 0;
    if (J_x == pao_x)  //行相等时
    {
        if (J_y == pao_y)
        {
            kill_J = 0;
        } else if (pao_y < J_y)
        {
            if (count_other_chest('x', pao_y, J_y, pao_x) == 1)
            {
                kill_J = 1;
            }
        } else if (pao_y > J_y)
        {
            if (count_other_chest('x', J_y, pao_y, pao_x) == 1)
            {
                kill_J = 1;
            }
        }
    } else if (J_y == pao_y) //列相等时
    {
        if (J_x == pao_x)
        {
            kill_J = 0;
        } else if (pao_x < J_x)
        {
            if (count_other_chest('y', pao_x, J_x, pao_y) == 1)
            {
                kill_J = 1;
            }
        } else if (pao_x > J_x)
        {
            if (count_other_chest('y', J_x, pao_x, pao_y) == 1)
            {
                kill_J = 1;
            }
        }
    } else  //行列都不想等时
    {
        kill_J = 0;
    }

    if (kill_J == 1)
    {
        return true;
    } else
    {
        return false;
    }
}

//马杀死黑将
bool kill_J_M(int M_x, int M_y, int J_x, int J_y)
{
    int kill_J = 0;
    if ((abs(M_x - J_x) == 2 && abs(M_y - J_y) == 1))
    {
        if (M_x < J_x)
        {
            if (map[M_x + 1][M_y] == '0')
            {
                kill_J = 1;
            }
        } else if (M_x > J_x)
        {
            if (map[M_x - 1][M_y] == '0')
            {
                kill_J = 1;
            }
        }
    } else if ((abs(M_x - J_x) == 1 && abs(M_y - J_y) == 2))
    {
        if (M_y < J_y)
        {
            if (map[M_x][M_y + 1] == '0')
            {
                kill_J = 1;
            }
        } else if (M_y > J_y)
        {
            if (map[M_x][M_y - 1] == '0')
            {
                kill_J = 1;
            }
        }
    }
    if (kill_J == 1)
    {
        return true;
    } else
    {
        return false;
    }
}

int main()
{
    int n_red, pos_black_x, pos_black_y;
    int pos_red_x[7], pos_red_y[7];
    while ((cin >> n_red >> pos_black_x >> pos_black_y) && n_red)
    {
        for (int i = 1; i <= 10; i++)
        {
            for (int j = 1; j <= 9; j++)
            {
                map[i][j] = '0';
            }
        }
        map[pos_black_x][pos_black_y] = 'J';

        for (int i = 0; i < n_red; i++)
        {
            char qizi;
            cin >> qizi >> pos_red_x[i] >> pos_red_y[i];
            map[pos_red_x[i]][pos_red_y[i]] = qizi;
        }

        //输出数据
//      for (int i = 1; i <= 10; i++)
//      {
//          for (int j = 1; j <= 9; j++)
//          {
//              cout << map[i][j] << " ";
//          }
//          cout << endl;
//      }

        //判断开局的局面是否是红棋输
        int begin = 0;
        for (int i = 0; i < n_red; i++)
        {
            if (map[pos_red_x[i]][pos_red_y[i]] == 'G')
            {
                if (pos_red_y[i] == pos_black_y)
                {
                    for (int line = pos_red_x[i] - 1; line > pos_black_x;
                            line--)
                    {
                        if (map[line][pos_black_y] != '0')
                        {
                            begin = 1;
                        }
                    }
                } else
                {
                    begin = 1;
                }
            }
        }
        if (begin == 0)
        {
            cout << "NO" << endl;
            continue;
        }

        //模仿将军走一步,记得更新黑将的状态,上一步的状态删除,上上步的状态删除
        int t = 4;
        int step_by_J = 0;
        char be_killed = '0';
        while (t--)
        {
//          cout << "**********" << endl;
            int temp_x = pos_black_x, temp_y = pos_black_y;
            change_pos_black(t, temp_x, temp_y);
            if (!yuejie_black(temp_x, temp_y))
            {
                step_by_J++;
                for (int i = 0; i < n_red; i++)
                {
                    if (temp_x == pos_red_x[i] && temp_y == pos_red_y[i])
                    {
                        be_killed = map[pos_red_x[i]][pos_red_y[i]];
                        pos_red_x[i] = 0;
                        pos_red_y[i] = 0;
                        break;
                    }
                }
                map[pos_black_x][pos_black_y] = '0';
                map[temp_x][temp_y] = 'J';
            } else if (yuejie_black(temp_x, temp_y))
            {
//              cout << "将军这一步越界了" << endl;
//              cout << "**********" << endl;
                continue;
            }
            //四个将军函数如下
            for (int i = 0; i < n_red; i++)
            {
                if (map[pos_red_x[i]][pos_red_y[i]] == 'R')  //车杀死将军
                {
                    int pos_C_x = pos_red_x[i];
                    int pos_C_y = pos_red_y[i];
//                  cout << "车 杀死将军的结果: "
//                          << kill_J_ju(pos_C_x, pos_C_y, temp_x, temp_y)
//                          << endl;
                    if (kill_J_ju(pos_C_x, pos_C_y, temp_x, temp_y) == 1)
                    {
                        step_by_J--;
                        break;
                    }
                } else if (map[pos_red_x[i]][pos_red_y[i]] == 'G')  //帅杀死黑将
                {
                    int pos_G_x = pos_red_x[i];
                    int pos_G_y = pos_red_y[i];
//                  cout << "帅 杀死将军的结果: "
//                          << kill_J_G(pos_G_x, pos_G_y, temp_x, temp_y)
//                          << endl;
                    if (kill_J_G(pos_G_x, pos_G_y, temp_x, temp_y) == 1)
                    {
                        step_by_J--;
                        break;
                    }
                } else if (map[pos_red_x[i]][pos_red_y[i]] == 'C')
                {
                    int pos_P_x = pos_red_x[i];
                    int pos_P_y = pos_red_y[i];
//                  cout << "炮 杀死将军的结果: "
//                          << kill_J_pao(temp_x, temp_y, pos_P_x, pos_P_y)
//                          << endl;
                    if (kill_J_pao(temp_x, temp_y, pos_P_x, pos_P_y) == 1)
                    {
                        step_by_J--;
                        break;
                    }
                } else if (map[pos_red_x[i]][pos_red_y[i]] == 'H')
                {
                    int pos_M_x = pos_red_x[i];
                    int pos_M_y = pos_red_y[i];
//                  cout << "马 杀死将军的结果: "
//                          << kill_J_M(pos_M_x, pos_M_y, temp_x, temp_y)
//                          << endl;
                    if (kill_J_M(pos_M_x, pos_M_y, temp_x, temp_y) == 1)
                    {
                        step_by_J--;
                        break;
                    }
                }
            }
            if (!yuejie_black(temp_x, temp_y))
            {
                map[temp_x][temp_y] = be_killed;
            }
//          cout << "**********" << endl;
        }
//      cout << "生存的次数: " << step_by_J << endl;
//      if (step_by_J > 0 && t == 0)
//      {
//          cout << "NO";
//      } else if (step_by_J < 0 && t == 0)
//      {
//          cout<<"YES";
//      }
//      else
        if (step_by_J > 0)
        {
            cout << "NO" << endl;
        } else
        {
            cout << "YES" << endl;
        }

    }
    return 0;
}

你可能感兴趣的:(算法----水,象棋)