Qt--中国象棋

利用Qt制作中国象棋小游戏
先给出效果图:

1.首先是总的文件(其中chessmovelaw文件是自定义文件,res是资源文件-包括背景,棋子的图片等)
在这里插入图片描述
2.widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

enum ChessType  //棋子
{
    NullChess,
    Ju_R,
    Ma_R,
    Xiang_R,
    Shi_R,
    Jiang_R,
    Pao_R,
    Bing_R,
    Ju_B,
    Ma_B,
    Xiang_B,
    Shi_B,
    Jiang_B,
    Pao_B,
    Bing_B
};

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

    void paintEvent(QPaintEvent * e);
    //鼠标按下事件
    void mousePressEvent(QMouseEvent * event);
    //被选中棋子,能否从选中位置移动到当前位置
    bool CanMove(int tarRow,int tarCol);

    bool IsRedChess(ChessType chessType);

    void IsDead();

    void timerEvent(QTimerEvent *event);
    int eventID1;

    int d=60;

    void InitChess();
    void DrawChess(QPainter*p,int row,int col,ChessType type);
private:
    Ui::Widget *ui;

    QPoint stPos,edPos;
    int W,H;
    ChessType chessType[10][9];
    int pressRow,pressCol;
    //turn=0为红,turn=1为黑
    bool turn;
};
#endif // WIDGET_H

3.棋子文件chessmovelaw.h
声明棋子走法

#ifndef CHESSMOVELAW_H
#define CHESSMOVELAW_H
#include "widget.h"

//棋子移动规则文件
class ChessMoveLaw
{
public:    
    static bool ChessCanMove(ChessType chessType[10][9],int sourceRow,int sourceCol,int destRow,int destCol);

protected:
    static bool MaLaw(ChessType chessType[10][9],int sourceRow,int sourceCol,int destRow,int destCol);
    static bool XiangLaw(ChessType chessType[10][9],int sourceRow,int sourceCol,int destRow,int destCol);
    static bool ShiLaw(ChessType chessType[10][9],int sourceRow,int sourceCol,int destRow,int destCol);
    static bool JiangLaw(ChessType chessType[10][9],int sourceRow,int sourceCol,int destRow,int destCol);
    static bool JuLaw(ChessType chessType[10][9],int sourceRow,int sourceCol,int destRow,int destCol);
    static bool PaoLaw(ChessType chessType[10][9],int sourceRow,int sourceCol,int destRow,int destCol);
    static bool BingLaw(ChessType chessType[10][9],int sourceRow,int sourceCol,int destRow,int destCol);

    static bool IsSameColor(ChessType chessType[10][9],int sourceRow,int sourceCol,int destRow,int destCol);

    static bool IsRedChess(ChessType chessType);
};

#endif // CHESSMOVELAW_H

4.有关棋子的函数实现chessmovelaw.cpp
实现各类棋子对应走法规则-不知道走法要先了解象棋规则

#include "chessmovelaw.h"
#include <cmath>
#include <QDebug>

