前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Qt中国象棋四——显示棋子可移动位置/项目完成

Qt中国象棋四——显示棋子可移动位置/项目完成

作者头像
用户5908113
发布2019-11-18 21:34:23
7910
发布2019-11-18 21:34:23
举报
文章被收录于专栏:Pou光明Pou光明

1.棋子“马”算法简要分析

棋子“马”的计算可移动区域算法简介:

1,求出8个待选位置,8个位置的偏移是(-2,-1)(-2,1)(2,-1)(2,1)

(1,-2)(1,2)(-1,-2)(-1,2)存在关系:|x|+|y|=3

2,判断待选位置是否在棋盘内

3,判断中间是否有卡位的棋子

4,位置上是否已存在同色棋子

算法实现过程如下,注释比较详细:

代码语言:javascript
复制
Item newItem;
    for (int i = -2; i<=2; i++)    {        for(int j = -2; j<=2; j++)        {            if (qAbs(i) + qAbs(j) == 3)            {                QPoint newPoint = item.m_pt + QPoint(i,j);                //当该点在棋盘内,可继续搜索                if (newPoint.x() >= 0 && newPoint.x() <= 8                   && newPoint.y()>=0 && newPoint.y() <= 9)                {                    ;                }                else                {                    continue;                }
                //求该方向行走路线的 卡位元素位置                //相对当前点4个卡位位置计算                QPoint ptDirect(0,0);                if (qAbs(i) > qAbs(j))                {                    if (i>0)                    {                        ptDirect = QPoint(1,0);                    }                    else                    {                        ptDirect = QPoint(-1,0);                    }                }                else                {                    if (j>0)                    {                        ptDirect = QPoint(0,1);                    }                    else                    {                        ptDirect = QPoint(0,-1);                    }                }
                //在棋盘中马的卡位元素位置                QPoint ptHit = item.m_pt + ptDirect;
                //目标点卡位位置有棋子                if (findItemAtLogicPoint(ptHit,newItem))                {                    //卡位                    continue;                }
                //目标点卡位位置无棋子,但是目标点是同色棋子                if (findItemAtLogicPoint(newPoint ,newItem) &&                           item.m_color == newItem.m_color)                {                    //有本组item                    continue;                }                moveableArea.append(newPoint);            }        }    }

2. 绘制棋子可移动位置

要绘制出棋子可移动位置其实就是将之前moveableArea中的QPoint标记出来。

QVector<QPoint> moveableArea; //获取已选择棋子的可移动区域getMoveableArea(m_selectedItem,moveableArea);

绘制棋子可移动位置与绘制棋子类似,可参考Qt 中国象棋第二节的绘制棋子部分,文末附有链接。

代码语言:javascript
复制
void MainWindow::drawMoveableArea(QPainter &painter, const QVector<QPoint> moveableArea){    for(int i = 0; i < moveableArea.size(); i++)    {        QRect rcTarget( START_X + moveableArea[i].x()*55.5,                        START_Y + moveableArea[i].y()*56,                        53,50);
        painter.drawPixmap(rcTarget,m_moveableAreaImage);    }}

效果如下:

3. 其他逻辑调整

鼠标事件这里是整个业务的核心;添加定时器事件,用于将选中的棋子进行提示。

代码语言:javascript
复制
//鼠标点击,走棋、吃棋等逻辑void MainWindow::mousePressEvent(QMouseEvent *e){
    //获得鼠标点击位置所对应的棋子    QPoint pt;    pt.setX( (e->pos().x() - START_X ) / RECT_WIDTH);    pt.setY( (e->pos().y() - START_Y ) / RECT_HEIGHT);
    //是否有选中的棋子    if(m_bExistSelectedItem)    {        //再次点击已经选择的棋子,什么也不做        if (pt == m_selectedItem.m_pt)        {            return;        }
        //点击其它棋子        Item clickedItem;        if (findItemAtLogicPoint(pt,clickedItem))        {                        //点击的同色的另外一个棋子,改选            if ( (m_bIsRedTurn && clickedItem.m_color == COLOR_RED) ||                 (!m_bIsRedTurn && clickedItem.m_color != COLOR_RED))            {                //改选棋子后,清除原有的落子提示                m_moveableArea.clear();                update();
                setItemShow(m_selectedItem, true);                m_selectedItem = clickedItem;
    //获取已选择棋子的可移动区域                getMoveableArea(m_selectedItem,m_moveableArea);                   update();                return;            }        }
        //绘制落子提示        getMoveableArea(m_selectedItem,m_moveableArea);    //获取已选择棋子的可移动区域        update();

        //点击的异色棋子,判断是否能走能吃        QVector<QPoint> moveableArea;        getMoveableArea(m_selectedItem,moveableArea);    //获取已选择棋子的可移动区域
        if(moveableArea.contains(pt))        {            //包含当前鼠标点中的棋子,则能吃            bool bDeleteSHUAI = false;            deleteItemAtLogicPoint(pt,bDeleteSHUAI);      //吃掉            changeItemLogicPoint(m_selectedItem.m_pt,pt); //绘制新的棋子位置            m_moveableArea.clear();                       //清除落子提示//            update();                                     //发送重新绘图事件
            if(bDeleteSHUAI)            {                QString str = m_bIsRedTurn?QStringLiteral("红方胜利!"):QStringLiteral("黑方胜利!");                QMessageBox::information(NULL,  "GAME OVER  ",str, QMessageBox::Yes , QMessageBox::Yes);                newGame();                return ;            }
            m_bExistSelectedItem = false;            m_bIsRedTurn = !m_bIsRedTurn;            update();            return ;
        }    }    else  //当前没有选中棋子    {        Item clickedItem;        if(findItemAtLogicPoint(pt,clickedItem))  //知道了我是谁、我在哪        {            if( (m_bIsRedTurn && clickedItem.m_color == COLOR_RED) ||               (!m_bIsRedTurn && clickedItem.m_color == COLOR_BLACK))            {                m_selectedItem = clickedItem;                m_bExistSelectedItem = true;
                getMoveableArea(m_selectedItem,m_moveableArea);    //获取已选择棋子的可移动区域                update();                return;            }        }
    }}
void MainWindow::timerEvent(QTimerEvent *){    for (int i = 0; i<m_items.size(); i++)    {        if (m_items[i].m_pt == m_selectedItem.m_pt)        {            m_items[i].m_bShow = !m_items[i].m_bShow;        }    }}

后记总结:

这一个小项目在参考源码的情况下陆陆续续写了近两周,有些惭愧啊。

个人技能的增长需要不断去学习新的知识并将学到的东西不断提炼和总结,最后变成自己的东西才算是真正的学会,不然就像【知道了那么多道理却依然过不好这一生一样!】

之前项目文章回顾:

1. Qt中国象棋一—— Qt 2D 绘图入门

2. Qt中国象棋二——棋盘与棋子的绘制

3. Qt中国象棋三——让你的車和炮动起来

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Pou光明 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档