社区讨论

代码求条

P5380[THUPC 2019] 鸭棋参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@miu4p7m2
此快照首次捕获于
2025/12/06 18:06
2 个月前
此快照最后确认于
2025/12/08 21:20
2 个月前
查看原帖
CPP
#include <bits/stdc++.h>
#include <windows.h>
using namespace std;
#define Debug cout<<endl<<endl<<endl
const int N=15;
int Q;
bool is_red=true;//现在是谁的回合(true为红方,false为蓝方)
bool is_end=false;//游戏是否结束
int xs,ys,xt,yt;
enum class piece
{
    none=0,//空位
    red_captain=1,//红方王
    red_guard=2,//红方士
    red_elephant=3,//红方象
    red_horse=4,//红方马
    red_car=5,//红方车
    red_duck=6,//红方鸭
    red_soldier=7,//红方卒
    blue_captain=8,//蓝方王
    blue_guard=9,//蓝方士
    blue_elephant=10,//蓝方象
    blue_horse=11,//蓝方马
    blue_car=12,//蓝方车
    blue_duck=13,//蓝方鸭
    blue_soldier=14,//蓝方卒
};
piece mp[N][N]={
    {piece::blue_car,piece::blue_horse,piece::blue_elephant,piece::blue_guard,piece::blue_captain,piece::blue_guard,piece::blue_elephant,piece::blue_horse,piece::blue_car},
    {piece::none,piece::none,piece::none,piece::none,piece::none,piece::none,piece::none,piece::none,piece::none},
    {piece::blue_duck,piece::none,piece::none,piece::none,piece::none,piece::none,piece::none,piece::none,piece::blue_duck},
    {piece::blue_soldier,piece::none,piece::blue_soldier,piece::none,piece::blue_soldier,piece::none,piece::blue_soldier,piece::none,piece::blue_soldier},
    {piece::none,piece::none,piece::none,piece::none,piece::none,piece::none,piece::none,piece::none,piece::none},
    {piece::none,piece::none,piece::none,piece::none,piece::none,piece::none,piece::none,piece::none,piece::none},
    {piece::red_soldier,piece::none,piece::red_soldier,piece::none,piece::red_soldier,piece::none,piece::red_soldier,piece::none,piece::red_soldier},
    {piece::red_duck,piece::none,piece::none,piece::none,piece::none,piece::none,piece::none,piece::none,piece::red_duck},
    {piece::none,piece::none,piece::none,piece::none,piece::none,piece::none,piece::none,piece::none,piece::none},
    {piece::red_car,piece::red_horse,piece::red_elephant,piece::red_guard,piece::red_captain,piece::red_guard,piece::red_elephant,piece::red_horse,piece::red_car}
};//初始化棋盘

//将输入的坐标转化为和数组下标对应的下标
void change(int &x,int &y)
{
    x=9-x;
}



