使用C++的QT框架实现五子棋

news2024/11/26 15:40:51

最近有点无聊正好想玩五子棋,那就实现一下这个游戏吧,网上的五子棋逻辑又长又复杂,我这个逻辑还是蛮简单的,展示如下

这是一个简单的五子棋,今天就了解一下这个游戏的思路,使用的是QT框架,只要思路了解什么框架都能实现

1.首先画棋盘,主要是分横和竖两个方向,代码如下

void Widget::paintEvent(QPaintEvent *event) {
    // 创建一个 QPainter 对象,用于绘制图形,以当前的 Widget 为绘图设备
    QPainter huajia(this);

    // 使用循环绘制水平和垂直的线条,创建一个网格效果
    for (int a = 0; a < 21; a++) {
        // 绘制垂直线条,起点为 (a*40, 0),终点为 (a*40, 800)
        huajia.drawLine(QPoint(a * 40, 0), QPoint(a * 40, 800));

        // 绘制水平线条,起点为 (0, a*40),终点为 (800, a*40)
        huajia.drawLine(QPoint(0, a * 40), QPoint(800, a * 40));
    }

    // 调用基类的 paintEvent 函数来完成绘制操作
    return QWidget::paintEvent(event);
}

加上窗口的大小标题设置

Widget::Widget(QWidget *parent)
    : QWidget(parent) // 构造函数初始化列表,传递父窗口指针
    , ui(new Ui::Widget) // 创建一个 Ui::Widget 对象,通常用于用户界面设计
{
    ui->setupUi(this); // 调用 Ui::Widget 对象的 setupUi 函数来设置用户界面

    // 启用鼠标跟踪,以便能够捕获鼠标移动事件
    this->setMouseTracking(true);

    // 设置窗口的固定大小为 800x800 像素
    this->setFixedSize(QSize(800, 800));

    // 设置窗口的标题为 "五子棋"
    this->setWindowTitle("五子棋");

    // 调用 chushihua() 函数来执行初始化操作
    chushihua();
}

使用循环进行画线,如下

2.创建棋子类,头文件为

#ifndef QIZIZHUANGTAI_H  // 条件编译指令,防止头文件被重复包含
#define QIZIZHUANGTAI_H

#include <QPoint>  // 包含 QPoint 类的头文件
#include <QBrush>  // 包含 QBrush 类的头文件

class qizizhuangtai : public QPoint  // 定义一个 qizizhuangtai 类,继承自 QPoint 类
{

public:
    explicit qizizhuangtai(QPoint dian);  // 构造函数声明

    int x;  // 整型变量 x
    int y;  // 整型变量 y
    int yanse = 0;  // 整型变量 yanse,初始化为 0
    bool zhuangtai = false;  // 布尔变量 zhuangtai,初始化为 false
    QBrush huashua;  // QBrush 对象 huashua
    void shua(int a);  // 成员函数声明 shua
    void fangkai();  // 成员函数声明 fangkai
};

#endif // QIZIZHUANGTAI_H  // 结束条件编译指令,确保头文件完整性

cpp为

#include "qizizhuangtai.h"  // 包含自定义头文件 "qizizhuangtai.h"
#include <QBrush>  // 包含 QBrush 类的头文件

qizizhuangtai::qizizhuangtai(QPoint dian)
{
    this->x = dian.x();  // 构造函数,设置类的 x 成员变量为传入 QPoint 对象的 x 坐标
    this->y = dian.y();  // 构造函数,设置类的 y 成员变量为传入 QPoint 对象的 y 坐标
}

void qizizhuangtai::shua(int a)
{
    this->yanse = a;  // 成员函数,设置类的 yanse 成员变量为传入的整数参数 a
}

void qizizhuangtai::fangkai()
{
    this->zhuangtai = true;  // 成员函数,将类的 zhuangtai 成员变量设置为 true
}

棋子类的属性为:棋子的x,y坐标,状态(比如一开始都为false,而绘画只绘画出为true的棋子)颜色 (区分两方不同的棋子)

3.将棋盘上所有的点都装进一个数组,就是chushihua()这个方法,具体实现如下

void Widget::chushihua()
{
    for (int a = 1; a < 20; a++) {
        for (int b = 1; b < 20; b++) {
            QPoint dian = QPoint(a * 40, b * 40);  // 创建一个 QPoint 对象,坐标为 (a*40, b*40)
            qizizhuangtai qi(dian);  // 创建一个 qizizhuangtai 对象 qi,传入 QPoint 对象 dian
            quan.append(qi);  // 将 qizizhuangtai 对象 qi 添加到容器 quan 中
        }
    }
}

可能会有人问为什么要这样做,其实很简单,应为我们画棋子本事就是根据一个点,加上半径即可,半径已经选好了,那么主要是这个棋子圆形状的坐标,而鼠标事件正好可以捕获坐标,点到哪会将这个位置的棋子状态改变

