C++中国象棋

ssdut c++的大作业,在控制台的界面实现人人对弈,比较适合初学,自己设计了一些简单算法,两百多行完成。

以下正文:

完成中国象棋游戏,实现如下功能:

1.实现人与人之间象棋的对弈。

2.每次走子之前都会判断是否符合规则,若不符合规则就要重新走子。

3.程序随时判断是否有一方取得胜利,该局结束。

类的设计:

1.chess:棋子类,有int型私有变量id存储棋子的编号。作为基类派生出其他具体的棋子类。有判断棋子走法是否符合规则的judge_move()纯虚函数。

代码:

class chess{
private:
    int id;//等级
public:
    chess(int i):id(i){}
    int get(){return id;}
    virtual bool judge_move(chessboard &cb,int startx,int starty,int aimx,int aimy)=0;
    virtual ~chess(){};//虚析构
};

2.具体的棋子类:包括soldier类、horse类、rook类、guard类、cannon类、elephant类、general类分别代表兵(卒)、馬(马)、車(车)、士(仕)、炮(砲)、相(象)、帅(将)的类,由chess类作为基类派生。每个派生类都对judge_move()函数进行重写。

以马为例:

class horse : public chess{//马的实现
public:
    horse(int i) : chess((i==0?-2:2)){}
    bool judge_move(chessboard &cb,int startx,int starty,int aimx,int aimy){
        int tempx=aimx-startx,tempy=aimy-starty;
        int sid=cb.getid(startx, starty),aid=cb.getid(aimx, aimy);
        if(sid*aid<=0&&(tempx*tempx+tempy*tempy==5)&&!cb.get(startx+tempx/2,starty+tempy/2))
        return true;
        return false;
    }
};

3.chessboard类:棋盘类,私有成员包括10*9的指向chess的指针数组用以存储各个棋子对象的地址,并通过指针调用实现多态。

代码:

class chessboard{
private:
    chess *c[10][9];//用指针调用各个棋子,实现多态
    char chessword[15][4]={"帅","相","炮","士","車","馬","兵","","卒","马","车","仕","砲","象","将"};//名字
public:
    chessboard(){memset(c, NULL, sizeof(c));};//把指针初始化为零指针
    void init();
    chess* get(int x,int y){return c[x][y];}
    int getid(int x,int y){ if(c[x][y]!=NULL) return c[x][y]->get();return 0;}
    void show();
    void play();
    bool move(int startx,int starty,int aimx,int aimy);
    ~chessboard();//析构函数
    static bool end;//判断结束
    static int player;
};

算法描述:

红方棋子中文分别为"兵","馬","車","士","炮","相","帅"。

id的编号分别为-1、-2、-3、-4、-5、-6、-7。

黑方棋子:中文分别为"卒","马","车","仕","砲","象","将"。

id的编号分别为1、2、3、4、5、6、7。

(由于只显示一个汉子表示棋子,所以用“砲”作为红方的炮)

维护的变量:

startx starty: 开始的位置 ;  aimx  aimy:目标的位置

sid:存储开始位置的棋子的编号,若该点没有棋子(空指针),则值为0。

aid:存储目标位置的棋子的编号,若该点没有棋子(空指针),则值为0。

tempx:开始位置到目标位置的x坐标的偏移量(aimx-startx)。

 

tempy:开始位置到目标位置的y坐标的偏移量(aimy-starty)。

 

 

走棋的实现:

 

每次把位置信息传到chessboard类的move()函数时,会判断:

1.传入的两个位置是否越界(超出了10*9数组的范围),越界则返回false

2.传入的开始位置的点的id是否为零(当点上无棋子,也就是空指针的时候为零),若为零则返回false。

3.当前选的棋子是否是这一回对应那一方的棋子,若不是则返回false

4.对当前棋子的具体规则进行判断(通过指针调用虚函数,判断该棋子的具体规则,多态的实现)。若错误则返回false

若以上判断都准确无误,则把棋子走到对应位置:

1.不吃子:目标位置为空指针时,把目标位置的指针指向该棋子对象,把棋子的起始位置指针赋值NULL,设为空指针。

2. 吃子:delete目标位置的棋子对象,该棋子被吃。把目标位置的指针指向该棋子对象,把棋子的起始位置指针赋值NULL,设为空指针。

判断结束:

 

棋盘类有一个静态变量bool end, 初始化为true。当将(帅)对象被析构时,把end赋值为false,表示棋局结束,退出走棋的循环(while(chessboard :: end)控制走棋是否继续)。

输出胜利的一方的信息:

棋盘类有一个静态变量int player,初始化为-1,每走棋一次乘以-1,在1-1之间交替表示棋手的轮流下棋。以此来鉴别胜利的是哪一方。

 

棋子具体的规则算法:

1.判断目标点是否是己方的棋:两方的子的id互为相反数,所以只有当sid*aid>0时表示目标位置是己方的子,不能走。因而只有满足sid*aid<=0才是合法条件(空位置为0)。

2.判断是否满足只能走1格,或马走日,象走田的条件时,只需要区偏移的距离进行判断。例如temp*temp+tempy+tempy表示偏移量的平方,当该值为1时,表示只走了任意方向的一格;当值为2时,表示士的斜走;值为5时,表示马走日;为8时,表示象走田。

3.判断马走日的蹩脚马时,用数学计算方法,可以归纳出只需判断(x+tempx/2,y+tempy/2)位置是否有子便可。而判断塞象时,只用判段(x+tempx/2,y+tempy/2)的位置是否有子即可。

4.判断将(帅)和士是否在3*3的营里:明显,y坐标肯定要满足y>=3&&y<=5,而x坐标只需对7取模,就可以把0-27-9约束在0-2里,判断即可:aimx%7>=0&&aimx%7<=2。

其他一些规则如兵不能回头(sid*tempx<=0),过河后可以横走,炮只能隔子吃子,已经在代码实现,不详述。

输出如下:

 

1.棋盘的构建,输入的界面:

 

2.按规则正确输入后的界面:

3.不按规则,错误输入的界面:

4.某一方将(帅)被吃,结束的界面:

附上完整代码:

#include <iostream>
#include <memory.h>
#include <math.h>
using namespace std;//存储结构:chess类是基类,派生类是各种棋子,在chessboard类中用chess的指针调用各个棋子
class chessboard;
class chess{
private:
    int id;//等级
public:
    chess(int i):id(i){}
    int get(){return id;}
    virtual bool judge_move(chessboard &cb,int startx,int starty,int aimx,int aimy)=0;
    virtual ~chess(){};//虚析构
};

class chessboard{
private:
    chess *c[10][9];//用指针调用各个棋子,实现多态
    char chessword[15][4]={"帅","相","炮","士","車","馬","兵","","卒","马","车","仕","砲","象","将"};//名字
public:
    chessboard(){memset(c, NULL, sizeof(c));};//把指针初始化为零指针
    void init();
    chess* get(int x,int y){return c[x][y];}
    int getid(int x,int y){ if(c[x][y]!=NULL) return c[x][y]->get();return 0;}
    void show();
    void play();
    bool move(int startx,int starty,int aimx,int aimy);
    ~chessboard();//析构函数
    static bool end;//判断结束
    static int player;
};

bool chessboard::end=true;
int chessboard::player=-1;

bool chessboard::move(int startx,int starty,int aimx,int aimy){
    if(startx>=0&&startx<10&&starty>=0&&starty<9//初步判断传入的点是否符合规则
       &&aimx>=0&&aimx<10&&aimy>=0&&aimy<9
       &&getid(startx,starty)&&getid(startx,starty)*player>0
       &&c[startx][starty]->judge_move(*this,startx,starty,aimx,aimy)){
        if(c[aimx][aimy]!=NULL) delete c[aimx][aimy];//吃子
        c[aimx][aimy]=c[startx][starty];
        c[startx][starty]=NULL;
    player*=-1;
    return true;
    }
    cout<<"走法错误,不符合规则"<<endl;
    return false;
}