bool ChessMoveLaw::ChessCanMove(ChessType chessType[10][9],int sourceRow,int sourceCol,int destRow,int destCol)
{
    //如果目标棋子不为空且颜色相同
    if(chessType[destRow][destCol]!=NullChess && IsSameColor( chessType, sourceRow, sourceCol, destRow, destCol))
        return false;

    //马-规则
    if(chessType[sourceRow][sourceCol]==Ma_R || chessType[sourceRow][sourceCol]==Ma_B)
    {
        return MaLaw( chessType, sourceRow, sourceCol, destRow, destCol);
    }
    //象-规则
    if(chessType[sourceRow][sourceCol]==Xiang_R || chessType[sourceRow][sourceCol]==Xiang_B)
    {
        return XiangLaw( chessType, sourceRow, sourceCol, destRow, destCol);
    }
    //士-规则
    if(chessType[sourceRow][sourceCol]==Shi_R || chessType[sourceRow][sourceCol]==Shi_B)
    {
        return ShiLaw( chessType, sourceRow, sourceCol, destRow, destCol);
    }
    //将-规则
    if(chessType[sourceRow][sourceCol]==Jiang_R || chessType[sourceRow][sourceCol]==Jiang_B)
    {
        return JiangLaw( chessType, sourceRow, sourceCol, destRow, destCol);
    }
    //车-规则
    if(chessType[sourceRow][sourceCol]==Ju_R || chessType[sourceRow][sourceCol]==Ju_B)
    {
        return JuLaw( chessType, sourceRow, sourceCol, destRow, destCol);
    }
    //炮-规则
    if(chessType[sourceRow][sourceCol]==Pao_R || chessType[sourceRow][sourceCol]==Pao_B)
    {
        return PaoLaw( chessType, sourceRow, sourceCol, destRow, destCol);
    }
    //兵-规则
    if(chessType[sourceRow][sourceCol]==Bing_R || chessType[sourceRow][sourceCol]==Bing_B)
    {
        return BingLaw( chessType, sourceRow, sourceCol, destRow, destCol);
    }
    return true;
}

bool ChessMoveLaw::IsRedChess(ChessType chessType)
{
    if(chessType==Ju_R || chessType==Ma_R || chessType==Xiang_R || chessType==Shi_R  || chessType==Pao_R || chessType==Jiang_R || chessType==Bing_R )
        return true;
    else
        return false;
}
bool ChessMoveLaw::IsSameColor(ChessType chessType[10][9],int sourceRow,int sourceCol,int destRow,int destCol)
{
    if(chessType[destRow][destCol]==NullChess)
        return false;
    return IsRedChess(chessType[sourceRow][sourceCol])==IsRedChess(chessType[destRow][destCol]);
}

//马的走法
bool ChessMoveLaw::MaLaw(ChessType chessType[10][9],int sourceRow,int sourceCol,int destRow,int destCol)
{
    if(abs(sourceRow-destRow)==1)
    {
        if(abs(sourceCol-destCol)!=2)
            return false;
        else if(chessType[sourceRow][(sourceCol+destCol)/2]!=NullChess)
            return false;
        else
            return true;
    }
    else if(abs(sourceRow-destRow)==2)
    {
        if(abs(sourceCol-destCol)!=1)
            return false;
        else if(chessType[(sourceRow+destRow)/2][sourceCol]!=NullChess)
            return false;
        else
            return true;
    }
    else
    {
        return false;
    }
}

//象的走法
bool ChessMoveLaw::XiangLaw(ChessType chessType[10][9],int sourceRow,int sourceCol,int destRow,int destCol)
{
    //是否过河了
    if(IsRedChess(chessType[sourceRow][sourceCol]))
    {
        if(sourceRow<=4 && destRow<=4)
        {
            if(abs(sourceRow-destRow)==2)
            {
                if(abs(sourceCol-destCol)!=2)
                    return false;
                else
                {
                    if(chessType[(sourceRow+destRow)/2][(sourceCol+destCol)/2]==NullChess)
                        return true;
                    else
                        return false;
                }
            }
            else
            {
                return false;
            }
        }
    }
    else
    {
        if(sourceRow>=5 && destRow>=5)
        {
            if(abs(sourceRow-destRow)==2)
            {
                if(abs(sourceCol-destCol)!=2)
                    return false;
                else
                {
                    if(chessType[(sourceRow+destRow)/2][(sourceCol+destCol)/2]==NullChess)
                        return true;
                    else
                        return false;
                }
            }
            else
            {
                return false;
            }
        }
    }
}

