首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

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

为什么是車和炮呢?因为我比较喜欢車和炮直来直去的样子!

本节要介绍的就是整个象棋项目最为重点的地方了——会涉及一些棋子可走路径的搜索算法。以車为例,它的可走路径是四个方向上空位置和异色棋子位置,即单方向遇到的空位置则加入搜索点、遇到同色棋子或异色则停止搜索。

我们先想一下走棋的过程:先用鼠标选中一个棋子,之后再选一个要走的位置,当然,这个位置可能是空位置也可能是对方棋子的位置(吃子);或者是选中一个棋子后,不想走这个棋子,改选其他的棋子。上述的这些动作我们都在鼠标事件中完成。

流程分解:

1.获取鼠标所选棋子

在鼠标事件中,我们使用的功能是当有鼠标点击的事件时,我们获取被点击的位置(不论是左键还是右键)的像素坐标,通过该坐标算出被选中的棋子。

//获得鼠标点击位置所对应的棋子,也可能没有棋子    QPoint pt;    pt.setX( (e->pos().x() - START_X ) / RECT_WIDTH);    pt.setY( (e->pos().y() - START_Y ) / RECT_HEIGHT);

2.有被选中棋子的几种情况

①再次点击所选棋子,则什么也不做

②走到空位置(重新绘制棋子位置)

③选择其他棋子

1>点击同色棋子,则是改选棋子

2>点击异色棋子时,吃掉(重新绘制棋子位置)

这里我们先搜索出当前棋子的可走路径,然后再判断该异色棋子是否在可走路径之内,如果在,则可吃掉(当吃掉的是老将时,需再做处理);

结合程序说明上述过程:

//再次点击已经选择的棋子,什么也不做        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_selectedItem = clickedItem;                return;            }        }

    //点击的异色棋子,判断是否能走能吃QVector<QPoint> moveableArea;//获取已选择棋子的可移动区域getMoveableArea(m_selectedItem,moveableArea);
        if(moveableArea.contains(pt))        {            //包含当前鼠标点中的棋子,则能吃            bool bDeleteSHUAI = false;            deleteItemAtLogicPoint(pt,bDeleteSHUAI);      //吃掉//绘制新的棋子位置            changeItemLogicPoint(m_selectedItem.m_pt,pt);             update();                        //重新绘图生效        }

車的可走路径搜索实现

炮的搜索路径就不贴程序了~

void MainWindow::getMoveableAreaJU(Item item, QVector<QPoint> &moveableArea){    //棋子“车”的计算可移动区域算法简介:    //向4个方向上依次遍历点,把空点都加入。    //当碰到棋子时停止,如果是同色棋子,不加入;    //是异色棋子,则加入(该处认为可走,因为可以吃子)
    //左边    int x = item.m_pt.x() - 1;    while(x >= 0)    {        QPoint newPoint = QPoint(x,item.m_pt.y());        Item newItem;
        if(findItemAtLogicPoint(newPoint,newItem))        {            if(newItem.m_color != item.m_color)            {                moveableArea.append(newPoint);                break;            }        }
        moveableArea.append(newPoint);  //如果是空点,直接追加        x--;
    }
    //上边    int y = item.m_pt.y() - 1;    while(y >= 0)    {        QPoint newPoint = QPoint(item.m_pt.x(),y);        Item newItem;
        if(findItemAtLogicPoint(newPoint,newItem))        {            if(newItem.m_color != item.m_color)            {                moveableArea.append(newPoint);                break;            }        }
        moveableArea.append(newPoint);  //如果是空点,直接追加        y--;    }}

最后来几张效果图片:

棋子、棋盘效果图

車向上移动

炮的隔山打

后记总结:

虽然用到的鼠标事件是相对简单的,但是可以很好的理解事件的应用。Qt框架是以事件来驱动的,鼠标事件、绘图事件、键盘事件、窗体事件、语言改变事件等 等等。

下一篇
举报
领券