//获取棋子能够到达的位置
vector<pair<int,int> > get_possible_pos(piece type,int x,int y)
{
    vector <pair<int,int> > pos;//存储能够到达的位置
    //红方棋子
    if(type==piece::red_captain)
    {
        if(mp[x][y+1]==piece::none || (mp[x][y+1]>=piece::blue_captain && mp[x][y+1]<=piece::blue_soldier))//为空或是蓝方棋子(吃子)
            pos.push_back({x,y+1});
        if(y-1>=0 && (mp[x][y-1]==piece::none || (mp[x][y-1]>=piece::blue_captain && mp[x][y-1]<=piece::blue_soldier)))//添加边界判断,避免访问下标-1的位置得到不确定的值
            pos.push_back({x,y-1});
        if(mp[x+1][y]==piece::none || (mp[x+1][y]>=piece::blue_captain && mp[x+1][y]<=piece::blue_soldier))
            pos.push_back({x+1,y});
        if(x-1>=0 && (mp[x-1][y]==piece::none || (mp[x-1][y]>=piece::blue_captain && mp[x-1][y]<=piece::blue_soldier)))
            pos.push_back({x-1,y});
    }
    else if(type==piece::red_guard)
    {
        if(mp[x+1][y+1]==piece::none || (mp[x+1][y+1]>=piece::blue_captain && mp[x+1][y+1]<=piece::blue_soldier))
            pos.push_back({x+1,y+1});
        if((x-1>=0 && y-1>=0) && (mp[x-1][y-1]==piece::none || (mp[x-1][y-1]>=piece::blue_captain && mp[x-1][y-1]<=piece::blue_soldier)))
            pos.push_back({x-1,y-1});
        if(y-1>=0 && (mp[x+1][y-1]==piece::none || (mp[x+1][y-1]>=piece::blue_captain && mp[x+1][y-1]<=piece::blue_soldier)))
            pos.push_back({x+1,y-1});
        if(x-1>=0 && (mp[x-1][y+1]==piece::none || (mp[x-1][y+1]>=piece::blue_captain && mp[x-1][y+1]<=piece::blue_soldier)))
            pos.push_back({x-1,y+1});
    }
    else if(type==piece::red_elephant)
    {
        for(int sx=-1;sx<=1;sx++)
            for(int sy=-1;sy<=1;sy++)
            {
                if(sx==0 || sy==0)//sx和sy不能取0
                    continue;
                if((x+sx>=0 && y+sy>=0) && (mp[x+sx][y+sy]==piece::none))//没有任意一方棋子停留
                    pos.push_back({x+2*sx,y+2*sy});
            }
    }
    else if(type==piece::red_horse)
    {
        for(int sx=-1;sx<=1;sx++)
            for(int sy=-1;sy<=1;sy++)
            {
                if(sx==0 || sy==0)
                    continue;
                if(x+sx>=0 && mp[x+sx][y]==piece::none)//无任何一方棋子停留
                    pos.push_back({x+2*sx,y+sy});
                if(y+sy>=0 && mp[x][y+sy]==piece::none)
                    pos.push_back({x+sx,y+2*sy});
            }
    }
    else if(type==piece::red_car)
    {
        for(int i=x-1;i>=0;i--)//向上扩展(不包含当前棋子)
        {
            if(mp[i][y]!=piece::none)//遇到其他棋子阻挡
                break;
            pos.push_back({i,y});
        }
        for(int i=x+1;i<10;i++)//向下扩展
        {
            if(mp[i][y]!=piece::none)//遇到其他棋子阻挡
                break;
            pos.push_back({i,y});
        }
        for(int i=y-1;i>=0;i--)//向左扩展
        {
            if(mp[x][i]!=piece::none)//遇到其他棋子阻挡
                break;
            pos.push_back({x,i});
        }
        for(int i=y+1;i<9;i++)//向右扩展
        {
            if(mp[x][i]!=piece::none)//遇到其他棋子阻挡
                break;
            pos.push_back({x,i});
        }
    }
    else if(type==piece::red_duck)
    {
        for(int sx=-1;sx<=1;sx++)
            for(int sy=-1;sy<=1;sy++)
            {
                if(sx==0 || sy==0)
                    continue;
                if((x+2*sx>=0 && y+sy>=0 && x+sx>=0) && (mp[x+2*sx][y+sy]==piece::none && mp[x+sx][y]==piece::none))
                    pos.push_back({x+3*sx,y+2*sy});
                if((x+sx>=0 && y+2*sy>=0 && y+sy>=0) && (mp[x+sx][y+2*sy]==piece::none && mp[x][y+sy]==piece::none))
                    pos.push_back({x+2*sx,y+3*sy});
            }
    }
    else if(type==piece::red_soldier)
    {
        if(mp[x+1][y]==piece::none || (mp[x+1][y]>=piece::blue_captain && mp[x+1][y]<=piece::blue_soldier))
            pos.push_back({x+1,y});
        if(x-1>=0 && (mp[x-1][y]==piece::none || (mp[x-1][y]>=piece::blue_captain && mp[x-1][y]<=piece::blue_soldier)))
            pos.push_back({x-1,y});
        if(mp[x][y+1]==piece::none || (mp[x][y+1]>=piece::blue_captain && mp[x][y+1]<=piece::blue_soldier))
            pos.push_back({x,y+1});
        if(y-1>=0 && (mp[x][y-1]==piece::none || (mp[x][y-1]>=piece::blue_captain && mp[x][y-1]<=piece::blue_soldier)))
            pos.push_back({x,y-1});
        if(mp[x+1][y+1]==piece::none || (mp[x+1][y+1]>=piece::blue_captain && mp[x+1][y+1]<=piece::blue_soldier))
            pos.push_back({x+1,y+1});
        if((x-1>=0 && y-1>=0) && (mp[x-1][y-1]==piece::none || (mp[x-1][y-1]>=piece::blue_captain && mp[x-1][y-1]<=piece::blue_soldier)))
            pos.push_back({x-1,y-1});
        if(y-1>=0 && (mp[x+1][y-1]==piece::none || (mp[x+1][y-1]>=piece::blue_captain && mp[x+1][y-1]<=piece::blue_soldier)))
            pos.push_back({x+1,y-1});
        if(x-1>=0 && (mp[x-1][y+1]==piece::none || (mp[x-1][y+1]>=piece::blue_captain && mp[x-1][y+1]<=piece::blue_soldier)))
            pos.push_back({x-1,y+1});
    }

    //蓝方棋子
    else if(type==piece::blue_captain)
    {
        if(mp[x][y+1]==piece::none || (mp[x][y+1]>=piece::red_captain && mp[x][y+1]<=piece::red_soldier))//为空或是红方棋子(吃子)
            pos.push_back({x,y+1});
        if(y-1>=0 && (mp[x][y-1]==piece::none || (mp[x][y-1]>=piece::red_captain && mp[x][y-1]<=piece::red_soldier)))
            pos.push_back({x,y-1});
        if(mp[x+1][y]==piece::none || (mp[x+1][y]>=piece::red_captain && mp[x+1][y]<=piece::red_soldier))
            pos.push_back({x+1,y});
        if(x-1>=0 && (mp[x-1][y]==piece::none || (mp[x-1][y]>=piece::red_captain && mp[x-1][y]<=piece::red_soldier)))
            pos.push_back({x-1,y});
    }
    else if(type==piece::blue_guard)
    {
        if(mp[x+1][y+1]==piece::none || (mp[x+1][y+1]>=piece::red_captain && mp[x+1][y+1]<=piece::red_soldier))
            pos.push_back({x+1,y+1});
        if((x-1>=0 && y-1>=0) && (mp[x-1][y-1]==piece::none || (mp[x-1][y-1]>=piece::red_captain && mp[x-1][y-1]<=piece::red_soldier)))
            pos.push_back({x-1,y-1});
        if(y-1>=0 && (mp[x+1][y-1]==piece::none || (mp[x+1][y-1]>=piece::red_captain && mp[x+1][y-1]<=piece::red_soldier)))
            pos.push_back({x+1,y-1});
        if(x-1>=0 && (mp[x-1][y+1]==piece::none || (mp[x-1][y+1]>=piece::red_captain && mp[x-1][y+1]<=piece::red_soldier)))
            pos.push_back({x-1,y+1});
    }
    else if(type==piece::blue_elephant)
    {
        for(int sx=-1;sx<=1;sx++)
            for(int sy=-1;sy<=1;sy++)
            {
                if(sx==0 || sy==0)//sx和sy不能取0
                    continue;
                if((x+sx>=0 && y+sy>=0) && (mp[x+sx][y+sy]==piece::none))//没有任意一方棋子停留
                    pos.push_back({x+2*sx,y+2*sy});
            }
    }
    else if(type==piece::blue_horse)
    {
        for(int sx=-1;sx<=1;sx++)
            for(int sy=-1;sy<=1;sy++)
            {
                if(sx==0 || sy==0)
                    continue;
                if(x+sx>=0 && mp[x+sx][y]==piece::none)//无任何一方棋子停留
                    pos.push_back({x+2*sx,y+sy});
                if(y+sy>=0 && mp[x][y+sy]==piece::none)
                    pos.push_back({x+sx,y+2*sy});
            }
    }
    else if(type==piece::blue_car)
    {
        for(int i=x-1;i>=0;i--)//向上扩展
        {
            if(mp[i][y]!=piece::none)//遇到其他棋子阻挡
                break;
            pos.push_back({i,y});
        }
        for(int i=x+1;i<10;i++)//向下扩展
        {
            if(mp[i][y]!=piece::none)//遇到其他棋子阻挡
                break;
            pos.push_back({i,y});
        }
        for(int i=y-1;i>=0;i--)//向左扩展
        {
            if(mp[x][i]!=piece::none)//遇到其他棋子阻挡
                break;
            pos.push_back({x,i});
        }
        for(int i=y+1;i<9;i++)//向右扩展
        {
            if(mp[x][i]!=piece::none)//遇到其他棋子阻挡
                break;
            pos.push_back({x,i});
        }
    }
    else if(type==piece::blue_duck)
    {
        for(int sx=-1;sx<=1;sx++)
            for(int sy=-1;sy<=1;sy++)
            {
                if(sx==0 || sy==0)
                    continue;
                if((x+2*sx>=0 && y+sy>=0 && x+sx>=0) && (mp[x+2*sx][y+sy]==piece::none && mp[x+sx][y]==piece::none))
                    pos.push_back({x+3*sx,y+2*sy});
                if((x+sx>=0 && y+2*sy>=0 && y+sy>=0) && (mp[x+sx][y+2*sy]==piece::none && mp[x][y+sy]==piece::none))
                    pos.push_back({x+2*sx,y+3*sy});
            }
    }
    else if(type==piece::blue_soldier)
    {
        if(mp[x+1][y]==piece::none || (mp[x+1][y]>=piece::red_captain && mp[x+1][y]<=piece::red_soldier))
            pos.push_back({x+1,y});
        if(x-1>=0 && (mp[x-1][y]==piece::none || (mp[x-1][y]>=piece::red_captain && mp[x-1][y]<=piece::red_soldier)))
            pos.push_back({x-1,y});
        if(mp[x][y+1]==piece::none || (mp[x][y+1]>=piece::red_captain && mp[x][y+1]<=piece::red_soldier))
            pos.push_back({x,y+1});
        if(y-1>=0 && (mp[x][y-1]==piece::none || (mp[x][y-1]>=piece::red_captain && mp[x][y-1]<=piece::red_soldier)))
            pos.push_back({x,y-1});
        if(mp[x+1][y+1]==piece::none || (mp[x+1][y+1]>=piece::red_captain && mp[x+1][y+1]<=piece::red_soldier))
            pos.push_back({x+1,y+1});
        if((x-1>=0 && y-1>=0) && (mp[x-1][y-1]==piece::none || (mp[x-1][y-1]>=piece::red_captain && mp[x-1][y-1]<=piece::red_soldier)))
            pos.push_back({x-1,y-1});
        if(y-1>=0 && (mp[x+1][y-1]==piece::none || (mp[x+1][y-1]>=piece::red_captain && mp[x+1][y-1]<=piece::red_soldier)))
            pos.push_back({x+1,y-1});
        if(x-1>=0 && (mp[x-1][y+1]==piece::none || (mp[x-1][y+1]>=piece::red_captain && mp[x-1][y+1]<=piece::red_soldier)))
            pos.push_back({x-1,y+1});
    }
    //剔除越界的位置(手动遍历,不能用for(auto p:pos),这样的话在删除元素后原迭代器可能失效)
    for(auto it=pos.begin();it!=pos.end();)
        if(it->first<0 || it->first>=10 || it->second<0 || it->second>=9)
            it=pos.erase(it);
        else
            it++;
    //剔除目标位置有己方棋子的位置
    for(auto it=pos.begin();it!=pos.end();)
    {
        bool cur_is_red=(mp[x][y]>=piece::red_captain && mp[x][y]<=piece::red_soldier);
        bool target_is_red=(mp[it->first][it->second]>=piece::red_captain && mp[it->first][it->second]<=piece::red_soldier);
        if(!(cur_is_red^target_is_red))
            it=pos.erase(it);
        else
            it++;
    }
    return pos;
}
//判断移动是否合法
bool check_move(piece type,int xs,int ys,int xt,int yt)
{
    vector <pair<int,int> > pos=get_possible_pos(type,xs,ys);//获取当前棋子从当前位置出发能够到达的位置有哪些
    for(auto p:pos)
        if(p.first==xt && p.second==yt)
            return true;//能够到达目标位置
    return false;//不能到达目标位置
}
//判断本次行动是否合法
bool judge(int xs,int ys,int xt,int yt)
{
    //判断游戏是否结束
    if(is_end)//游戏结束后的操作都不合法
        return false;
    //判断当前位置有没有己方棋子停留
    piece type=mp[xs][ys];//将要被移动的棋子是什么
    if(type==piece::none)//没有棋子必然不合法
        return false;
    if((type>=piece::red_captain && type<=piece::red_soldier)^is_red)//红方只能移动红方的棋子,蓝方只能移动蓝方的棋子
        return false;
    //判断棋子移动是否合法
    if(!check_move(type,xs,ys,xt,yt))//移动不合法
        return false;
    return true;
}