4.根据鼠标选择要画哪里,如下

或者这种 

这个是怎么实现的呢,其实本质是使用加减算出上下左右坐标的点,之后求出鼠标离这四个点的聚类最后求出最近的点画棋子,代码如下

#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#define QIZIBANJING 15
#define LUOZIBIAOJI 6
#define GEZIDAXIAO 40
#include <QMouseEvent>
#include <QDebug>
#include "qizizhuangtai.h"
#include <QMessageBox>

void Widget::mouseMoveEvent(QMouseEvent *event)
{
    int x = event->x() / 40;  // 将鼠标事件的x坐标除以40,用于确定鼠标所在的列
    int y = event->y() / 40;  // 将鼠标事件的y坐标除以40,用于确定鼠标所在的行
    int shubiaox = event->x();  // 获取鼠标事件的x坐标
    int shubiaoy = event->y();  // 获取鼠标事件的y坐标

    qDebug() << "x为:" << x << "  " << "y为:" << y;

    QPoint zuoshang = QPoint(x * 40, y * 40);  // 左上角的点坐标
    QPoint youshang = zuoshang + QPoint(40, 0);  // 右上角的点坐标
    QPoint zuoxia = zuoshang + QPoint(0, 40);   // 左下角的点坐标
    QPoint youxia = zuoshang + QPoint(40, 40);   // 右下角的点坐标

    // 比较鼠标事件点与四个角的距离的平方
    int zs = (shubiaox - zuoshang.x()) * (shubiaox - zuoshang.x()) + (shubiaoy - zuoshang.y()) * (shubiaoy - zuoshang.y());
    int ys = (shubiaox - youshang.x()) * (shubiaox - youshang.x()) + (shubiaoy - youshang.y()) * (shubiaoy - youshang.y());
    int zx = (shubiaox - zuoxia.x()) * (shubiaox - zuoxia.x()) + (shubiaoy - zuoxia.y()) * (shubiaoy - zuoxia.y());
    int yx = (shubiaox - youxia.x()) * (shubiaox - youxia.x()) + (shubiaoy - youxia.y()) * (shubiaoy - youxia.y());

    qDebug() << "左上距离" << zs << " 右上距离" << ys << " 左下距离" << zx << " 右下距离" << yx;

    // 根据距离的平方选择一个标记点
    if (zs < 800) {
        this->biaojidianx = zuoshang.x();
        this->biaojidiany = zuoshang.y();
    }
    if (ys < 800) {
        this->biaojidianx = youshang.x();
        this->biaojidiany = youshang.y();
    }
    if (zx < 800) {
        this->biaojidianx = zuoxia.x();
        this->biaojidiany = zuoxia.y();
    }
    if (yx < 800) {
        this->biaojidianx = youxia.x();
        this->biaojidiany = youxia.y();
    }

    qDebug() << "标记点x:" << this->biaojidianx << "标记点y:" << this->biaojidiany;
}

这样大致就求出要画棋子的点了

5.落子,主要还是使用鼠标的松开事件,进行对状态的修改

void Widget::mouseReleaseEvent(QMouseEvent *event)
{
    // 遍历存储在 'quan' 向量中的棋子对象
    for (int a = 0; a < quan.size(); a++) {
        // 检查当前棋子的坐标是否与 'biaojidianx' 和 'biaojidiany' 匹配
        if (quan[a].x == biaojidianx && quan[a].y == biaojidiany) {
            // 对匹配的棋子执行 'shua' 操作,传入当前玩家的信息 'qishou'
            quan[a].shua(this->qishou);

            // 对匹配的棋子执行 'fangkai' 操作,可能是该操作的状态变化
            quan[a].fangkai();

            // 切换当前玩家。如果当前玩家是 'hei',则切换为 'bai',反之亦然
            if (this->qishou == hei) {
                this->qishou = bai;
            } else if (this->qishou == bai) {
                this->qishou = hei;
            }
        }
    }

    // 调用基类的鼠标释放事件处理函数,以确保正常的事件处理流程
    return QWidget::mouseReleaseEvent(event);
}

落子顺便改下颜色

 落子进行绘画,代码如下

