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

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

9d3b17a71bbe41e897210e2cb227d171.png

这是一个简单的五子棋,今天就了解一下这个游戏的思路,使用的是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();
}

使用循环进行画线,如下

d98fa04e3fd64eddb37ec192662df341.png

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;  // 整型变量 xint y;  // 整型变量 yint yanse = 0;  // 整型变量 yanse,初始化为 0bool zhuangtai = false;  // 布尔变量 zhuangtai,初始化为 falseQBrush huashua;  // QBrush 对象 huashuavoid shua(int a);  // 成员函数声明 shuavoid 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 对象 dianquan.append(qi);  // 将 qizizhuangtai 对象 qi 添加到容器 quan 中}}
}

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

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

d75e705e70a34fffa4ea7b0967c1e6f1.png

或者这种 

d74b27c0e4874ce18f53696eb5a4018f.png

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

#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);
}

落子顺便改下颜色

3ef2a2caf389454d820b41acb404ac8b.png

 落子进行绘画,代码如下

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);
}

如下所示 

55336f0dbcda494e96763b7f8dc9ac37.png

检测逻辑如下

检测的话其实也蛮容易的,只需要双层for遍历所有的点和这个点的左右上下连续四个是否的颜色属性一样就可以了,大家可以自己试一下

这样的话就大致实现了五子棋的功能,到这里就写完了

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习——回归

目录 一、线性回归 1、回归的概念&#xff08;Regression、Prediction&#xff09; 2、符号约定 3、算法流程 4、最小二乘法&#xff08;LSM&#xff09; 二、梯度下降 梯度下降的三种形式 1、批量梯度下降&#xff08;Batch Gradient Descent,BGD&#xff09;&#xff…

【2023.11.6】OpenAI发布会——近期chatgpt被攻击,不能使用

OpenAI发布会 写在最前面发布会内容GPT-4 Turbo 具有 128K 上下文函数调用更新改进了指令遵循和 JSON 模式可重现的输出和对数概率更新了 GPT-3.5 Turbo 助手 API、检索和代码解释器API 中的新模式GPT-4 Turbo 带视觉DALLE 3文字转语音 &#xff08;TTS&#xff09;收听语音样本…

[unity]切换天空盒

序 unity是自带天空盒的&#xff1a; 但有的时候不想用自带的。怎么自定义&#xff1f;如何设置&#xff1f; 官方文档 Unity - Manual: The Lighting window (unity3d.com) 相关窗口的打开方法 天空盒对应的选项 实际操作 从标准材质球到天空盒材质球 新建一个材质球&…

Powerpoint不小心被覆盖?PPT误删文件如何恢复?

PowerPoint不小心删除了&#xff0c;这可能是众多学生和工作人员最头痛的事情了。PPT被覆盖或误删可能意味着几个小时的努力付之东流。那么PPT覆盖的文档要如何救回来呢&#xff1f;小编将会在本篇文章中为大家分享几个解决方案&#xff0c;使PPT文档覆盖还原操作成为可能&…

为什么有的孩子玩着玩着就成了学霸?

毫不夸张地说&#xff0c;几乎所有的父母都想养出聪明宝宝&#xff0c;孩子上学之后能成为学霸就更省心了。 可“聪明”毕竟不能量化&#xff0c;不是说让孩子上几天课就能提升的。很多家长都在促进孩子大脑发育上使足了劲&#xff0c;可到头来却发现是在做“无用功”。 事实…

Linux-命令行命令

注&#xff1a;[]的内容说明是可选的 1.ls ls [-a -l -h] [Linux路径] >如果没有参数&#xff0c;就展示当前工作目录的内容 > -a&#xff1a;all的意思&#xff0c;即列出所有文件&#xff08;包含隐藏文件/文件夹&#xff09; > -l&#xff1a;以列表形式展示内容&…

3、Dockerfile 深入与其他细节

Dockerfile 在 Docker 中创建镜像最常用的方式&#xff0c;就是使用 Dockerfile。Dockerfile 是一个 Docker 镜像 的描述文件&#xff0c;我们可以理解成火箭发射的 A、B、C、D…的步骤。Dockerfile 其内部包含了一 条条的指令&#xff0c;每一条指令构建一层&#xff0c;因此每…

代码随想录算法训练营第16天|104. 二叉树的最大深度111.二叉树的最小深度222.完全二叉树的节点个数

JAVA代码编写 104. 二叉树的最大深度 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3示例 2&#xff1a; …

鸡尾酒学习——原谅(自制)