//移动棋子
void move(int xs,int ys,int xt,int yt)
{
    mp[xt][yt]=mp[xs][ys];//将棋子移动到目标位置
    mp[xs][ys]=piece::none;//将原位置清空
}
//输出棋子类型
void print_piece(piece type)
{
    switch(type)
    {
        case piece::red_captain:
            cout<<"red captain";
            break;
        case piece::red_guard:
            cout<<"red guard";
            break;
        case piece::red_elephant:
            cout<<"red elephant";
            break;
        case piece::red_horse:
            cout<<"red horse";
            break;
        case piece::red_car:
            cout<<"red car";
            break;
        case piece::red_duck:
            cout<<"red duck";
            break;
        case piece::red_soldier:
            cout<<"red soldier";
            break;
        case piece::blue_captain:
            cout<<"blue captain";
            break;
        case piece::blue_guard:
            cout<<"blue guard";
            break;
        case piece::blue_elephant:
            cout<<"blue elephant";
            break;
        case piece::blue_horse:
            cout<<"blue horse";
            break;
        case piece::blue_car:
            cout<<"blue car";
            break;
        case piece::blue_duck:
            cout<<"blue duck";
            break;
        case piece::blue_soldier:
            cout<<"blue soldier";
            break;
        default:
            break;
    }
}
//判断游戏是否结束
bool check_end()
{
    int cnt;//统计棋盘上王的个数
    for(int i=0;i<10;i++)
        for(int j=0;j<9;j++)
            if(mp[i][j]==piece::red_captain || mp[i][j]==piece::blue_captain)
                cnt++;
    if(cnt==2)
        return false;
    is_end=true;//修改结束标记
    return true;
}
//判断是否被将军
bool check_threat()
{
    for(int i=0;i<10;i++)
    {
        for(int j=0;j<9;j++)
        {
            if(mp[i][j]==piece::none || mp[i][j]==piece::red_captain || mp[i][j]==piece::blue_captain)
                continue;
            vector <pair<int,int> > pos=get_possible_pos(mp[i][j],i,j);
            for(auto p:pos)
            {
                if(mp[p.first][p.second]!=piece::red_captain || mp[p.first][p.second]!=piece::blue_captain)
                    continue;
                return true;//将军了对手(因为在get_possible_pos函数中已经判断了不能下在己方棋子上,所以只要能够到达的王必然是对方的王)
            }
        }
    }
    return false;
}
//回答问题
void answer(int xs,int ys,int xt,int yt)
{
    piece type=mp[xs][ys];//被移动的棋子是什么
    //输出这次被移动的棋子
    print_piece(type);
    cout<<";";
    //判断是否吃子
    if(mp[xt][yt]!=piece::none && (mp[xs][ys]>=piece::red_captain && mp[xs][ys]<=piece::red_soldier)^(mp[xt][yt]>=piece::red_captain && mp[xt][yt]<=piece::red_soldier))//有棋子且棋子不同才能吃子
        print_piece(mp[xt][yt]);
    else
        cout<<"NA";
    cout<<";";
    move(xs,ys,xt,yt);
    check_end();//先更新游戏状态再判断将军
    //判断是否被将军
    if(check_threat())
        cout<<"yes";
    else
        cout<<"no";
    cout<<";";
    //判断游戏是否结束
    if(is_end)
        cout<<"yes";
    else
        cout<<"no";
    cout<<endl;
}