//士的走法
bool ChessMoveLaw::ShiLaw(ChessType chessType[10][9],int sourceRow,int sourceCol,int destRow,int destCol)
{
    //是否在田字格内
    if(IsRedChess(chessType[sourceRow][sourceCol]))
    {
        if(sourceRow>=0 &&sourceRow<=2 && sourceCol>=3 && sourceCol<=5 && destRow>=0 && destRow<=2 && destCol>=3 && destCol<=5 )
        {
            //斜线走
            if(abs(sourceRow-destRow)==1 && abs(sourceCol-destCol)==1)
                return true;
            else
                return false;
        }
        return false;
    }
    else
    {
        if(sourceRow>=7 &&sourceRow<=9 && sourceCol>=3 && sourceCol<=5 && destRow>=7 && destRow<=9 && destCol>=3 && destCol<=5 )
        {
            if(abs(sourceRow-destRow)==1 && abs(sourceCol-destCol)==1)
                return true;
            else
                return false;
        }
        return false;
    }
}

//将的走法
bool ChessMoveLaw::JiangLaw(ChessType chessType[10][9],int sourceRow,int sourceCol,int destRow,int destCol)
{
     //是否在田字格内
     if(IsRedChess(chessType[sourceRow][sourceCol]))
     {
         if(sourceRow>=0 &&sourceRow<=2 && sourceCol>=3 && sourceCol<=5 && destRow>=0 && destRow<=2 && destCol>=3 && destCol<=5 )
         {
             //上下左右走
             if(((abs(sourceRow-destRow)==1 && abs(sourceCol-destCol)==0))||((abs(sourceRow-destRow)==0 && abs(sourceCol-destCol)==1)))
                 return true;
             else
                 return false;
         }
         return false;
     }
     else
     {
         if(sourceRow>=7 &&sourceRow<=9 && sourceCol>=3 && sourceCol<=5 && destRow>=7 && destRow<=9 && destCol>=3 && destCol<=5 )
         {
             if(((abs(sourceRow-destRow)==1 && abs(sourceCol-destCol)==0))||((abs(sourceRow-destRow)==0 && abs(sourceCol-destCol)==1)))
                 return true;
             else
                 return false;
         }
         return false;
     }

     if(chessType[sourceRow][sourceCol]==Jiang_R)
     {
         int r,c;
         int m=0;
         for(int i=0;i<10;i++)
             for(int j=0;j<9;j++)
             {
                 if(chessType[i][j] == Jiang_B)
                 {
                     r=i;
                     c=j;
                 }
             }
         if(destCol==c)
         {
             for(int a=destRow;a<r;a++)
             {
                 if(chessType[a][c] != NullChess)
                 {
                     m++;
                 }
             }
             if(m==0)
                 qDebug()<<"黑棋获胜!";
         }
     }
     else if(chessType[sourceRow][sourceCol]==Jiang_B)
     {
         int r,c;
         int m=0;
         for(int i=0;i<10;i++)
             for(int j=0;j<9;j++)
             {
                 if(chessType[i][j] == Jiang_R)
                 {
                     r=i;
                     c=j;
                 }
             }
         if(destCol==c)
         {
             for(int a=r;a<destRow;a++)
             {
                 if(chessType[a][c] != NullChess)
                 {
                     m++;
                 }
             }
             if(m==0)
                 qDebug()<<"红棋获胜!";
         }
     }


}

//车的走法
bool ChessMoveLaw::JuLaw(ChessType chessType[10][9],int sourceRow,int sourceCol,int destRow,int destCol)
{
    int m=0;
    if(sourceRow==destRow)
    {
        if(sourceCol<destCol)
        {
            for(int i=sourceCol+1;i<destCol;i++)
                if(chessType[sourceRow][i]!=NullChess)
                    m++;
            if(m==0)
                return true;
            else
                return false;
        }
        if(sourceCol>destCol)
        {
            for(int i=destCol+1;i<sourceCol;i++)
                if(chessType[sourceRow][i]!=NullChess)
                    m++;
            if(m==0)
                return true;
            else
                return false;
        }
    }
    if(sourceCol==destCol)
    {
        if(sourceRow<destRow)
        {
            for(int i=sourceRow+1;i<destRow;i++)
                if(chessType[i][sourceCol]!=NullChess)
                    m++;
            if(m==0)
                return true;
            else
                return false;
        }
        if(sourceRow>destRow)
        {
            for(int i=destRow+1;i<sourceRow;i++)
                if(chessType[i][sourceCol]!=NullChess)
                    m++;
            if(m==0)
                return true;
            else
                return false;
        }
    }
}