void Widget::paintEvent(QPaintEvent *event){
    // 创建一个画刷 'huashua',设置颜色为黑色
    QBrush huashua;
    huashua.setColor(Qt::black);
    huashua.setStyle(Qt::SolidPattern);
    // 设置绘图对象 'huajia' 的画刷为 'huashua'
    huajia.setBrush(huashua);
    // 绘制一个小矩形,可能用于标记某个点的位置
    huajia.drawRect(biaojidianx-6, biaojidiany-6, 12, 12);

    // 创建另一个画刷 'huashua2',设置颜色为红色
    QBrush huashua2;
    huashua2.setColor(Qt::red);
    huashua2.setStyle(Qt::SolidPattern);
    // 此处似乎有错误,应该设置 'huajia' 的画刷为 'huashua2' 而不是 'huashua'
    huajia.setBrush(huashua);

    // 绘制圆形
    for (int a = 0; a < quan.size(); a++) {
        if (quan[a].zhuangtai == true) {
            if (quan[a].yanse == 0) {
                // 设置画刷颜色为蓝色
                huashua.setColor(Qt::blue);
                huajia.setBrush(huashua);
                // 绘制蓝色圆形
                huajia.drawEllipse(quan[a].x-15, quan[a].y-15, 30, 30);
                // 调用 'jiance' 函数,可能用于检查圆形的位置
                jiance(quan[a].x, quan[a].y);
            }
            else {
                // 设置画刷颜色为红色
                huashua2.setColor(Qt::red);
                huajia.setBrush(huashua2);
                // 绘制红色圆形
                huajia.drawEllipse(quan[a].x-15, quan[a].y-15, 30, 30);
                // 调用 'jiance' 函数,可能用于检查圆形的位置
                jiance(quan[a].x, quan[a].y);
            }
        }
    }

    // 更新绘图,可能会触发重新绘制操作
    this->update();

    // 调用基类的绘图事件处理函数,以确保正常的事件处理流程
    return QWidget::paintEvent(event);
}

如下所示 

这样就大致实现了五子棋的功能,当然忘记写检测了,其实也蛮容易的,只需要双层for遍历所有的点和这个点的左右上下连续四个是否的yanse属性一样就可以了,大家可以自己试一下,那五子棋到这里就写完了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1167173.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

企业寄件平台一站式管理教程

企业寄件管理平台的诞生&#xff0c;有两大影响因素&#xff1a; 1、企业寄件管理在企业管理体系中越发重要 随着互联网和快递业的发展&#xff0c;企业对外业务开始依托网络、快递。因公寄件在企业中已经是常事&#xff0c;这几年疫情的影响下&#xff0c;越发明显。寄合同、…

活动回顾|OpenTiny 参与线下大会:共创开源未来,助力低代码技术创新

前言 10月下旬 OpenTiny 社区有幸参与了中国开源年会 COSCon’23及华为云开发者日南京站活动。中国开源年会 COSCon’23活动于2023年10月28日至29日在成都菁蓉汇举行&#xff0c;以“科技向善”为指引&#xff0c;旨在推动开源技术和社区的发展&#xff0c;加强产学研合作&…

基于单片机的无线报警系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 技术交流认准下方 CSDN 官方提供的联系方式 文章目录 概要 一、整体设计方案二、 系统的总体方案论证与设计2.1系统的功能要求2.2 系统的技术要求2.3 系统的方案论证及设计2.3.…

PHP进销存ERP系统源码

PHP进销存ERP系统源码 系统介绍&#xff1a; 扫描入库库存预警仓库管理商品管理供应商管理。 1、电脑端手机端&#xff0c;手机实时共享&#xff0c;手机端一目了然。 2、多商户Saas营销版 无限开商户&#xff0c;用户前端自行注册&#xff0c;后台管理员审核开通 3、管理…

更快更准 | YOLOv3算法超详细解析(包括诞生背景+论文解析+技术原理等)

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。YOLOv3是一种基于深度学习的目标检测算法&#xff0c;它可以快速而准确地在图像中检测出多个目标。它是由Joseph Redmon和Ali Farhadi在2018年提出的&#xff0c;是YOLO&#xff08;You Only Look Once&#xff09;系列算法…

写了上千篇文章总结出来的高质量文章内容要点

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容&#x1f34a; 1. 确定文章主题&#x1f34a; 2. 确定目标读者&#x1f34a; 3. 研究资料和信息&#x1f34a; 4. 制定写作计划&#x1f34a; 5. 确定文章结构&#x1f389; 5.1引言&#x1f389; 5.2主体&#x1f389; 5.…

学习笔记|正负偏态的转换方法|对数转换|正态得分法|适用条件|《小白爱上SPSS》课程:加餐 | 如何将非正态分布数据转换为正态分布的?手把手教你SPSS操作

目录 学习目的软件版本原始文档将非正态分布数据转换为正态分布一、正负偏态的转换方法&#xff08;一&#xff09;正偏态数据转换方法&#xff08;二&#xff09;负偏态数据转换方法 三、正态性检验&#xff08;一&#xff09;操作如下&#xff08;二&#xff09;结果解读四、…

CTF工具PDF隐写神器wbStego4open安装和详细使用方法

wbStego4open安装和详细使用方法 1.wbStego4open介绍&#xff1a;2.wbStego4open下载&#xff1a;3.wbStego4open原理图&#xff1a;4.wbStego4open使用教程&#xff1a;第一步&#xff1a;第二步&#xff1a;第三步&#xff1a;第四步&#xff1a;第五步&#xff1a; 5.wbSteg…