//主函数
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    // for(int i=0;i<10;i++)
    // {
    //     for(int j=0;j<9;j++)
    //     {
    //         if(mp[i][j]==piece::none)
    //             continue;
    //         cout<<"("<<i<<","<<j<<")"<<"   ";
    //         print(mp[i][j]);
    //         cout<<endl;
    //         vector <pair<int,int> > pos=get_possible_pos(mp[i][j],i,j);
    //         for(auto p:pos)
    //             cout<<"("<<p.first<<","<<p.second<<")"<<endl;
    //     }
    //     cout<<endl<<endl<<endl;
    // }
    cin>>Q;
    while(Q--)
    {
        cin>>xs>>ys>>xt>>yt;
        change(xs,ys);
        change(xt,yt);
        //-----------------------------------------------------------------
        // printf("(%d,%d)   (%d,%d)\n",xs,ys,xt,yt);
        // vector <pair<int,int> > pos=get_possible_pos(mp[xs][ys],xs,ys);
        // for(auto p:pos)
        //     printf("(%d,%d)\n",p.first,p.second);
        //-----------------------------------------------------------------
        if(!judge(xs,ys,xt,yt))//操作不合法,跳过
        {
            cout<<"Invalid command"<<endl;
            //-----
            // Debug;
            //-----
            continue;
        }
        answer(xs,ys,xt,yt);//回答问题
        move(xs,ys,xt,yt);//移动棋子
        is_red=!is_red;//切换回合
        //-----
        // Debug;
        //-----
    }
    return 0;
}










