QT项目实战: 五子棋小游戏

目录

内容介绍

一.添加头文件

二.画棋盘

1.宏定义

2.棋盘

三.画棋子

四.获取棋子摆放位置

五.判断棋子存在

六.判断胜利

1.变量定义和初始化

2.检查获胜条件

3.游戏结束处理

七.重绘

八.效果展示

九.代码

1.mainwindow.h 

2.mainwindow.cpp

3.chessitem.h

4.chessitem.cpp


内容介绍

简单的五子棋游戏

  • MainWindow 类继承自 QMainWindow,用于创建游戏窗口。
  • DrawChessBoard 函数使用 QPainter 绘制棋盘的网格线。
  • DrawHandChess 函数根据当前的棋子颜色在鼠标位置绘制一个棋子。
  • DrawChessItem 函数遍历所有已经放置的棋子并绘制它们。
  • DrawChessAtPoint 函数在指定的位置绘制一个棋子。
  • mousePressEvent 函数处理鼠标点击事件,判断点击位置是否已经有棋子,如果没有,则放置一个新棋子并检查是否胜利。
  • CountNearItem 函数用于计算在特定方向上连续相同颜色的棋子数量。
  • paintEvent 函数是重绘事件,它调用其他函数来绘制整个棋盘和棋子。

一.添加头文件

#include <QKeyEvent> 是 C++ 源代码文件中包含 Qt 库的头文件,用于处理键盘事件。在应用程序中,可以通过重写 QWidget::keyPressEvent() 或 QWidget::keyReleaseEvent() 函数来处理键盘事件。这两个函数的参数都是 QKeyEvent 对象,可以用它来获取键盘事件的详细信息,例如按下或释放的键、键的序号、修饰键等。

#include <QTimer> 是 C++ 源代码文件中包含 Qt 库的头文件,用于创建定时器。QTimer 是 Qt 中用于定时操作的类,可以用来触发特定时间间隔后的操作。通过 QTimer,可以实现定时执行某些任务、定时更新界面等功能。

#include <QPainter> 是 C++ 源代码文件中包含 Qt 库的头文件,用于绘制图形和图像。QPainter 是 Qt 中用于绘制图形和图像的类,可以用来绘制各种形状、文本、图像等。通过 QPainter,可以实现自定义绘制、图形界面美化等功能。

#include <QMouseEvent> 是用于包含 QMouseEvent 类的头文件的指令。在Qt框架中,QMouseEvent 类用于表示鼠标事件,例如鼠标的按下、释放、移动和双击等动作。

二.画棋盘

1.宏定义

  • #define ChessR 12:定义了棋盘的行数,这里是12行。
  • #define ChessC 12:定义了棋盘的列数,这里是12列。
  • #define MaxX 35:定义了棋盘上每个方格的宽度,这里是35个单位。
  • #define MaxY 35:定义了棋盘上每个方格的高度,这里是35个单位。

2.棋盘

  • painter.setPen(QPen(QColor(Qt::black), 2));:设置画笔的颜色为黑色,线宽为2个像素。

  • painter.setBrush(Qt::white);:设置画刷的颜色为白色,用于填充图形。

  • 接下来的双重 for 循环遍历棋盘的列(i)和行(j):painter.drawRect((i+0.5)*Max_X, (j+0.5)*Max_Y, Max_X, Max_Y);:在这个循环中,drawRect 函数被用来绘制一个矩形。矩形的左上角坐标是 (i+0.5)*Max_X 和 (j+0.5)*Max_Y,这样可以确保矩形是从每个方格的中心开始绘制的。矩形的宽度和高度被设置为 Max_X 和 Max_Y

