C++双人象棋

· · 科技·工程

#include<bits/stdc++.h>
#include<windows.h>
#include<Windows.h>
#define color(a) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),a)
#define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME)&0x8000)?1:0)
#define down KEY_DOWN(VK_LBUTTON)//判断是否按下鼠标 
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
HWND h=GetForegroundWindow();
CONSOLE_FONT_INFO consoleCurrentFont;
void HideTheCursor()//隐藏光标
{
    CONSOLE_CURSOR_INFO cciCursor;
    HANDLE hStdOut=GetStdHandle(STD_OUTPUT_HANDLE);
    if(GetConsoleCursorInfo(hStdOut,&cciCursor)){cciCursor.bVisible=FALSE;SetConsoleCursorInfo(hStdOut,&cciCursor);}
}
void gotoxy(short x,short y)//移动光标 
{
    COORD pos={x,y};
    HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(hOut,pos);
}
POINT downpos()//按下鼠标的位置 
{
    POINT p;
    GetCursorPos(&p);
    ScreenToClient(h,&p);
    GetCurrentConsoleFont(hOutput,FALSE,&consoleCurrentFont);
    int x=p.x/consoleCurrentFont.dwFontSize.X;
    int y=p.y/consoleCurrentFont.dwFontSize.Y;
    return (POINT){x,y};
}
const int N=55,n=19,m=17,boundd=60;
using namespace std;
struct Chess{string name; int zy;}chess[N][N];
bool hef(int x,int y){
    return (1<=x && x<=n) & (1<=y && y<=m);
}
void clear(int x,int y){chess[x][y].name="  ";chess[x][y].zy=2;}
bool turn;//阵营0红1黑2环境 
int step,eatc,pec;
double w1,w2;
void init(){
    HideTheCursor();
    HANDLE hStdIn=GetStdHandle(STD_INPUT_HANDLE);
    DWORD mode;
    GetConsoleMode(hStdIn, &mode);
    mode&=~ENABLE_QUICK_EDIT_MODE;
    SetConsoleMode(hStdIn,mode);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)chess[i][j].name="  ",chess[i][j].zy=2;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(i==10)continue;
            if(!(j&1)&&i&1)chess[i][j].name="--",chess[i][j].zy=2;
            if(!(i&1)&&j&1)chess[i][j].name="丨",chess[i][j].zy=2;
        }
    }
    for(int j=1;j<=m;j++)
        if(j%4==1)chess[7][j].name="兵",chess[7][j].zy=0;
    chess[1][1].name=chess[1][17].name="俥",chess[1][1].zy=0,chess[1][17].zy=0;
    chess[1][3].name=chess[1][15].name="馬",chess[1][3].zy=0,chess[1][15].zy=0;
    chess[1][5].name=chess[1][13].name="相",chess[1][5].zy=0,chess[1][13].zy=0;
    chess[1][7].name=chess[1][11].name="仕",chess[1][7].zy=0,chess[1][11].zy=0;
    chess[5][3].name=chess[5][15].name="砲",chess[5][3].zy=0,chess[5][15].zy=0;
    chess[1][9].name="帅",chess[1][9].zy=0;
    for(int j=1;j<=m;j++)
        if(j%4==1)chess[13][j].name="卒",chess[13][j].zy=1;
    chess[19][1].name=chess[19][17].name="車",chess[19][1].zy=1,chess[19][17].zy=1;
    chess[19][3].name=chess[19][15].name="马",chess[19][3].zy=1,chess[19][15].zy=1;
    chess[19][5].name=chess[19][13].name="象",chess[19][5].zy=1,chess[19][13].zy=1;
    chess[19][7].name=chess[19][11].name="士",chess[19][7].zy=1,chess[19][11].zy=1;
    chess[15][3].name=chess[15][15].name="炮",chess[15][3].zy=1,chess[15][15].zy=1;
    chess[19][9].name="将",chess[19][9].zy=1;
}
pair<int,int> hashh(int o){//0防御 1进攻 
    int cnt1=0,cnt2=0;
    int px1=0,py1=0,px2=0,py2=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(chess[i][j].name=="帅"){
                px1=i;
                py1=j; 
            }
            if(chess[i][j].name=="将"){
                px2=i;
                py2=j; 
            }
        }
    } 
    if(o){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                double dis1=sqrt((px1-i)*(px1-i)+(py1-j)*(py1-j)),dis2=sqrt((px2-i)*(px2-i)+(py2-j)*(py2-j)),bl1=1/sqrt(dis1),bl2=1/sqrt(dis2);
                if(chess[i][j].name=="俥") cnt1+=100*bl2;
                else if(chess[i][j].name=="車") cnt2+=100*bl1;
                else if(chess[i][j].name=="馬"){
                    if(step<=40) cnt1+=70*bl2;
                    else if(step<=80) cnt1+=80*bl2;
                    else cnt1+=85*bl2;
                }
                else if(chess[i][j].name=="马"){
                    if(step<=40) cnt2+=70*bl1;
                    else if(step<=80) cnt2+=80*bl1;
                    else cnt2+=85*bl1;
                }
                else if(chess[i][j].name=="砲"){
                    if(step<=40) cnt1+=85*bl2;
                    else if(step<=80) cnt1+=75*bl2;
                    else cnt1+=50*bl2;
                }
                else if(chess[i][j].name=="炮"){
                    if(step<=40) cnt2+=85*bl1;
                    else if(step<=80) cnt2+=75*bl1;
                    else cnt2+=50*bl1;
                }
                else if(chess[i][j].name=="兵"){
                    if(step<=40) cnt1+=10*bl2;
                    else if(step<=80) cnt1+=15*bl2;
                    else{
                        if(i>=11) cnt1+=30*bl2;
                        else cnt1+=15*bl2;
                    }
                }
                else if(chess[i][j].name=="卒"){
                    if(step<=40) cnt2+=10*bl1;
                    else if(step<=80) cnt2+=15*bl1;
                    else{
                        if(i<=9) cnt2+=30*bl1;
                        else cnt2+=15*bl1;
                    }
                }
            }
        }
    }
    else{
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                double dis1=sqrt((px1-i)*(px1-i)+(py1-j)*(py1-j)),dis2=sqrt((px2-i)*(px2-i)+(py2-j)*(py2-j)),bl1=1/dis1,bl2=1/dis2;
                if(chess[i][j].name=="俥"){
                    if(step<=40) cnt1+=30*bl1;
                    else cnt1+=40*bl1;
                }
                else if(chess[i][j].name=="車"){
                    if(step<=40) cnt2+=30*bl2;
                    else cnt2+=40*bl2;
                }
                else if(chess[i][j].name=="馬"){
                    if(step<=40) cnt1+=30*bl1;
                    else if(step<=80) cnt1+=40*bl1;
                    else cnt1+=45*bl1;
                }
                else if(chess[i][j].name=="马"){
                    if(step<=40) cnt2+=30*bl2;
                    else if(step<=80) cnt2+=40*bl2;
                    else cnt2+=45*bl2;
                }
                else if(chess[i][j].name=="砲"){
                    if(step<=40) cnt1+=15*bl1;
                    else if(step<=80) cnt1+=10*bl1;
                    else cnt1+=5*bl1;
                }
                else if(chess[i][j].name=="炮"){
                    if(step<=40) cnt2+=15*bl2;
                    else if(step<=80) cnt2+=10*bl2;
                    else cnt2+=5*bl2; 
                }
                else if(chess[i][j].name=="仕"){
                    if(step<=40) cnt1+=40;
                    else if(step<=80) cnt1+=50;
                    else cnt1+=60;
                }
                else if(chess[i][j].name=="士"){
                    if(step<=40) cnt2+=40;
                    else if(step<=60) cnt2+=50;
                    else cnt2+=60;
                }
                else if(chess[i][j].name=="相"){
                    if(step<=80) cnt1+=30*bl1;
                    else cnt1+=35*bl1;
                }
                else if(chess[i][j].name=="象"){
                    if(step<=80) cnt2+=30*bl2;
                    else cnt2+=35*bl2; 
                }
            }
        }
    }
    return make_pair(cnt1,cnt2);
}
int checkline(int x,int y,int _y){
    if(y>_y) swap(y,_y);
    int cnt=0;
    for(int i=y+1; i<=_y-1; i++){
        if(chess[i][x].zy<=1) cnt++;
    }
    return cnt;
}
int checkrow(int y,int x,int _x){
    if(x>_x) swap(x,_x);
    int cnt=0;
    for(int i=x+1; i<=_x-1; i++){
        if(chess[y][i].zy<=1) cnt++;
    }
    return cnt;
}
bool can_move(string name,int x,int y,int _x,int _y){
    swap(x,y),swap(_x,_y);
    if(!hef(_y,_x) && !hef(y,x)) return 0;
    if(chess[y][x].zy!=turn) return 0;
    if(x==_x && y==_y) return 0;
    if(chess[y][x].zy==chess[_y][_x].zy) return 0; 
    if(name=="俥" || name=="車"){
        if(x==_x && !checkline(x,y,_y)) 
            return 1;
        else if(y==_y && !checkrow(y,x,_x)) 
            return 1;
        return 0;
    } else if(name=="砲" || name=="炮"){
        if(x==_x && checkline(x,y,_y)==0 && chess[_y][_x].zy==2) 
            return 1;
        else if(y==_y && checkrow(y,x,_x)==0 && chess[_y][_x].zy==2) 
            return 1;
        else if(x==_x && checkline(x,y,_y)==1 && chess[_y][_x].zy+chess[y][x].zy==1)
            return 1;
        else if(y==_y && checkrow(y,x,_x)==1 && chess[_y][_x].zy+chess[y][x].zy==1)
            return 1; 
        else return 0;
    }else if(name=="马" || name=="馬"){
        bool f1=0,f2=1;
        int dx=abs(x-_x),dy=abs(y-_y);
        if(dx&1 || dy&1) return 0;
        if(dx+dy==6 && dx && dy)
            f1=1;
        if(dx==4 && chess[y][(x+_x)/2].zy<=1) //别马腿 
            f2=0;
        if(dy==4 && chess[(y+_y)/2][x].zy<=1) //别马腿 
            f2=0;
        return f1&f2;
    }
    else if(name=="相" || name=="象"){
        bool f1=0,f2=1;
        if(name=="相" && _y>=11) return 0;
        if(name=="象" && _y<=9) return 0;
        int dx=abs(x-_x),dy=abs(y-_y);
        if(dx&1 || dy&1) return 0;
        if(dx+dy==8 && dx==dy)
            f1=1;
        if(chess[(y+_y)/2][(x+_x)/2].zy<=1) //塞象眼 
            f2=0;
        return f1&f2;
    }else if(name=="兵" || name=="卒"){
        int dx=abs(x-_x),dy=abs(y-_y);
        if(name=="兵"){
            if(_y>=11)
                if(dx+dy==2 && (_y-y==2 || dx==2)) return 1;
            if(_y-y==2 && !dx) return 1;
            return 0;
        } 
        if(name=="卒"){
            if(_y<=9)
                if(dx+dy==2 && (_y-y==-2 || dx==2)) return 1;
            if(_y-y==-2 && !dx) return 1;
            return 0;
        }
    } else if(name=="士" || name=="仕"){
        int dx=abs(x-_x),dy=abs(y-_y);
        if(name=="仕"){
            if(_y>5 || _x>11 || _x<7) return 0;
            if(dx!=2 || dy!=2) return 0;
            return 1;
        } 
        if(name=="士"){
            if(_y<15 || _x>11 || _x<7) return 0;
            if(dx!=2 || dy!=2) return 0;
            return 1;
        }
    }else if(name=="帅" || name=="将"){
        int dx=abs(x-_x),dy=abs(y-_y);
        if(name=="帅"){
            if(_y>5 || _x>11 || _x<7) return 0;
            if(dx==2 && !dy || dy==2 && !dx) return 1;
            return 0;
        } 
        if(name=="将"){
            if(_y<15 || _x>11 || _x<7) return 0;
            if(dx==2 && !dy || dy==2 && !dx) return 1;
            return 0;
        }
    }
}
bool ftf(){
    int pos_x=0,pos_y=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(chess[i][j].name=="将"){
                pos_x=i;
                pos_y=j;
                break;
            }
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(chess[i][j].name=="帅"){
                if(j==pos_y){
                    if(checkline(j,i,pos_x)==0){
                        return 1;
                    }
                }
            }
        }
    }
    return 0;
}
int ckjiangjun(){//判断将军 1車 2炮 3马 4 兵卒 

    int lst=turn^1;
    int pos_x=0,pos_y=0;//将的坐标 
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if((turn==1&&chess[i][j].name=="帅")||(turn==0&&chess[i][j].name=="将")){
                pos_x=i;
                pos_y=j;
                break;
            }
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if((chess[i][j].name=="俥"&&turn==0)||(chess[i][j].name=="車"&&turn==1)){
                if(i==pos_x){
                    int cnt=0;
                    for(int k=min(j,pos_y)+1;k<max(j,pos_y);k++){
                        if(chess[i][k].zy!=2){
                            cnt++;
                        }
                    }
                    if(cnt==0){
                        return 1;
                    }
                }
                else if(j==pos_y){
                    int cnt=0;
                    for(int k=min(i,pos_x)+1;k<max(i,pos_x);k++){
                        if(chess[k][j].zy!=2){
                            cnt++;
                        }
                    }
                    if(cnt==0){
                        return 1;
                    }
                }
            }
            else if((chess[i][j].name=="砲"&&turn==0)||(chess[i][j].name=="炮"&&turn==1)){
                if(i==pos_x){
                    int cnt=0;
                    for(int k=min(j,pos_y)+1;k<max(j,pos_y);k++){
                        if(chess[i][k].zy!=2){
                            cnt++;
                        }
                    }
                    if(cnt==1){
                        return 2;
                    }
                }
                else if(j==pos_y){
                    int cnt=0;
                    for(int k=min(i,pos_x)+1;k<max(i,pos_x);k++){
                        if(chess[k][j].zy!=2){
                            cnt++;
                        }
                    }
                    if(cnt==1){
                        return 2;
                    }
                }
            }
            else if((chess[i][j].name=="馬"&&turn==0)||(chess[i][j].name=="马"&&turn==1)){
                if(i+2==pos_x&&j+4==pos_y&&chess[i][j+2].zy==2){
                    return 3;
                }
                else if(i+2==pos_x&&j-4==pos_y&&chess[i][j-2].zy==2){
                    return 3;
                }
                else if(i-2==pos_x&&j+4==pos_y&&chess[i][j+2].zy==2){
                    return 3;
                }
                else if(i-2==pos_x&&j-4==pos_y&&chess[i][j-2].zy==2){
                    return 3;
                }
                else if(i+4==pos_x&&j+2==pos_y&&chess[i+2][j].zy==2){
                    return 3; 
                }
                else if(i+4==pos_x&&j-2==pos_y&&chess[i+2][j].zy==2){
                    return 3;
                }
                else if(i-4==pos_x&&j+2==pos_y&&chess[i-2][j].zy==2){
                    return 3;
                }
                else if(i-4==pos_x&&j-2==pos_y&&chess[i-2][j].zy==2){
                    return 3;
                }
            }
            else if(chess[i][j].name=="兵"&&turn==0){
                if(i>=11){//过河兵 
                    if(i==pos_x&&j-2==pos_y){
                        return 4;
                    }
                    else if(abs(i-pos_x)+abs(j-pos_y)==2){
                        return 4;
                    }
                }
            }
            else if(chess[i][j].name=="卒"&&turn==1){
                if(i<=10){//过河卒 
                    if(i==pos_x&&j+2==pos_y){
                        return 4;
                    }
                    else if(abs(i-pos_x)+abs(j-pos_y)==2){
                        return 4;
                    }
                }
            }
        }
    }
    return 0;
}
void print(int x,int y){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(i==x&&j==y) color(8);
            else if(chess[i][j].zy==0) color(12);
            else if(chess[i][j].zy==1) color(10);
            else color(15);
            cout<<chess[i][j].name;
            if(i==x&&j==y){
                chess[i][j].name="  ";
            }
            color(15);
        }
        printf("\n");
    }
}
bool ckover(){
    bool f=1;
    turn^=1;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            Chess c=chess[i][j];
            if(c.zy!=turn || c.zy==2) continue;
            for(int _x=1; _x<=n; _x++){
                for(int _y=1; _y<=m; _y++){
                    if(_x%2==0 || _y%2==0) continue;
                    Chess pre=chess[_x][_y];
                    if(!can_move(c.name,i,j,_x,_y)) continue;
                    swap(chess[i][j],chess[_x][_y]);
                    clear(i,j);
                    turn^=1;
                    if(!ckjiangjun()&&!ftf()){
                        f=0;
                    }
                    turn^=1;
                    swap(chess[i][j],chess[_x][_y]);
                    chess[_x][_y]=pre;
                    if(!f) {
                        turn^=1;
                        return f;
                    }
                }
            }       
        }
    turn^=1;
    return 1;
}
bool peace(){
    if(step<=60) return 0;
    if(eatc<=8) return 0;
    pair<int,int> int4399=hashh(1),wch666=hashh(0);
    int atkr=int4399.first,atkb=int4399.second,prtr=wch666.first,prtb=wch666.second;
    if(!(abs(atkr-atkb)<=20 &&  abs(prtr-prtb)<=20)) return 0;
    return 1;
} 
int main(){
    init();
    print(0,0);
    string red_black[2]={"红","黑"}; 
    while(1){
        cout<<"\n\n轮到"<<red_black[turn]<<"方移动\n";
        int x1,y1,x2,y2,xx1,yy1,xx2,yy2;
        POINT p;
        do{
            while(!down);
            p=downpos();
            y1=yy1=p.x,x1=xx1=p.y;
            yy1/=2,xx1++;
            yy1++; 
        }
        while(xx1>n||yy1>m||chess[xx1][yy1].zy!=turn);
        if(y1-1-(y1&1)>0){
            gotoxy(y1-1-(y1&1),x1);
            putchar('(');
        }
        gotoxy(y1+1+!(y1&1),x1);
        putchar(')');
        while(1){
            Sleep(300);
            cout<<endl;
            while(!down);
            p=downpos();
            y2=yy2=p.x,x2=xx2=p.y;
            yy2/=2,xx2++;
            yy2++;
            if(xx2>n||yy2>m||chess[xx2][yy2].name=="丨"||chess[xx2][yy2].name=="--") continue;
            if(chess[xx2][yy2].zy==turn){
                if(y1-1-(y1&1)>0){
                gotoxy(y1-1-(y1&1),x1);
                putchar('-');
                }
                gotoxy(y1+1+!(y1&1),x1);
                putchar('-');
                x1=x2,y1=y2,xx1=xx2,yy1=yy2;
                if(y1-1-(y1&1)>0){
                    gotoxy(y1-1-(y1&1),x1);
                    putchar('(');
                }
                gotoxy(y1+1+!(y1&1),x1);
                putchar(')');
            }
            if(can_move(chess[xx1][yy1].name,xx1,yy1,xx2,yy2)) break;
        }
        x1=xx1,y1=yy1,x2=xx2,y2=yy2;
        bool joker=0;
        bool ck=0;
        if(can_move(chess[x1][y1].name,x1,y1,x2,y2)){
            Chess tmp=chess[x2][y2];
            if(chess[x2][y2].zy<=1 && chess[x2][y2].zy!=chess[x1][y1].zy){
                chess[x2][y2]=(Chess){"  ",2};
                joker=1;
            }
            swap(chess[x1][y1],chess[x2][y2]);
            if(ftf()){
                system("cls");
                swap(chess[x1][y1],chess[x2][y2]);
                chess[x2][y2]=tmp;
                print(0,0);
                cout<<"\n\n移动不合法,请重新移动\n";
                continue;
            }
            turn^=1;
            if(ckjiangjun()){
                swap(chess[x1][y1],chess[x2][y2]);
                chess[x2][y2]=tmp;
                system("cls");
                print(0,0);
                cout<<"\n\n禁止送将,请重新移动\n";
                turn^=1;
                continue;
            }
            turn^=1;
            system("cls");
            chess[x1][y1].name=chess[x2][y2].name;
            chess[x1][y1].zy=2;
            print(x1,y1);
            if(ckover()){
                cout<<"\n\n      绝杀\n";
                break;
            }
            if(ckjiangjun()){ 

                cout<<"\n\n将军\n";
                ck=1;
            }
            else{
                turn^=1;
                if(ckjiangjun()){
                    ck=1;
                    eatc=0;
                    cout<<"\n\n将军\n";
                }
                turn^=1;

            }
            if(joker && !ck){
                eatc=0;
                cout<<"\n\n吃"; 
            }
        }else{
            system("cls");  
            print(0,0); 
            cout<<"\n\n移动不合法,请重新移动\n";
            continue;
        }
        int f1=0,f2=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(chess[i][j].name=="帅"){
                    f1=1;
                }
                if(chess[i][j].name=="将"){
                    f2=1;
                }
            }
        }
        if(!f1||!f2){
            break;
        }
        if(peace() && pec>=10){
            pec=0;
            cout<<"\n\n局势已进入僵局,是否和棋?双方均输入 1 则和棋\n\n";
            int pr,pb;
            cin>>pr>>pb;
            if(pr==1 && pb==1){
                cout<<"\n  和棋\n";
                return 0; 
            }
        }
        turn^=1;
        pec++;
        eatc++; 
        step++;
    }
    cout<<"\n"<<red_black[turn]<<"方获胜\n";
    return 0;
}