// //输出带颜色的棋盘
// void print(piece p)
// {
//     switch(p)
//     {
//         case piece::none:
//             cout << "\033[0m·";
//             break;
//         case piece::red_captain:
//             cout << "\033[31m帥";
//             break;
//         case piece::red_guard:
//             cout << "\033[31m仕";
//             break;
//         case piece::red_elephant:
//             cout << "\033[31m相";
//             break;
//         case piece::red_horse:
//             cout << "\033[31m馬";
//             break;
//         case piece::red_car:
//             cout << "\033[31m車";
//             break;
//         case piece::red_duck:
//             cout << "\033[31m鸭";
//             break;
//         case piece::red_soldier:
//             cout << "\033[31m兵";
//             break;
//         case piece::blue_captain:
//             cout << "\033[34m將";
//             break;
//         case piece::blue_guard:
//             cout << "\033[34m士";
//             break;
//         case piece::blue_elephant:
//             cout << "\033[34m象";
//             break;
//         case piece::blue_horse:
//             cout << "\033[34m馬";
//             break;
//         case piece::blue_car:
//             cout << "\033[34m車";
//             break;
//         case piece::blue_duck:
//             cout << "\033[34m鸭";
//             break;
//         case piece::blue_soldier:
//             cout << "\033[34m卒";
//             break;
//     }
//     // 恢复默认颜色
//     cout << "\033[0m";
// }
// void write()//打印棋盘
// {
//     //控制使控制台输出字符为UTF-8编码
//     #ifdef _WIN32
//     system("chcp 65001");
//     #endif
//     for(int i=0;i<10;i++)
//     {
//         for(int j=0;j<9;j++)
//         {
//             print(mp[i][j]);
//             cout<<" ";
//         }
//         cout<<endl;
//     }
// }
代码如上。初步调试(输入数据为样例)发现在本应当输出blue captain;NA;no;no这一行的时候,get_possible_pos函数似乎没有获取到蓝方王能够到达的位置(调试的时候没有输出),但并不知道原因是什么。

回复

0 条回复,欢迎继续交流。

正在加载回复...