三.画棋子

  • painter.setPen(QPen(QColor(Qt::black), 1));:设置画笔的颜色为黑色,线宽为1个像素。这通常用于绘制棋子的轮廓。

  • 接下来的 for 循环遍历 p_ChessItem 容器中的所有棋子:ChessItem item = p_ChessItem[i];:从 p_ChessItem 容器中获取第 i 个棋子。ChessItem 是一个自定义的结构体或类,包含棋子的位置 _pt 和颜色信息 _blackif(item._black){ painter.setBrush(Qt::black); } else { painter.setBrush(Qt::white); }:根据棋子的颜色属性 _black 设置画刷的颜色。如果 _black 为真,则画刷颜色为黑色,否则为白色。DrawChessAtPoint(painter, item._pt);:调用 DrawChessAtPoint 函数在指定的位置 item._pt 绘制棋子。这个函数需要被定义,它应该接受一个 QPainter 对象和一个 QPoint 对象,并在该点绘制一个圆形或其他形状来表示棋子。

四.获取棋子摆放位置

  • QPoint ptCenter((point.x() + 0.5) * Max_X, (point.y() + 0.5) * Max_Y);:计算棋子的中心点位置。Max_X 和 Max_Y 是棋盘上每个格子宽度和高度的常量。(point.x() + 0.5) * Max_X 和 (point.y() + 0.5) * Max_Y 的计算是为了将棋子的位置从棋盘的离散格子坐标转换为中心点坐标。

  • painter.drawEllipse(ptCenter, Max_X / 3, Max_Y / 3);:在计算出的中心点位置 ptCenter 绘制一个椭圆。椭圆的宽度是 Max_X / 3,高度是 Max_Y / 3。这表示椭圆的尺寸是棋盘格尺寸的三分之一,从而在棋盘上绘制一个大小合适的棋子。

五.判断棋子存在

  • for 循环遍历 p_ChessItem 容器中的所有棋子。
  • if 语句检查当前棋子的位置 _pt 是否与给定的点 pt 相等。
  • 如果位置相等,函数立即返回 true,表示棋子存在。
  • 如果 for 循环完成后没有找到相等的点,函数返回 false,表示棋子不存在。

六.判断胜利

1.变量定义和初始化

nLeftnLeftUpnUpnRightnRightUpnRightDownnDownnLeftDown 这些变量通过调用 CountNearItem 函数来计算,该函数接受一个棋子对象 item 和一个表示方向的 QPoint 对象,返回该方向上相邻的棋子数量。

2.检查获胜条件

代码检查四个方向上的棋子数量组合

  • (nRightUp + nLeftDown) >= 4:检查右上到左下对角线方向上是否有至少四个连续的棋子。
  • (nUp + nDown) >= 4:检查垂直方向上是否有至少四个连续的棋子。
  • (nLeftUp + nRightDown) >= 4:检查左上到右下对角线方向上是否有至少四个连续的棋子。
  • (nLeft + nRight) >= 4:检查水平方向上是否有至少四个连续的棋子。

3.游戏结束处理

  • 如果上述任一条件满足,即有一方玩家形成了至少四个连续棋子的组合,游戏结束。
  • 根据 b_black 变量的值(如果为真,表示黑棋赢;否则,表示白棋赢),构建一个字符串 str 来显示获胜信息。
  • 使用 QMessageBox::information 函数显示一个消息框,通知玩家游戏结束,并显示获胜信息。
  • 清除棋盘上的所有棋子(通过 p_ChessItem.clear();)。
  • 函数返回,结束游戏。

七.重绘

八.效果展示

九.代码

1.mainwindow.h 

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QPainter>
#include <QPaintEvent>
#include <QMouseEvent>
#include <QVector>
#include <QDebug>
#include "chessitem.h"
#include <QMessageBox>#define ChessR 12
#define ChessC 12
#define MaxX 35
#define MaxY 35QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();void paintEvent(QPaintEvent *event);void mousePressEvent(QMouseEvent *event); //鼠标变形int CountNearItem(ChessItem item , QPoint pt); //判断棋子连接private:Ui::MainWindow *ui;void InitUI();void DrawChessBoard();//画棋盘void DrawChessItem();//绘制棋盘上的棋子void DrawChessAtPoint(QPainter &painter , QPoint &point); //画棋子的样式和位置bool b_black; //定义棋子的颜色QVector<ChessItem> p_ChessItem;//存储棋子};
#endif // MAINWINDOW_H