class horse : public chess{//马的实现
public:
    horse(int i) : chess((i==0?-2:2)){}
    bool judge_move(chessboard &cb,int startx,int starty,int aimx,int aimy){
        int tempx=aimx-startx,tempy=aimy-starty;
        int sid=cb.getid(startx, starty),aid=cb.getid(aimx, aimy);
        if(sid*aid<=0&&(tempx*tempx+tempy*tempy==5)&&!cb.get(startx+tempx/2,starty+tempy/2))
        return true;
        return false;
    }
};

class soldier : public chess{//兵(卒)的实现
public:
    soldier(int c) : chess((c==0?-1:1)){}
    bool judge_move(chessboard &cb,int startx,int starty,int aimx,int aimy){
        int tempx=aimx-startx,tempy=aimy-starty;
        int sid=cb.getid(startx, starty),aid=cb.getid(aimx, aimy);
        if(sid*aid<=0&&sid*tempx<=0){
            if(abs(tempx)==1&&tempy==0) return true;
            if(abs(tempy)==1&&tempx==0)
                if((startx/5==0&&sid>0)||(startx/5==1&&sid<0)) return true;
            return false;
        }
        return false;
    }
};

class general : public chess{//帅(将)的实现
public:
    general(int c) : chess((c==0?-7:7)){}
    bool judge_move(chessboard &cb,int startx,int starty,int aimx,int aimy){
        int tempx=aimx-startx,tempy=aimy-starty;
        int sid=cb.getid(startx, starty),aid=cb.getid(aimx, aimy);
        if(sid*aid<=0&&tempy*tempy+tempx*tempx==1&&aimx%7>=0&&aimx%7<=2&&aimy>=3&&aimy<=5)
            return true;
        return false;
    }
    ~general(){chessboard::end=false;}
};

class elephant : public chess{//象(相)的实现
public:
    elephant(int c) : chess((c==0?-6:6)){}
    bool judge_move(chessboard &cb,int startx,int starty,int aimx,int aimy){
        int tempx=aimx-startx,tempy=aimy-starty;
        int sid=cb.getid(startx, starty),aid=cb.getid(aimx, aimy);
        if(sid*aid<=0&&tempy*tempy+tempx*tempx==8&&startx/5==aimx/5&&!cb.get(startx+tempx/2,starty+tempy/2))
            return true;
        return false;
    }
};

class cannon : public chess{//炮的实现
public:
    cannon(int c) : chess((c==0?-5:5)){}
    bool judge_move(chessboard &cb,int startx,int starty,int aimx,int aimy){
        int tempx=aimx-startx,tempy=aimy-starty;
        int sid=cb.getid(startx, starty),aid=cb.getid(aimx, aimy);
        if(sid*aid<=0&&!(tempx&&tempy)&&(tempx+tempy)){
            int tot=0;
            if(tempx!=0){
                int sign=tempx>0?1:-1;
                for(int i=1;i<abs(tempx);i++)
                    if(cb.get(startx+sign*i,starty)) tot++;
            }
            else{
                int sign=tempy>0?1:-1;
                for(int i=1;i<abs(tempy);i++)
                    if(cb.get(startx,starty+sign*i)) tot++;
            }
            if(!aid)
            {if(!tot) return true;}
            else
            {if(tot==1) return true;}
        }
        return false;
    }
};

class guard: public chess{//士(仕)的实现
public:
    guard(int c) : chess((c==0?-4:4)){}
    bool judge_move(chessboard &cb,int startx,int starty,int aimx,int aimy){
        int tempx=aimx-startx,tempy=aimy-starty;
        int sid=cb.getid(startx, starty),aid=cb.getid(aimx, aimy);
        if(sid*aid<=0&&tempy*tempy+tempx*tempx==2&&aimx%7>=0&&aimx%7<=2&&aimy>=3&&aimy<=5)
            return true;
        return false;
    }
};