//炮的走法
bool ChessMoveLaw::PaoLaw(ChessType chessType[10][9],int sourceRow,int sourceCol,int destRow,int destCol)
{
    int m=0;
    if(sourceRow==destRow)
    {
        if(sourceCol<destCol)
        {
            //是否隔山打牛
            for(int i=sourceCol+1;i<destCol-1;i++)
                if(chessType[sourceRow][i]!=NullChess)
                    m++;

            if(m==0 && chessType[destRow][destCol]==NullChess)
                return true;
            else if(m==1 && chessType[destRow][destCol]!=NullChess && chessType[destRow][destCol-1]!=NullChess)
            {
                if(IsRedChess(chessType[sourceRow][sourceCol])!=IsRedChess(chessType[destRow][destCol]))
                    return true;
                return false;
            }
            else
                return false;
        }
        if(sourceCol>destCol)
        {
            for(int i=destCol+1;i<sourceCol;i++)
                if(chessType[sourceRow][i]!=NullChess)
                    m++;
            if(m==0 && chessType[destRow][destCol]==NullChess)
                return true;
            else if(m==1 && chessType[destRow][destCol]!=NullChess && chessType[destRow][destCol+1]!=NullChess)
            {
                if(IsRedChess(chessType[sourceRow][sourceCol])!=IsRedChess(chessType[destRow][destCol]))
                    return true;
                return false;
            }
            else
                return false;
        }
    }
    if(sourceCol==destCol)
    {
        if(sourceRow<destRow)
        {
            for(int i=sourceRow+1;i<destRow;i++)
                if(chessType[i][sourceCol]!=NullChess)
                    m++;
            if(m==0 && chessType[destRow][destCol]==NullChess)
                return true;
            else if(m==1 && chessType[destRow][destCol]!=NullChess && chessType[destRow-1][destCol]!=NullChess)
            {
                if(IsRedChess(chessType[sourceRow][sourceCol])!=IsRedChess(chessType[destRow][destCol]))
                    return true;
                return false;
            }
            else
                return false;
        }
        if(sourceRow>destRow)
        {
            for(int i=destRow+1;i<sourceRow;i++)
                if(chessType[i][sourceCol]!=NullChess)
                    m++;
            if(m==0 && chessType[destRow][destCol]==NullChess)
                return true;
            else if(m==1 && chessType[destRow][destCol]!=NullChess && chessType[destRow+1][destCol]!=NullChess)
            {
                if(IsRedChess(chessType[sourceRow][sourceCol])!=IsRedChess(chessType[destRow][destCol]))
                    return true;
                return false;
            }
            else
                return false;
        }
    }
}

//兵的走法
bool ChessMoveLaw::BingLaw(ChessType chessType[10][9],int sourceRow,int sourceCol,int destRow,int destCol)
{
    //是否过河了
    if(IsRedChess(chessType[sourceRow][sourceCol]))
    {
        //没有过河
        if(sourceRow<=4)
        {
            if(destRow-sourceRow==1 && sourceCol==destCol)
                return true;
            else
                return false;
        }
        //过河了
        else
        {
            if(destRow-sourceRow==1)
                return true;
            else if(sourceRow==destRow)
            {
                if(abs(sourceCol-destCol)==1)
                    return true;
                else
                    return false;
            }
            else
                return false;
        }
    }
    else
    {
        if(sourceRow>=5)
        {
            if(sourceRow-destRow==1 && sourceCol==destCol)
                return true;
            else
                return false;
        }
        else
        {
            if(sourceRow-destRow==1)
                return true;
            else if(sourceRow==destRow)
            {
                if(abs(sourceCol-destCol)==1)
                    return true;
                else
                    return false;
            }
            else
                return false;
        }
    }
}