1、材料&#xff1a;冰块、君度、蓝橙力娇酒、雪碧、橘子。 2、口感&#xff1a;甜味为主带着一丝丝酸味&#xff0c;喝起来比较清爽&#xff0c;没有一丝酒味的小甜酒。&#xff08;喜欢喝酒的可以多加酒&#xff0c;不喜欢喝酒的可以适量减少酒&#xff09; 3、视觉效果&…

cookie 里面都包含什么属性?

结论先行&#xff1a; Cookie 中除了名称和值外&#xff0c;还有几个比较常见的&#xff0c;例如&#xff1a; Domain 域&#xff1a;指定了 cookie 可以发送到哪些域&#xff0c;只有发送到指定域或其子域的请求才会携带该cookie&#xff1b; Path 路径&#xff1a;指定哪些…

MySQL:锁机制

目录 概述三种层级的锁锁相关的 SQLMyISAM引擎下的锁InnoDB引擎下的锁InnoDB下的表锁和行锁InnoDB下的共享锁和排他锁InnoDB下的意向锁InnoDB下的记录锁&#xff0c;间隙锁&#xff0c;临键锁记录锁&#xff08;Record Locks&#xff09;间隙锁&#xff08;Gap Locks&#xff0…

彻底删除Ubuntu双系统(联想小新2022)

彻底卸载Ubuntu双系统 以里联想小新pro16 i9-12900h为例子 把开机启动项设为默认Windows启动 以联想电脑为例子&#xff0c;关机后一直点击Fn F2进入Bios把windows启动项移到最上面&#xff0c;这样可以开机默认启动windows了删除ubuntu系统分区 使用磁盘管理软件 DiskGeniu…

【手把手教你】将python程序打包成exe可执行文件

1. 安装环境 pip install pyinstaller6.0.02. 打包文件 pyinstaller -D “要启动的文件名“.py比如我的命令就是&#xff1a;pyinstaller -D eval.py 执行完后&#xff0c;会生两个文件夹dist和bulib两个文件和一个xxx.spec文件 3. 删除生成的文件 删除生成的bulid和dist文…

19、Flink 的Table API 和 SQL 中的内置函数及示例(1)

Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…

JAVA 版小程序商城免费搭建 多商家入驻 直播带货 商城系统 B2B2C 商城源码之 B2B2C产品概述

1. 涉及平台 平台管理、商家端&#xff08;PC端、手机端&#xff09;、买家平台&#xff08;H5/公众号、小程序、APP端&#xff08;IOS/Android&#xff09;、微服务平台&#xff08;业务服务&#xff09; 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端框架…

4.移位计算,乘除法运算

目录 一. 移位计算 &#xff08;1&#xff09;算数移位 &#xff08;2&#xff09;逻辑移位 &#xff08;3&#xff09;循环移位 二. 乘法运算 &#xff08;1&#xff09;原码的乘法运算 &#xff08;2&#xff09;补码的乘法运算 三. 除法运算 &#xff08;1&#xf…

MySQL -- mysql connect

MySQL – mysql connect 文章目录 MySQL -- mysql connect一、Connector/C 使用1.环境安装2.尝试链接mysql client 二、MySQL接口1.初始化2.链接数据库3.下发mysql命令4.获取执行结果5.关闭mysql链接6.在C语言中连接MySQL 三、MySQL图形化界面推荐 使用C接口库来进行连接 一、…

【无代码】【VR开发】【Unity】【VRTK】4-导入VRTK Tilia Package

【导入VRTK V4】 VRTK的Tilia Package包含了一整套空间开发方案。导入后你可以在PackageManager中看到它们。 所有的Tilia包都可以在如下页面找到: https://www.vrtk.io/tilia.html Tilia包有一个安装器,可以让你仅仅安装需要的包。包的种类很多,按照适用方向分类。 点击H…

关于Web端 —— UI自动化测试

在手工测试阶段&#xff0c;针对项目输出了测试用例&#xff0c;如果这些测试用例需要在版本迭代的过程中&#xff0c;需要进行回归测试&#xff0c;通过手工重复地执行测试用例&#xff0c;将会耗费大量的人力。 为此应运而生就有了自动化测试&#xff0c;通过使用自动化工具…

行情分析——加密货币市场大盘走势(11.7)

大饼昨日下跌过后开始有回调的迹象&#xff0c;现在还是在做指标修复&#xff0c;大饼的策略保持逢低做多。稳健的依然是不碰&#xff0c;目前涨不上去&#xff0c;跌不下来。 以太昨天给的策略&#xff0c;依然有效&#xff0c;现在以太坊开始回调。 目前来看&#xff0c;回踩…