class rook : public chess{//车的实现
public:
    rook(int c) : chess((c==0?-3:3)){}
    bool judge_move(chessboard &cb,int startx,int starty,int aimx,int aimy){
        int tempx=aimx-startx,tempy=aimy-starty;
        int sid=cb.getid(startx, starty),aid=cb.getid(aimx, aimy);
        if(sid*aid<=0&&!(tempx&&tempy)&&(tempx+tempy)){
            if(tempx!=0){
                int sign=tempx>0?1:-1;
                for(int i=1;i<abs(tempx);i++)
                    if(cb.get(startx+sign*i,starty)) return false;
            }
            else{
                int sign=tempy>0?1:-1;
                for(int i=1;i<abs(tempy);i++)
                    if(cb.get(startx,starty+sign*i)) return false;
            }
                return true;
        }
        return false;
    }
};

chessboard :: ~chessboard(){
    for(int i=0;i<10;i++)
        for(int j=0;j<9;j++)
            if(c[i][j]!=NULL){
                delete c[i][j];
                c[i][j]=NULL;
            }
}

void chessboard :: init(){//初始化,棋子的生成
    c[0][0]=new rook(0);        c[0][8]=new rook(0);
    c[0][1]=new horse(0);       c[0][7]=new horse(0);
    c[0][2]=new elephant(0);    c[0][6]=new elephant(0);
    c[0][3]=new guard(0);       c[0][5]=new guard(0);
    c[0][4]=new general(0);     c[9][4]=new general(1);
    c[2][1]=new cannon(0);      c[2][7]=new cannon(0);
    c[3][0]=new soldier(0);     c[3][2]=new soldier(0);
    c[3][4]=new soldier(0);     c[3][6]=new soldier(0);
    c[3][8]=new soldier(0);     c[6][8]=new soldier(1);
    c[6][0]=new soldier(1);     c[6][2]=new soldier(1);
    c[6][4]=new soldier(1);     c[6][6]=new soldier(1);
    c[7][1]=new cannon(1);      c[7][7]=new cannon(1);
    c[9][0]=new rook(1);        c[9][8]=new rook(1);
    c[9][1]=new horse(1);       c[9][7]=new horse(1);
    c[9][2]=new elephant(1);    c[9][6]=new elephant(1);
    c[9][3]=new guard(1);       c[9][5]=new guard(1);
}

void chessboard :: show(){
    cout<<"吴  零一二三四五六七八"<<endl<<endl;
    char num[10][4]={"零","一","二","三","四","五","六","七","八","九"};
    for(int i=0;i<10;i++){
        if(i==5) cout<<"    ——楚 河 汉 界———"<<endl;
        cout<<num[i]<<"  ";
        for(int j=0;j<9;j++){
            if(c[i][j]!=NULL)
            cout<<chessword[c[i][j]->get()+7];
            else if((i==1&&j==4)||(i==8&&j==4))
                cout<<"米";
            else
                cout<<"十";
        }
        cout<<endl;
    }
}

void chessboard::play(){
    this->init();
    this->show();
    do{
       int startx,starty,aimx,aimy;
        int sid,aid;
        do{
            sid=aid=0;
            cout<<"请输入起始棋子位置与目标位置的坐标:"<<endl;
            cin>>startx>>starty>>aimx>>aimy;
        }while(!this->move(startx,starty,aimx,aimy));
        this->show();
    }while(chessboard::end);
    cout<<"结束,赢家是Player"<<(chessboard::player==1?1:2)<<endl;
}

int main(){
    chessboard C;
    C.play();
}

 

  • 42
    点赞
  • 186
    收藏
    觉得还不错? 一键收藏
  • 23
    评论