5.widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QRect>
#include <QDebug>
#include <QPushButton>
#include <QPoint>
#include <QMouseEvent>
#include <QFont>
#include <QDialog>
#include "chessmovelaw.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    stPos=QPoint(73,42);
    edPos=QPoint(630,663);
    W = (edPos.x()-stPos.x())/8;
    H = (edPos.y()-stPos.y())/9;



    InitChess();
    //未选中棋子
    pressRow=-1;
    pressCol=-1;
    turn=false;

    //定时器
    eventID1=startTimer(1000);   //可自定义切换快慢
}

Widget::~Widget()
{
    delete ui;
}

void Widget::timerEvent(QTimerEvent *event)
{
    //设置字体大小
    QFont font;
    font.setPointSize(20);
    ui->label->setFont(font);
    //设置定时器-倒计时
    if(event->timerId()==eventID1)
    {
    d--;
    ui->label->move(700,20);
    ui->label->resize(200,60);
    QString aa="倒计时";
    QString bb=QString::number(d);
    ui->label->setText(aa+bb);
    }

}
void Widget::paintEvent(QPaintEvent * e)
{
    QPainter painter(this);
    QRect rect = this->rect();
    rect.setWidth(rect.width()-100);

    painter.drawPixmap(rect,QPixmap(":/res/background.png"));

    if(pressRow>=0 && pressCol>=0)
    {
        QRect r(stPos.x()+pressCol*W-0.5*W,stPos.y()+pressRow*H-0.5*H,W,H);
        painter.drawPixmap(r,QPixmap(":/res/selected.png"));
    }
    for(int i=0;i<10;i++)
        for(int j=0;j<9;j++)
        {
            if(chessType[i][j] != NullChess)
                DrawChess(&painter,i,j,chessType[i][j]);
        }
}

void Widget::mousePressEvent(QMouseEvent * event)
{
    event->pos();
    if(event->button()==Qt::LeftButton)
    {
        int row=(event->y()-stPos.y()+0.5*H)/H;
        int col=(event->x()-stPos.x()+0.5*W)/W;
        //选中到行和列在棋盘内的时候
        if(row>=0 && row<=9 && col>=0 && col<=8)
        {
            //之前选中到棋子为空
            if(pressRow>=0 && pressCol>=0)
            {
                //如果满足象棋移动规则,移动棋子
                if(CanMove(row,col))
                {
                    d=61;
                    chessType[row][col]=chessType[pressRow][pressCol];
                    chessType[pressRow][pressCol]=NullChess;
                    pressRow=-1;
                    pressCol=-1;
                    turn=!turn;
                    IsDead();
                    repaint();
                    return;
                }
            }
            //当前选中棋子为空
            if(chessType[row][col]!=NullChess)
            {
                //如果是红棋走且选中的是红棋,或如果是黑棋走且选中的是黑棋,把棋子选中
                if((turn==false &&IsRedChess(chessType[row][col]))||(turn==true && !IsRedChess(chessType[row][col])))
                {
                    pressRow=row;
                    pressCol=col;
                }
                repaint();
            }
        }
    }
}



