Qt实现中国象棋:(五)棋子移动测试

一、鼠标信息获取

1:从前面的内容可以看出要想实现棋子的移动,实际就是进行图片的重新绘制。图片QPixmap已经与枚举中的变量形成了一一映射的关系。整个widget窗口被chessmap进行了均等分,chessmap[i][j]的值可以表示一张图片,其下标表示widget被分割后第i行第j列的一块小区域,该区域就是用来放置chessmap[i][j]所表示的图片。就是说通过对chessmap中的特定元素的重新赋值就可实现棋子的移动。鼠标第一次点击要移动的棋子,第二次点击目的位置。通过两次获取鼠标点击位置坐标来得到与之对应的chessmap下标。(这里的分析请结合前文)
2:根据需求选择使用mousePressEvent来获取鼠标信息(使用该函数需添加头文件“QMouseEvent“)。

int X,Y;//鼠标点击位置对应的下标(定义在.h文件中)
//鼠标点击(按压)事件
void myWidget::mousePressEvent(QMouseEvent *event)
{
    QPoint point=event->pos();
    int w=this->width()/col;//列对应x轴
    int h=this->height()/row;//行对应y轴
    X=point.x()/w;
    Y=point.y()/h;
    qDebug()<<QString("移动坐标:")<<"("<<Y<<","<<X<<")";
}

3:为了便于观察以及测试,可将第一次点击和第二次点击鼠标获得的信息显示在label和label_2中。需要定义一个变量来辨别是第几次点击鼠标,这里定义了一个int类型变量,用bool类型也是可行的。

int mou = 0;//鼠标点击次数判定(初始值为0,第一次点击后mou值为1,第二次点击后值又变为0)

为实现上面需求,需要自定义信号和槽函数。信号的发出者是widget,信号的接收者是label和label_2。因此信号在mywidget.h中定义,槽函数在widget.h中定义。
在这里插入图片描述

//信号在mywidget.h中定义
signals:
    void clicked(int x,int y,int mou);//自定义点击信号,在mousePressEvent事件发生时触发
//槽函数在widget.h中定义 
private slots:
   void  on_mouseClicked(int x,int y,int mou);   

修改后的mousePressEvent函数

//鼠标点击(按压)事件
void myWidget::mousePressEvent(QMouseEvent *event)
{
    QPoint point=event->pos();
    int w=this->width()/col;
    int h=this->height()/row;
    X=point.x()/w;//x轴对应的下标
    Y=point.y()/h;//y轴所对应的下标
    emit clicked(X,Y,mou);//发出信号
    if(mou==0)
    {
        qDebug()<<QString("初始坐标:")<<"("<<Y<<","<<X<<")";
        mou=1;//第一次点击完成
    }
    else
    {
        qDebug()<<QString("目的坐标:")<<"("<<Y<<","<<X<<")";
        mou=0;//第二次点击完成
    }
}

4:信号与槽函数的连接,连接的connect函数写在Widget的构造函数当中。

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);
    connect(ui->widget,&myWidget::clicked,this,&Widget::on_mouseClicked);
}

槽函数的内容

void Widget::on_mouseClicked(int x,int y,int mou)
{
    if(mou==0)
        ui->label->setText(QString("from坐标Y:%1,坐标X:%2").arg(y).arg(x));
    else
        ui->label_2->setText(QString("to坐标Y:%1,坐标X:%2").arg(y).arg(x));
}

5:鼠标信息获取完成后的显示效果
在这里插入图片描述

二、图片的移动

1:完成以上的操作后以及所要移动图片以及目的位置在chessmap中的下标。移动图片有一个必须保证的需求,即棋子移动后必须补上该位置的棋盘图片。所以需要将(三)棋盘绘制的详细分析及实现中棋盘绘制完成后的chessmap数组所有值复制下来。在mywidget.h中定义一个int类型数组chessboardValue[line][row]来保存各个位置表示的棋盘值。在mapInit()函数最后加上以下代码就可以完成棋盘图片值的保存

    //保存各棋盘图片在数组中对应的值
    for(int i=0;i<row;i++)
    {
        for(int j=0;j<col;j++)
        {
            chessboardValue[i][j]=chessmap[i][j];
        }
    }

