• Qt的简单应用:五子棋游戏( 含源码 )



    一、项目简介

    五子棋起源于中国,是全国智力运动会竞技项目之一,是一种两人对弈的纯策略型棋类游戏。双方分别使用黑白两色的棋子,下在棋盘直线与横线的交叉点上,先形成五子连珠者获胜。

    (1)对局双方各执一色棋子。
    (2)空棋盘开局。
    (3)黑先、白后,交替下子,每次只能下一子。
    (4)棋子下在棋盘的空白点上,棋子下定后不得移动或拿走。
    (5)黑方的第一枚棋子必须下在天元点上,即中心交叉点
    五子棋对局,执行黑方指定开局、三手可交换、五手两打的规定。整个对局过程中黑方有禁手,白方无禁手。黑方禁手有三三禁手、四四禁手和长连禁手三种。

    二、效果演示

    1. 对局开始
    在这里插入图片描述
    2. 棋手对弈
    在这里插入图片描述

    3. 黑棋胜利
    在这里插入图片描述

    三、程序设计

    1. 定义主窗口类 ( MainWindow )

    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
        void DrawChessBroad();//绘制棋盘
        void DrawItems();//绘制棋子
        QVector<Item> m_items;//记录我们的落子
        bool m_bIsBlackTun;//记录落子颜色
        int CountRoundItems(Item it, QPoint pt);//获取一个方向上的棋子数量
        void mousePressEvent(QMouseEvent *event);//鼠标点击落子
        void paintEvent(QPaintEvent *event);
    
    private:
        Ui::MainWindow *ui;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    2. 创建主窗口 ( mainwindow )

    MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        //比18*25.5稍微大一些
        resize(480,480);
        m_bIsBlackTun = 0;//初始化落子颜色 0 为白色 1为黑色
        m_items.clear();//清空我们的落子
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3. 绘制棋盘 ( DrawChinessBroad )

    void MainWindow::DrawChessBroad(){
        //鼠标光标定位到QPainter,按F1查看帮助文档,找到drawRect函数
        QPainter painter(this);
        QPen pen;//画笔
        pen.setColor(Qt::black);//定义画笔颜色
        pen.setWidth(2);//设置画笔的宽度
        QBrush brush(QColor(Qt::darkYellow));//画刷并设置颜色
        painter.setPen(pen);//添加画笔
        painter.setBrush(brush);//添加画刷
        //因为我们要绘制18*18的棋盘,所以我们使用双重for循环来绘制18*18个棋盘格子
        for(int j = 0;j<CHESS_COLUMES;j++)
        {
            for(int i = 0;i<CHESS_ROWS;i++)
            {
                //我们使用drawRect(int x, int y, int width, int height)来绘制一个矩形(棋盘格子)
                //前两个参数代表矩形的左上顶点,后两个参数代表矩形的宽高
                painter.drawRect((i+0.5)*RECT_WIDTH,(j+0.5)*RECT_HEIGHT,RECT_WIDTH,RECT_HEIGHT);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    4. 定义棋子类 Item

    class Item
    {
    public:
        Item();
        Item(QPoint pt,bool bBlack);//棋子类的有参构造
        QPoint m_pt;//棋子坐标
        //重写==
        bool operator ==(const Item &t1) const
        {
            return (m_bBlack == t1.m_bBlack && m_pt == t1.m_pt);
        }
        bool m_bBlack;//是黑方还是白方下棋
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    5. 绘制棋子 ( DrawItems )

    void MainWindow::DrawItems(){
        QPainter painter(this);
        QPen pen;
        QBrush brush;
        pen.setColor(Qt::transparent);//设置画笔颜色为透明色
        painter.setPen(pen);
        //循环我们的所有落子,并绘制出来
        for(int i = 0;i<m_items.size();i++)
        {
            Item item = m_items[i];
            //判断是黑方还是白方落子
            if(item.m_bBlack)
            {
                painter.setBrush(Qt::black);
            }else {
                painter.setBrush(Qt::white);
            }
            //获取棋子的位置
            QPoint ptCenter((item.m_pt.x()+0.5)*RECT_WIDTH,(item.m_pt.y()+0.5)*RECT_HEIGHT);
            //绘制棋子,棋子的半径为宽高的一半
            painter.drawEllipse(ptCenter,RECT_WIDTH/2,RECT_HEIGHT/2);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    6. 获取同方向上棋子数量 ( CountRoundItems )

    int MainWindow::CountRoundItems(Item it, QPoint pt)
    {
        Item it1 = it;//通过it1来获取当前棋子
        it1.m_pt += pt;//获取对应方向的棋子
        int counter = 0;
        while (m_items.contains(it1)) {//判断it1是否在m_items中
            counter++;//在这个方向的棋子数
            it1.m_pt += pt;
        }
        return counter;//返回棋子数量
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    7. 鼠标点击落子,判断输赢 ( mousePressEvent )

    void MainWindow::mousePressEvent(QMouseEvent *event)
    {
        QPoint pt;//定义一个点
        int chess_x = event->pos().x();//获取鼠标点击的x坐标
        int chess_y = event->pos().y();//获取鼠标点击的y坐标
        pt.setX(chess_x/RECT_WIDTH);//设置棋子x坐标
        pt.setY(chess_y/RECT_HEIGHT);//设置棋子y坐标
        //循环所有棋子判断落子处是否存在棋子
        for(int i = 0;i<m_items.size();i++){
            Item item = m_items[i];
            if(item.m_pt == pt){
                return;
            }
        }
        Item item(pt,m_bIsBlackTun);//设定棋子坐标及颜色
        m_items.append(item);//添加棋子到所有的棋子
        //判定是否赢
        int Left = CountRoundItems(item,QPoint(-1,0));//获取左边棋子的数量
        int Right = CountRoundItems(item,QPoint(+1,0));
        int Up = CountRoundItems(item,QPoint(0,-1));
        int Down = CountRoundItems(item,QPoint(0,+1));
        int LeftUp = CountRoundItems(item,QPoint(-1,-1));
        int LeftDown = CountRoundItems(item,QPoint(-1,+1));
        int RightUp = CountRoundItems(item,QPoint(+1,-1));
        int RightDown = CountRoundItems(item,QPoint(+1,+1));
        //判定四种情况
        if((Left+Right >= 4)|| (Up+Down)>=4 || (LeftUp+RightDown)>=4||(RightUp + LeftDown>=4))
        {
            QString strTip = item.m_bBlack?"黑棋胜出!":"白棋胜出!";//判断当前落子的颜色给出相应的获胜提示
            QMessageBox::information(this,"提示胜利",strTip,QMessageBox::Yes);
            m_items.clear();//清空所有落子
            return;
        }
        m_bIsBlackTun = !m_bIsBlackTun;//切换棋子颜色
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    8. 重绘下棋事件 ( paintEvent )

    void MainWindow::paintEvent(QPaintEvent *event)
    {
        //绘制棋盘
        DrawChessBroad();
        //绘制棋子
        DrawItems();
        //更新
        update();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  • 相关阅读:
    云原生微服务治理 第四章 Spring Cloud Netflix 服务注册/发现组件Eureka
    JavaSE——集合框架
    146.LRU缓存
    [JavaEE]计算机是如何工作的
    SpringCloud微服务技术栈-什么是Docker?怎么安装Docker?
    DBeaver新建Elasticsearch连接报错Error downloading driver libraries解决方案
    高新技术企业认定中涉及的领域有哪些?
    杭州亚运会虚实短视频《功成》,给数字人三维动画宣传片制作有何启发?
    用了10年开源工具,换了Smartbi后,3分钟搞定一份报表
    谈谈WPF和.net的开发模式
  • 原文地址:https://blog.csdn.net/Dustinthewine/article/details/126786956