中国象棋 - 兴安科技改版

· · 个人记录

原作者:Originum

链接:https://blog.csdn.net/Originum/article/details/80356452

第一次改版:Shaw.W

链接:https://blog.csdn.net/weixin_44544583/article/details/89323014

第二次改版:兴安科技

链接:https://www.luogu.com.cn/blog/XAscience/Chinese-Chess

#include<iostream>
#include<fstream>
#include<windows.h>
#include<conio.h>
#include<stdio.h>
#include<time.h>
#include<sstream>
#include<cstring>
#include<cmath>
#include<iomanip>
#define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)
using namespace std;
int posx=0,posy=0,gm_start=0;
bool errorflag=0;
int lx[26]={0,0,0,1,0,2,0,3,0,4,0,5,0,0,0,6,0,7,0,8,0,9,0,10,0,11},ly[22]={0,0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8,0,9};
bool kd(char ccc){
    if(!KEY_DOWN(ccc)) return 0;
    else return 1;
}
void color(int a){
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),a);
}
void mouse_xy(){//鼠标定位函数
    posx=0;
    posy=0;
    while(!kd(VK_LBUTTON));
    POINT p;
    GetCursorPos(&p);
    ScreenToClient(GetConsoleWindow(), &p);
    posy=(p.x/16);
    posx=(p.y/16);
    while(kd(VK_LBUTTON));
}
class Chessboard;
class Chess
{
private:
    int Id;
public:
    Chess(int x) :Id(x) {}
    int Get()                //取ID
    {
        return Id;
    }
    virtual bool Judgement(Chessboard& ch, int startx, int starty, int endx, int endy) = 0;//判断走步合理性
    virtual ~Chess() {}
};
class Chessboard
{
private:
    Chess *c[10][11];        //棋盘:X为横(9),Y为纵(10),从1开始记
    char Chessword[15][4] = { "兵","炮","车","马","相","仕","帅"," ","将","士","象","馬","車","砲","卒" };
public:
    static int Player;       //上半区为1,下半区为-1
    static bool End;         //判断是否结束
    Chessboard();
    Chess *Get(int x, int y);//返回指定点的指针
    int Getid(int x, int y);//返回指定点处棋子ID的指针
    bool Move(int startx, int starty, int endx, int endy);  //移动
    void Init();               //初始化棋子
    void Show();               //打印
    void Play();               //开始游戏
    ~Chessboard();
};
class General :public Chess//将、帅类,ID为-1和1
{
public:
    General(int i) :Chess((i == 0 ? -1 : 1)) {}
    bool Judgement(Chessboard& ch, int startx, int starty, int endx, int endy)
    {
        int TempX = startx - endx;
        int TempY = starty - endy;
        int S_Id = ch.Getid(startx, starty);
        int E_Id = ch.Getid(endx, endy);
        if ((S_Id*E_Id <= 0) && (TempX*TempX + TempY * TempY == 1) && (endx >= 4 && endx <= 6) && (endy >= 1 && endy <= 3 || endy >= 8 && endy <= 10))
        {
            return true;
        }
        return false;
    }
    ~General()
    {
        Chessboard::End = false;
    }
};
class BodyGuard :public Chess//士、仕类,ID为-2和2
{
public:
    BodyGuard(int i) :Chess((i == 0 ? -2 : 2)) {}
    bool Judgement(Chessboard& ch, int startx, int starty, int endx, int endy)
    {
        int TempX = startx - endx;
        int TempY = starty - endy;
        int S_Id = ch.Getid(startx, starty);
        int E_Id = ch.Getid(endx, endy);
        if ((S_Id*E_Id <= 0) && (TempX*TempX + TempY * TempY == 2) && (endx >= 4 && endx <= 6) && (endy >= 1 && endy <= 3 || endy >= 8 && endy <= 10))
        {
            return true;
        }
        return false;
    }
};
class Chancellor :public Chess//象、相类,ID为-3和3
{
public:
    Chancellor(int i) :Chess((i == 0 ? -3 : 3)) {}
    bool Judgement(Chessboard& ch, int startx, int starty, int endx, int endy)
    {
        int TempX = startx - endx;
        int TempY = starty - endy;
        int S_Id = ch.Getid(startx, starty);
        int E_Id = ch.Getid(endx, endy);
        if ((S_Id*E_Id <= 0) && (TempX*TempX + TempY * TempY == 8) && (endx % 2 != 0 && endx >= 1 && endy <= 9) && ((starty - 1) / 5 == (endy - 1) / 5) && !ch.Get(startx + (TempX / 2), starty + (TempY / 2)))
        {
            return true;
        }
        return false;
    }
};
class Horse :public Chess//馬、马类,ID为-4和4
{
public:
    Horse(int i) :Chess((i == 0 ? -4 : 4)) {}
    bool Judgement(Chessboard& ch, int startx, int starty, int endx, int endy)
    {
        int TempX = startx - endx;
        int TempY = starty - endy;
        int S_Id = ch.Getid(startx, starty);
        int E_Id = ch.Getid(endx, endy);
        if ((S_Id*E_Id <= 0) && (TempX*TempX + TempY * TempY == 5) && !ch.Get(startx + (TempX / 2), starty + (TempY / 2)))
        {
            return true;
        }
        return false;
    }
};
class Chariot :public Chess//車、车类,ID为-5和5
{
public:
    Chariot(int i) :Chess((i == 0 ? -5 : 5)) {}
    bool Judgement(Chessboard& ch, int startx, int starty, int endx, int endy)
    {
        int TempX = startx - endx;
        int TempY = starty - endy;
        int S_Id = ch.Getid(startx, starty);
        int E_Id = ch.Getid(endx, endy);
        if ((S_Id*E_Id <= 0) && (!(TempX&&TempY)) && (TempX + TempY))
        {
            if (TempX)
            {
                int Sign = (TempX > 0 ? -1 : 1);
                for (int i = 1; i < fabs(TempX); i++)
                {
                    if (ch.Get(startx + Sign * i, starty))
                    {
                        return false;
                    }
                }
            }
            else
            {
                int Sign = (TempY > 0 ? -1 : 1);
                for (int i = 1; i < fabs(TempY); i++)
                {
                    if (ch.Get(startx, starty + Sign * i))
                    {
                        return false;
                    }
                }
            }
            return true;
        }
        return false;
    }
};
class Cannon :public Chess//砲、炮类,ID为-6和6
{
public:
    Cannon(int i) :Chess((i == 0 ? -6 : 6)) {}
    bool Judgement(Chessboard& ch, int startx, int starty, int endx, int endy)
    {
        int TempX = startx - endx;
        int TempY = starty - endy;
        int S_Id = ch.Getid(startx, starty);
        int E_Id = ch.Getid(endx, endy);
        if ((S_Id*E_Id <= 0) && (!(TempX&&TempY)) && (TempX + TempY))
        {
            int Tmp = 0;
            if (TempX)
            {
                int Sign = (TempX > 0 ? -1 : 1);
                for (int i = 1; i < fabs(TempX); i++)
                {
                    if (ch.Get(startx + Sign * i, starty))
                    {
                        Tmp++;
                    }
                }
            }
            else
            {
                int Sign = (TempY > 0 ? -1 : 1);
                for (int i = 1; i < fabs(TempY); i++)
                {
                    if (ch.Get(startx, starty + Sign * i))
                    {
                        Tmp++;
                    }
                }
            }
            if (E_Id)
            {
                if (Tmp == 1)
                {
                    return true;
                }
            }
            else
            {
                if (!Tmp)
                {
                    return true;
                }
            }
        }
        return false;
    }
};
class Soldier :public Chess//卒、兵类,ID为-7和7
{
public:
    Soldier(int i) :Chess((i == 0 ? -7 : 7)) {}
    bool Judgement(Chessboard& ch, int startx, int starty, int endx, int endy)
    {
        int TempX = startx - endx;
        int TempY = starty - endy;
        int S_Id = ch.Getid(startx, starty);
        int E_Id = ch.Getid(endx, endy);
        if ((S_Id*E_Id <= 0) && (S_Id*TempY <= 0))
        {
            if (fabs(TempY) == 1 && TempX == 0)
            {
                return true;
            }
            if (fabs(TempX) == 1 && TempY == 0)
            {
                if (((starty - 1) / 5 == 0 && S_Id < 0) || ((starty - 1) / 5 == 1 && S_Id > 0))
                {
                    return true;
                }
            }
        }
        return false;
    }
};
int Chessboard::Player = -1;
bool Chessboard::End = true;
inline Chessboard::Chessboard()
{
    memset(c, NULL, sizeof(c));
}
inline Chess * Chessboard::Get(int x, int y)
{
    return c[x][y];
}
int Chessboard::Getid(int x, int y)
{
    if (c[x][y] != NULL)
    {
        return c[x][y]->Get();
    }
    return NULL;
}
bool Chessboard::Move(int startx, int starty, int endx, int endy)
{
    if (startx >= 1 && startx <= 9 && starty >= 1 && starty <= 10 && endx >= 1 && endx <= 9 && endy >= 1 && endy <= 10 && Getid(startx, starty) && Getid(startx, starty)*Player > 0 && c[startx][starty]->Judgement(*this, startx, starty, endx, endy))
    {
        if (c[endx][endy] != NULL)
        {
            delete c[endx][endy];           //吃子
        }
        c[endx][endy] = c[startx][starty];
        c[startx][starty] = NULL;
        Player *= -1;                       //更换玩家操作
        return true;
    }
    else
    {
        errorflag=1;
        return false;
    }
}
void Chessboard::Init()
{
    c[1][1] = new Chariot(1);
    c[9][1] = new Chariot(1);
    c[2][1] = new Horse(1);
    c[8][1] = new Horse(1);
    c[3][1] = new Chancellor(1);
    c[7][1] = new Chancellor(1);
    c[4][1] = new BodyGuard(1);
    c[6][1] = new BodyGuard(1);
    c[5][1] = new General(1);
    c[2][3] = new Cannon(1);
    c[8][3] = new Cannon(1);
    c[1][4] = new Soldier(1);
    c[3][4] = new Soldier(1);
    c[5][4] = new Soldier(1);
    c[7][4] = new Soldier(1);
    c[9][4] = new Soldier(1);
    c[1][10] = new Chariot(0);
    c[9][10] = new Chariot(0);
    c[2][10] = new Horse(0);
    c[8][10] = new Horse(0);
    c[3][10] = new Chancellor(0);
    c[7][10] = new Chancellor(0);
    c[4][10] = new BodyGuard(0);
    c[6][10] = new BodyGuard(0);
    c[5][10] = new General(0);
    c[2][8] = new Cannon(0);
    c[8][8] = new Cannon(0);
    c[1][7] = new Soldier(0);
    c[3][7] = new Soldier(0);
    c[5][7] = new Soldier(0);
    c[7][7] = new Soldier(0);
    c[9][7] = new Soldier(0);
}
void Chessboard::Show()
{
    system("cls");
    cout << endl;
    HANDLE handle;
    handle = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(handle, 0xF0);
    cout << "    P2  一  二  三  四  五  六  七  八  九" << endl << endl;
    char num[11][4] = { "零","一","二","三","四","五","六","七","八","九" ,"十" };
    for (int i = 1; i < 11; i++)
    {
        if (i == 6)
        {
            SetConsoleTextAttribute(handle, 0xF0);
            cout << "         — — — —楚河  汉界— — — —" << endl << endl;
        }
        SetConsoleTextAttribute(handle, 0xF0);
        cout << "    " << num[i] << "  ";
        for (int j = 1; j < 10; j++)
        {
            if (c[j][i] != NULL)
            {
                if (c[j][i]->Get() > 0)
                {
                    //SetConsoleTextAttribute(handle, 0xF2);
                    color(47);
                    cout << Chessword[c[j][i]->Get() + 7];
                    color(240);
                    cout<<"  ";
                }
                else
                {
                    //SetConsoleTextAttribute(handle, 0xFC);
                    color(207);
                    cout << Chessword[c[j][i]->Get() + 7];
                    color(240);
                    cout<<"  ";
                }
            }
            else if ((i == 2 && j == 5) || (i == 9 && j == 5))
            {
                SetConsoleTextAttribute(handle, 0xF0);
                cout << "米" << "  ";
            }
            else
            {
                SetConsoleTextAttribute(handle, 0xF0);
                cout << "十" << "  ";
            }
        }
        cout << endl << endl;
    }
    SetConsoleTextAttribute(handle, 0xF0);
    cout << "    P1  一  二  三  四  五  六  七  八  九" << endl << endl;
}
void nofastedit() { //关闭快速编辑
    HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
    DWORD mode;
    GetConsoleMode(hStdin, &mode);
    mode &= ~ENABLE_QUICK_EDIT_MODE;
    mode &= ~ENABLE_INSERT_MODE;
    mode &= ~ENABLE_MOUSE_INPUT;
    SetConsoleMode(hStdin, mode);
}
void Chessboard::Play()
{
    HANDLE handle;
    handle = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(handle, 0xFC);
    this->Init();
    do
    {
        int startx, starty, aimx, aimy, iflag;
        int sid, aid;
        iflag = 0;
        do
        {
            system("cls");
            this->Show();
            if(gm_start>=1){
                sid = aid = 0;
                if ((Chessboard::Player == 1 ? 2 : 1) == 1)
                {
                    SetConsoleTextAttribute(handle, 0xFC);
                }
                else
                {
                    SetConsoleTextAttribute(handle, 0xF2);
                }
                cout << "[消息]  P" << (Chessboard::Player == 1 ? 2 : 1) << "走棋" << endl;
                if(errorflag && gm_start>2){
                    errorflag=0;
                    cout<<"[消息]  走法错误,请重新走棋。"<<endl;
                }else{
                    cout<<"[消息]  请选择您要走的旗"<<endl;
                    gm_start++;
                }
                mouse_xy(); 
                startx=ly[posy];
                starty=lx[posx];
                cout<<"[消息]  请选择棋的落点。"<<endl;
                mouse_xy();
                aimx=ly[posy];
                aimy=lx[posx];  
            }else{
                SetConsoleTextAttribute(handle, 0xF0);
                cout<<"[信息] 原作者:Originum"<<endl;
                cout<<"[信息] 第一次改版:Shaw.W"<<endl;
                cout<<"[信息] 第二次改版:兴安科技"<<endl;
                SetConsoleTextAttribute(handle, 0xFC);
                system("pause");
                gm_start=1;
            }
        } while (!this->Move(startx, starty, aimx, aimy));
        system("cls");
        this->Show();
        for (int i = 4; i < 7; i++)
        {
            for (int j = 1; j < 11; j++)
            {
                if (c[i][j] != NULL)
                {
                    if ((int)fabs(c[i][j]->Get()) == 1)
                    {
                        iflag++;
                    }
                    else if (iflag != 0 && iflag != 2)
                    {
                        if ((int)fabs(c[i][j]->Get()) != 1)
                        {
                            iflag--;
                        }
                    }
                }
            }
        }
        if (iflag == 2)
        {
            Player *= -1;
            Chessboard::End = false;
        }
    } while (Chessboard::End);
    if ((Chessboard::Player == 1 ? 1 : 2) == 1)
    {
        SetConsoleTextAttribute(handle, 0xFC);
    }
    else
    {
        SetConsoleTextAttribute(handle, 0xF2);
    }
    cout << "结束,赢家是Player" << (Chessboard::Player == 1 ? 1 : 2) << endl;
}
Chessboard::~Chessboard()
{
    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 11; j++)
        {
            if (c[i][j] != NULL)
            {
                delete c[i][j];
                c[i][j] = NULL;
            }
        }
    }
}
using namespace std;
int main()
{
    system("mode con:cols=60 lines=33");
    nofastedit();
    Chessboard C;
    C.Play();

    system("pause");
}