2.mainwindow.cpp

#include "mainwindow.h"
#include "./ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);InitUI();
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::InitUI()
{//定义棋盘的大小this->resize((ChessC + 1) * MaxX, (ChessR + 1) * MaxX);b_black = false;
}void MainWindow::DrawChessBoard()
{QPainter painter(this);painter.setPen(QPen(QColor(Qt::black),2));painter.setBrush(Qt::white);//棋盘格子for(int i=0; i <ChessC; i++){for(int j =0; j<ChessR;j++){painter.drawRect((i+0.5)*MaxX,(j+0.5)*MaxY,MaxX,MaxY);}}
}//绘制棋盘上的所有棋子
void MainWindow::DrawChessItem()
{QPainter painter(this);painter.setPen(QPen(QColor(Qt::black),1));//遍历棋子,有就绘制,没有就不绘制for(int i = 0; i < p_ChessItem.size() ; i++){ChessItem item = p_ChessItem[i]; //当前棋子的样式和位置复制给棋子这个类if(item._black){painter.setBrush(Qt::black);}else {painter.setBrush(Qt::white);}DrawChessAtPoint(painter,item._pt);}
}void MainWindow::DrawChessAtPoint(QPainter &painter , QPoint &point)
{//获取棋子的摆放位置QPoint ptCenter((point.x() + 0.5) * MaxX , (point.y() + 0.5) * MaxY);painter.drawEllipse(ptCenter,MaxX/3,MaxY/3);
}void MainWindow::mousePressEvent(QMouseEvent *event)
{QPoint pt;  //定义点位pt.setX((event->pos().x())/MaxX);pt.setY((event->pos().y())/MaxY);//判断棋子是否存在for(int i = 0 ; i<p_ChessItem.size(); i++){ChessItem item = p_ChessItem[i];if(item._pt == pt){return ;}}//如果不存在,进行绘制和判断五子链接ChessItem item(pt,b_black);p_ChessItem.append(item);//统计四个点位是否连接int nLeft       = CountNearItem(item,QPoint(-1,0));int nLeftUp     = CountNearItem(item,QPoint(-1,-1));;int nUp         = CountNearItem(item,QPoint(0,-1));;int nRight      = CountNearItem(item,QPoint(1,0));;int nRightUp    = CountNearItem(item,QPoint(1,-1));;int nRightDown = CountNearItem(item,QPoint(1,1));;int nDown       = CountNearItem(item,QPoint(0,1));;int nLeftDown   = CountNearItem(item,QPoint(-1,1));;if( (nLeft + nRight) >= 4 || (nLeftUp + nRightDown) >=4|| (nUp + nDown) >=4 || (nRightUp + nLeftDown) >= 4){QString str = b_black ? "black win" : "white win";QMessageBox::information(NULL,"GAME OVER",str,QMessageBox::Yes);p_ChessItem.clear();return;}//换人下棋b_black = !b_black;
}int MainWindow::CountNearItem(ChessItem item, QPoint pt)
{int nCount = 0;item._pt += pt;while (p_ChessItem.contains(item)) {nCount++;item._pt += pt;}return nCount;
}void MainWindow::paintEvent(QPaintEvent *event)
{DrawChessBoard();DrawChessItem();update();
}

3.chessitem.h

#ifndef CHESSITEM_H
#define CHESSITEM_H#include <QObject>
#include <QPoint>class ChessItem
{
public:ChessItem();ChessItem(QPoint point,bool isBluck);  //位置和颜色bool operator==(const ChessItem &t1)const{return ((_pt==t1._pt) && (_black==t1._black));}QPoint _pt;  //棋子的位置bool _black; //棋子的颜色
};#endif // CHESSITEM_H

4.chessitem.cpp

#include "chessitem.h"ChessItem::ChessItem(void) {}ChessItem::ChessItem(QPoint point, bool isBluck)
{_pt = point;_black = isBluck;
}

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

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