void Widget::InitChess()
{
    for(int i=0;i<10;i++)
        for(int j=0;j<9;j++)
        {
            chessType[i][j]=NullChess;
        }

    chessType[0][0]=Ju_R;
    chessType[0][1]=Ma_R;
    chessType[0][2]=Xiang_R;
    chessType[0][3]=Shi_R;
    chessType[0][4]=Jiang_R;

    chessType[9][0]=Ju_B;
    chessType[9][1]=Ma_B;
    chessType[9][2]=Xiang_B;
    chessType[9][3]=Shi_B;
    chessType[9][4]=Jiang_B;

    for(int i=0;i<4;i++)
    {
        chessType[0][8-i]=chessType[0][i];
        chessType[9][8-i]=chessType[9][i];
    }

    chessType[2][1]=Pao_R;
    chessType[2][7]=Pao_R;
    chessType[7][1]=Pao_B;
    chessType[7][7]=Pao_B;

    chessType[3][0]=Bing_R;
    chessType[3][2]=Bing_R;
    chessType[3][4]=Bing_R;
    chessType[3][6]=Bing_R;
    chessType[3][8]=Bing_R;

    chessType[6][0]=Bing_B;
    chessType[6][2]=Bing_B;
    chessType[6][4]=Bing_B;
    chessType[6][6]=Bing_B;
    chessType[6][8]=Bing_B;
}

void Widget::DrawChess(QPainter*p,int row,int col,ChessType type)
{
    QPixmap pix;

    switch (type)
    {
    case Ju_R:
        pix=QPixmap(":/res/rr.png");
        break;
    case Ma_R:
        pix=QPixmap(":/res/rn.png");
        break;
    case Xiang_R:
        pix=QPixmap(":/res/rb.png");
        break;
    case Shi_R:
        pix=QPixmap(":/res/ra.png");
        break;
    case Jiang_R:
        pix=QPixmap(":/res/rk.png");
        break;
    case Pao_R:
        pix=QPixmap(":/res/rc.png");
        break;
    case Bing_R:
        pix=QPixmap(":/res/rp.png");
        break;
    case Ju_B:
        pix=QPixmap(":/res/br.png");
        break;
    case Ma_B:
        pix=QPixmap(":/res/bn.png");
        break;
    case Xiang_B:
        pix=QPixmap(":/res/bb.png");
        break;
    case Shi_B:
        pix=QPixmap(":/res/ba.png");
        break;
    case Jiang_B:
        pix=QPixmap(":/res/bk.png");
        break;
    case Pao_B:
        pix=QPixmap(":/res/bc.png");
        break;
    case Bing_B:
        pix=QPixmap(":/res/bp.png");
        break;
    default:
        break;
    }

    QRect r(stPos.x()+col*W-0.5*W,stPos.y()+row*H-0.5*H,W,H);

    p->drawPixmap(r,pix);
}

bool Widget::CanMove(int tarRow,int tarCol)
{
 if(pressRow>=0 && pressCol>=0)
 {
     return ChessMoveLaw::ChessCanMove(chessType,pressRow,pressCol,tarRow,tarCol);
 }
 return false;
}

bool Widget::IsRedChess(ChessType chessType)
{
    if(chessType==Ju_R || chessType==Ma_R || chessType==Xiang_R || chessType==Shi_R  || chessType==Pao_R || chessType==Jiang_R || chessType==Bing_R )
        return true;
    else
        return false;
}

void Widget::IsDead()
{
    int red=0;
    int black=0;
    for(int i=0;i<10;i++)
    {
        for(int j=0;j<9;j++)
        {
            if(chessType[i][j]==Jiang_R)
                red++;
            else if(chessType[i][j]==Jiang_B)
                black++;
        }
    }
    if(red==0)
    {
        QFont font;
        font.setPointSize(20);
        ui->label_2->setFont(font);
        ui->label_2->resize(200,60);
        QString w="黑方获胜!!";
        ui->label_2->move(700,80);
        ui->label_2->setText(w);
    }
    else if(black==0)
    {
        QFont font;
        font.setPointSize(20);
        ui->label_2->setFont(font);
        ui->label_2->resize(200,60);
        QString w="红方获胜!!";
        ui->label_2->move(700,80);
        ui->label_2->setText(w);
    }
    else
        return;
}

6.ui界面
在这里插入图片描述
如果有更好写法,请自行改进。

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值