电脑版WPS怎么将更新目录加到快速访问栏

效果 步骤 开启首页的“标签”、快速访问、在最近置顶展示然后选择好目录点击右边的设置 》 添加标签选中“快速访问”&#xff0c;确定并关闭完成 相关 WPS怎样设置快速访问工具栏 WPS怎样设置快速访问工具栏-百度经验WPS怎样设置快速访问工具栏,WPS怎样设置快速访问工具栏…

实现dialog在页面随意拖拽

实现dialog在页面随意拖拽 1.先建一个文件如图所示&#xff1a; 文件名:dialog-directive.js 文件内容&#xff1a; import Vue from vue // v-dialogDrag: 弹窗拖拽Vue.directive(dialogDrag, {bind(el, binding, vnode, oldVnode) {// 获取拖拽内容的头部const dialogHeade…

中国联通携手华为助力长城精工启动商用5G-A柔性产线

[中国&#xff0c;河北&#xff0c;2023年11月3日] 近日&#xff0c;中国联通携手华为助力精诚工科汽车系统有限公司保定自动化技术分公司&#xff08;简称长城精工自动化&#xff09;启动5G-A超高可靠性超低时延柔性产线的商用阶段。 在河北保定精工自动化工厂&#xff0c;5G…

java入门,java数据结构二叉树结构

一、前言 树结构是计算机各种存储和查询算法的基本结构。但是在学习这个数据结构的时候&#xff0c;很少人知道它有什么运用&#xff0c;因为在学的时候&#xff0c;也是纯数学的讲解。博主当时学的时候也是云里雾里&#xff0c;最经典的就是严蔚敏和吴伟民的那本《C语言数据结…

python自动化运维——模拟键盘鼠标重复性操作Pyautoui

一、程序样式展示 将程序与cmd.xls文件放在同一文件夹&#xff0c;每一步的截图也放在当前文件夹 通过图片在屏幕上面进行比对&#xff0c;找到点击处进行自动化操作 自动化rpa测试 二、核心点 1.Pyautoui模块&#xff1a;主要针对图片进行定位pyautogui.locateCenterOnScree…

重新理解数字化采购:一场企业内的数字化战役

在显性的采购商品成本之外&#xff0c;越来越多企业开始发现采购环节里高昂的供应链隐性成本&#xff0c;这些成本几乎分布在链条和经营的每个节点&#xff1a;供应商管理、物流履约&#xff0c;售前、售后以及最前端的系统对接搭建等等。 换言之&#xff0c;若想做好数字化采…

智能电表瞬时电量是什么意思?

智能电表已经成为我们进行能源管理的重要工具。其中&#xff0c;瞬时电量这一概念逐渐走进大众视野。那么&#xff0c;智能电表瞬时电量究竟是什么意思&#xff1f;它对我们的生活和能源管理又有哪些影响呢&#xff1f;下面&#xff0c;小编就来为大家介绍一下瞬时电量&#xf…

linux上重启mysql

1、先关闭 [rootHIS bin]# ./mysqladmin -h 127.0.0.1 -u root -p shutdown 2、 再重启 [rootHIS support-files]# ./mysql.server start

eclipse报错 an error has occurred.see the log file

eclipse报错: an error has occurred.see the log file 问题描述 eclipse安装好之后用的好好的,结果第二天再打开的时候突然就起不来了,然后就开始报错 原因分析&#xff1a; 刚安装上那会因为是jdk1.8的环境运行我的项目报错,后来换成高版本的jdk换成了11,用的好好的就这样…

企业提高客服服务质量,可以从哪几个方面着手?

随着市场竞争的日益激烈&#xff0c;企业提高客服服务质量成为了企业发展的重要方向。一个良好的客服服务体系可以提升企业的竞争力&#xff0c;增强企业的品牌影响力。那么企业要如何提高客服服务质量呢&#xff1f;本文将从多个方面入手&#xff0c;帮助企业提高客服服务质量…

双向可视对讲终端机居家养老家用视频对讲

双向可视对讲终端机&#xff0c;用于平安校园&#xff0c;智慧城市、银行、医院&#xff0c;智慧养老&#xff0c;平安校园&#xff0c;无人超市等方案中的可视对讲报警设备。语音识别报警、一键报警、双向视频对讲、录音、电子地图显示、广播喊话等具有多功能产品。是守护平安…

JWT

目录 JWT组成 第一部分header 第二部分payload 第三部分signature 注意 JWT认证算法&#xff1a;签发和校验 drf使用jwt drf项目的jwt认证开发流程 drf-jwt安装和简单使用 安装 简单使用 drf-jwt使用 jwt内置类JSONWebTokenAuthentication 控制使用jwt的登录接口…