2:在第一次点击时必须要求点击的是棋子图片(不然移动的就是棋盘图片),才可进行第二次点击且要求第二次点击位置与第一次不一致(后面进行添加棋子点击效果图后会有具体体现)。在dataDefne.h的枚举中可以看到表示棋子图片的值都大于30,同时需要一个数组来记录下当前的棋局状态。注:重绘过程中一定要先将整个棋盘先绘制下来再进行棋子的绘制,否则就会出现下图所示的情况。
在这里插入图片描述

所以不能只是简单的将chessmap的值交换后就用update函数(该函数就是再一次执行paintEvent函数)进行重绘操作。需要一个int类型数组curChess[line][row]来记录当前的棋局状态。

void saveQiJu();//在mywidget.h中定义

//保存当前棋局状态
void myWidget::saveQiJu()
{
    for(int i=0;i<row;i++)
    {
        foidgetr(int j=0;j<col;j++)
        {
            curChess[i][j]=chessmap[i][j];
        }
    }
}

从之前说明的棋子棋盘的绘制顺序知道上面的函数在开局后的每一次重绘棋盘图片对chessmap赋棋盘值前使用,用在mapInit函数中,因此在mapInit函数最前面加上以下代码。

 //刷新之前保存当前棋局
    if(gameBegin)
         saveQiJu();

在mapInit函数的最后加上以下代码来记录下chessmap中各个位置的棋盘值。

    //保存各棋盘图片在数组中对应的值
    for(int j=0;j<row;j++)
    {
        for(int i=0;i<col;i++)
            chessboardVaule[i][j]=chessmap[i][j];
    }

3:完成后的mousePressEvent函数

//鼠标点击(按压)事件
void myWidget::mousePressEvent(QMouseEvent *event)
{
    QPoint point=event->pos();
    int w=this->width()/row;
    int h=this->height()/line;
    X=point.x()/w;//x轴对应的下标
    Y=point.y()/h;//y轴所对应的下标
    emit clicked(X,Y,mou);//发出信号
    if(mou==0&&chessmap[Y][X]>30)
    {
        fromX=X;fromY=Y;//记下移动棋子初始位置下标
        qDebug()<<QString("初始坐标:")<<"("<<Y<<","<<X<<")";
        mou=1;//第一次点击完成
    }
    else if(mou==1)
    {
        if(fromY==X&&fromY==Y)
        {
            mou=0;//第二次点击完成,不做任何操作
        }
        else
        {
            chessmap[Y][X]=chessmap[fromY][fromX];//将目标位置的值改为被移动棋子的值
            chessmap[fromY][fromX]=chessboardVaule[fromY][fromX];//将棋子初始位置换位棋盘的值
            update();//重绘
            qDebug()<<QString("目的坐标:")<<"("<<Y<<","<<X<<")";
            mou=0;//第二次点击完成
        }
    }
}

4:完成后的paintEvent函数

void myWidget::paintEvent(QPaintEvent *event)
{   
    mapInit();//棋盘值
    QPainter painter(this);
    int h=this->height()/row;//单张图片的高度(对应y轴)
    int w=this->width()/col;//单张图片的宽度(对应x轴)
    drawChessboard(painter,w,h);//绘制棋盘
    if(!gameBegin)
    {//未开局的先初始化棋子在map中的对应值
        ChessPiecesInit();//棋子初始化
        gameBegin=true;//已开局
    }
    else
    {//已经开局的chessmap恢复为最近状态
        for(int i=0;i<row;i++)
        {
            for(int j=0;j<col;j++)
            {
                chessmap[i][j]=curChess[i][j];
            }
        }
    }
    drawChessPieces(painter,w,h);//绘制棋子
}

5:棋子移动效果
在这里插入图片描述
到这里棋子的简单移动功能就完成啦,后续再添加移动规则。欢迎各位留言谈论。

Qt实现中国象棋
(六)棋子移动规则

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zmq1998

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值