相关文章

【python】在【机器学习】与【数据挖掘】中的应用:从基础到【AI大模型】

目录 &#x1f497;一、Python在数据挖掘中的应用&#x1f495; &#x1f496;1.1 数据预处理&#x1f49e; &#x1f496;1.2 特征工程&#x1f495; &#x1f497;二、Python在机器学习中的应用&#x1f495; &#x1f496;2.1 监督学习&#x1f49e; &#x1f496;2.2…

【MySQL】(基础篇七) —— 通配符和正则表达式

通配符和正则表达式 本章介绍什么是通配符、如何使用通配符以及怎样使用LIKE操作符进行通配搜索&#xff0c;以便对数据进行复杂过滤&#xff1b;如何使用正则表达式来更好地控制数据过滤。 目录 通配符和正则表达式LIKE操作符百分号(%)通配符下划线(_)通配符 通配符使用技巧正…

深入理解 C++ 智能指针

文章目录 一、引言二、 原始指针的问题1、原始指针的问题2、智能指针如何解决这些问题 三、智能指针的类型四、std::shared_ptr1、shared_ptr使用2、shared_ptr的使用注意事项3、定制删除器4、shared_ptr的优缺点5、shared_ptr的模拟实现 五、std::unique_ptr1、unique_ptr的使…

SpringSecurity入门(三)

12、密码加密 12.1、不指定具体加密方式&#xff0c;通过DelegatingPasswordEncoder&#xff0c;根据前缀自动选择 PasswordEncoder passwordEncoder PasswordEncoderFactories.createDelegatingPasswordEncoder();12.2、指定具体加密方式 // Create an encoder with streng…

【iOS】UI学习——登陆界面案例、照片墙案例

文章目录 登陆界面案例照片墙案例 登陆界面案例 这里通过一个登陆界面来复习一下前面学习的内容。 先在接口部分定义两个UILabel、两个UITextField、两个UIButton按键&#xff1a; #import <UIKit/UIKit.h>interface ViewController : UIViewController {UILabel* _lb…

2024050501-重学 Java 设计模式《实战命令模式》

重学 Java 设计模式&#xff1a;实战命令模式「模拟高档餐厅八大菜系&#xff0c;小二点单厨师烹饪场景」 一、前言 持之以恒的重要性 初学编程往往都很懵&#xff0c;几乎在学习的过程中会遇到各种各样的问题&#xff0c;哪怕别人那运行好好的代码&#xff0c;但你照着写完…

Python数据分析与机器学习在电子商务推荐系统中的应用

文章目录 &#x1f4d1;引言一、推荐系统的类型二、数据收集与预处理2.1 数据收集2.2 数据预处理 三、基于内容的推荐3.1 特征提取3.2 计算相似度3.3 推荐物品 四、协同过滤推荐4.1 基于用户的协同过滤4.2 基于物品的协同过滤 五、混合推荐与评估推荐系统5.1 结合推荐结果5.2 评…

Qwen2本地部署的实战教程

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

网络安全技术实验一 信息收集和漏洞扫描

一、实验目的和要求 了解信息搜集和漏洞扫描的一般步骤&#xff0c;利用Nmap等工具进行信息搜集并进行综合分析&#xff1b;掌握TCP全连接扫描、TCP SYN扫描的原理,利用Scapy编写网络应用程序&#xff0c;开发端口扫描功能模块&#xff1b;使用漏洞扫描工具发现漏洞并进行渗透测…

8款高效电脑维护与多媒体工具合集!

AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频https://h5.cxyhub.com/?invitationhmeEo7 1. 系统安装利器——WinNTSetup 系统安装利器&#xff0c;目前最好用的系统安装器&#xff0c;Windows系统安装部署工具。支持所…

跟我学,数据结构和组原真不难

我个人认为408中计算机组成原理和数据结构最难 难度排行是计算机组成原理>数据结构>操作系统>计算机网络。 计算机组成原理比较难的原因是&#xff0c;他涉及的硬件的知识比较多&#xff0c;这对于大家来说难度就很高了&#xff0c;特别是对于跨考的同学来说&#x…