好的,以下是一个简单的 C++ 代码示例,实现了中国象棋人机对战的基本功能: ```c++ #include <iostream> #include <vector> using namespace std; // 棋子结构体 struct ChessPiece { string name; // 名称 string color; // 颜色 int x, y; // 位置 }; // 棋盘类 class ChessBoard { public: ChessBoard() { // 初始化棋盘 for (int i = 0; i < 10; i++) { for (int j = 0; j < 9; j++) { board[i][j] = ' '; } } } // 显示棋盘 void display() { for (int i = 0; i < 10; i++) { for (int j = 0; j < 9; j++) { cout << board[i][j] << " "; } cout << endl; } } // 初始化棋子 void initPieces() { // 红方 pieces.push_back({"车", "红", 0, 0}); pieces.push_back({"马", "红", 0, 1}); pieces.push_back({"象", "红", 0, 2}); pieces.push_back({"士", "红", 0, 3}); pieces.push_back({"将", "红", 0, 4}); pieces.push_back({"士", "红", 0, 5}); pieces.push_back({"象", "红", 0, 6}); pieces.push_back({"马", "红", 0, 7}); pieces.push_back({"车", "红", 0, 8}); pieces.push_back({"炮", "红", 2, 1}); pieces.push_back({"炮", "红", 2, 7}); pieces.push_back({"兵", "红", 3, 0}); pieces.push_back({"兵", "红", 3, 2}); pieces.push_back({"兵", "红", 3, 4}); pieces.push_back({"兵", "红", 3, 6}); pieces.push_back({"兵", "红", 3, 8}); // 黑方 pieces.push_back({"车", "黑", 9, 0}); pieces.push_back({"马", "黑", 9, 1}); pieces.push_back({"象", "黑", 9, 2}); pieces.push_back({"士", "黑", 9, 3}); pieces.push_back({"将", "黑", 9, 4}); pieces.push_back({"士", "黑", 9, 5}); pieces.push_back({"象", "黑", 9, 6}); pieces.push_back({"马", "黑", 9, 7}); pieces.push_back({"车", "黑", 9, 8}); pieces.push_back({"炮", "黑", 7, 1}); pieces.push_back({"炮", "黑", 7, 7}); pieces.push_back({"兵", "黑", 6, 0}); pieces.push_back({"兵", "黑", 6, 2}); pieces.push_back({"兵", "黑", 6, 4}); pieces.push_back({"兵", "黑", 6, 6}); pieces.push_back({"兵", "黑", 6, 8}); // 将棋子放置到棋盘上 for (int i = 0; i < pieces.size(); i++) { int x = pieces[i].x; int y = pieces[i].y; board[x][y] = pieces[i].name[0]; } } // 获取指定位置的棋子 ChessPiece getPiece(int x, int y) { for (int i = 0; i < pieces.size(); i++) { if (pieces[i].x == x && pieces[i].y == y) { return pieces[i]; } } return {"", "", -1, -1}; } // 移动棋子 void movePiece(int x1, int y1, int x2, int y2) { ChessPiece piece = getPiece(x1, y1); board[x1][y1] = ' '; board[x2][y2] = piece.name[0]; for (int i = 0; i < pieces.size(); i++) { if (pieces[i].x == x1 && pieces[i].y == y1) { pieces[i].x = x2; pieces[i].y = y2; } } } // 判断是否可以移动 bool canMove(int x1, int y1, int x2, int y2) { ChessPiece p1 = getPiece(x1, y1); ChessPiece p2 = getPiece(x2, y2); if (p1.color == p2.color) { return false; // 同色棋子不可互相吃 } // 判断棋子的走法是否合法 // 略... return true; } private: char board[10][9]; // 棋盘 vector<ChessPiece> pieces; // 棋子 }; int main() { ChessBoard chessBoard; chessBoard.initPieces(); chessBoard.display(); chessBoard.movePiece(3, 0, 4, 0); chessBoard.display(); return 0; } ``` 这段代码使用了 C++面向对象思想,定义了棋盘类 ChessBoard 和棋子结构体 ChessPiece,对棋盘的初始化、棋子的移动、棋盘的显示等操作进行了封装。其,initPieces() 函数初始化了棋子的位置,movePiece() 函数移动棋子,canMove() 函数判断棋子是否可以移动。在主函数,先初始化棋盘和棋子,然后显示棋盘,移动了一个兵,再次显示棋盘。
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值