ABB机械人模型下载

可以下载不同格式的 https://new.abb.com/products/robotics/zh/robots/articulated-robots/irb-6700 step的打开各部件是分开的&#xff0c;没有装配在一起&#xff0c;打开看单个零件时&#xff0c;我们会发现其各零件是有装配的定位关系的。 新建一个装配环境&#xff0c;点…

【qt】MDI多文档界面开发

MDI多文档界面开发 一.应用场景二.界面设计三.界面类设计四.实现功能1.新建文档2.打开文件3.关闭所有4.编辑功能5.MDI页模式6.瀑布展开模式7.平铺模式 五.总结 一.应用场景 类似于vs的界面功能,工具栏的功能可以对每个文档使用! 二.界面设计 老规矩,边做项目边学! 目标图: 需…

【JMeter接口测试工具】第二节.JMeter项目实战(上)【实战篇】

文章目录 前言项目实战零、接口测试流程一、测试数据准备二、接口功能测试三、掌握测试用例编写四、自动化脚本架构搭建总结 前言 零、接口测试流程 1、制定测试计划,分配任务 2、从 API 文档中提取接口清单&#xff1a;对 API 文档简化,提高测试效率,接口清单就是对 API 文档…

【研发日记】Matlab/Simulink软件优化(三)——利用NaNFlag为数据处理算法降阶

文章目录 前言 背景介绍 初始算法 优化算法 分析和应用 总结 前言 见《【研发日记】Matlab/Simulink软件优化(一)——动态内存负荷压缩》 见《【研发日记】Matlab/Simulink软件优化(二)——通信负载柔性均衡算法》 背景介绍 在一个嵌入式软件开发项目中&#xff0c;需要开…

OpenAI与核聚变公司寻求合作,白宫拨款1.8亿美元用于核聚变商业化研究

在当下&#xff0c;由 AI 引发的新一轮能源危机已经不再是一个小概率的「黑天鹅」事件&#xff0c;而是一头正在向我们猛冲而来的「灰犀牛」。 Helion Energy&#xff0c;是一家总部位于美国华盛顿州埃弗雷特的能源创业公司。 3.5研究测试&#xff1a;hujiaoai.cn 4研究测试&am…

Mysql的底层实现逻辑

Mysql5.x和Mysql8性能的差异 整体性能有所提高&#xff0c; 在非高并发场景下&#xff0c;他们2这使用区别不大&#xff0c;性能没有明显的区别。 只有高并发时&#xff0c;mysql8才体现他的优势。 2. Mysql数据存储结构Innodb逻辑结构 数据选用B树结构存储数据&#xff0…

如何画系统架构图学习

原文链接:https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/%E4%BB%8E%200%20%E5%BC%80%E5%A7%8B%E5%AD%A6%E6%9E%B6%E6%9E%84/51%20%E5%A6%82%E4%BD%95%E7%94%BB%E5%87%BA%E4%BC%98%E7%A7%80%E7%9A%84%E8%BD%AF%E4%BB%B6%E7%B3%BB%E7%BB%9F%E6%9E%B6%E6%9E%84%E5%9B%BE%EF…

C++ 11 【可变参数模板】【lambda】

&#x1f493;博主CSDN主页:麻辣韭菜&#x1f493;   ⏩专栏分类&#xff1a;C修炼之路⏪   &#x1f69a;代码仓库:C高阶&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多C知识   &#x1f51d;&#x1f51d; 目录 前言 一、新的类功能 1.1默认成员函数—…

【数据分析基础】实验三 文件操作、数组与矩阵运算

一&#xff0e;实验目的 掌握上下文管理语句with的使用方法。掌握文本文件的操作方法。了解os、os.path模块的使用。掌握扩展库Python-docx、openpyxl的安装与操作word、Excel文件内容的方法。熟练掌握numpy数组相关运算和简单应用。熟练使用numpy创建矩阵&#xff0c;熟悉常用…