【QT项目】简易五子棋游戏(人机对战)— 完整源码

news/2024/5/2 10:25:39/文章来源:https://blog.csdn.net/qq_59134387/article/details/127147586

文章目录

  • 前言
  • 一、游戏实现效果
  • 二、需求分析
  • 三、解决方案
  • 四、核心步骤
    • 1.插入棋盘图
    • 2.双方落子
    • 3.输赢判定
    • 4.重新开始
  • 五、完整源码
    • 1.main.cpp
    • 2.chessboard.h
    • 3.chessboard.cpp
  • 总结


前言

   本篇,我们将使用QT实现一个人机对战的简易五子棋游戏,适合QT零基础和初学者进行学习。


一、游戏实现效果

  • 这里的电脑为简单人机,没有采用特定的算法,因此没有防守功能,有兴趣的小伙伴可以自行拓展。
    在这里插入图片描述

二、需求分析

  • 项目开始前,需要我们对项目进行简单的需求分析,知道我们应该做些什么?

  (1)在窗口背景插入棋盘图

  (2)玩家鼠标点击棋盘某个区域落子

  (3)电脑在棋盘上某个空白区域落子

  (4)输赢判定,在棋盘的水平方向、垂直方向、对角线方向是否五子连珠

  (5)清空棋盘,开始新一轮游戏
  

三、解决方案

  • 完成需求分析后,需要针对每个需求思考相应的解决方案,确保项目的可行性。

  (1)在窗口内创建一个QLabel类标签用来插入棋盘图

  (2)使用鼠标点击事件函数,动态创建一个标签插入棋子图,并显示在鼠标的点击位置

  (3)使用随机数生成函数,在随机生成的键盘某个区域位置,用同样的方法插入棋子图

  (4)创建一个二维向量容器对应棋盘的每个坐标,并使用双重循环遍历棋盘判断是否五子连珠

  (5)在窗口内嵌套一个透明窗口作为棋子容器,游戏结束时,释放该窗口并重新动态创建透明窗口
  

四、核心步骤

1.插入棋盘图

  • 我们借助QLabel标签显示图片,并将标签设置与主窗口同等大小作为背景图
    //插入棋盘背景this->bg = new QLabel(this);								//创建标签到主窗口中this->bg->setGeometry(0,0,810,810);							//设置标签大小和位置this->bg->setPixmap(QPixmap("./picture/chessboard.png"));	//将棋盘图插入到标签中this->bg->setScaledContents(true);							//图片自适应标签大小

2.双方落子

  • 使用鼠标点击事件,在玩家在点击位置落子,紧接着电脑利用随机数生成坐标落子
void chessboard::mousePressEvent(QMouseEvent *event)
{//若鼠标点击位置没有棋子,则玩家落子if(chess.at(event->x()/54).at(event->y()/54) == 0){//返回值判断一方是否获胜bool result = this->piecePress(PLAYERS,event->x(),event->y());//玩家胜利时,跳过电脑落子重新开始游戏if(result == true){return;}//直到生成随机数区域没有棋子,则电脑落子while(1){//生成随机横坐标int computerx = qrand()%800;//生成随机纵坐标int computery = qrand()%800;//判断该位置是否有棋子if(chess.at(computerx/54).at(computery/54) == 0){//电脑落子this->piecePress(COMPUTER,computerx,computery);break;}}}
}
  • 落子显示,我们通过动态创建标签的方式显示棋子图片,并根据下棋对象显示黑棋/白棋
bool chessboard::piecePress(bool object, int x, int y)
{//动态创建标签插入棋子图,并初始化位置信息this->piece = new QLabel(this->chessWin);this->piece->setGeometry(x-x%54,y-y%54,54,54);this->piece->setScaledContents(true);//若下棋对象为玩家if(object == PLAYERS){//插入黑棋图this->piece->setPixmap(QPixmap("./picture/black.png"));//棋盘相应位置进行标记chess[x/54][y/54] = 1;}//若下棋对象为电脑else if(object == COMPUTER){//插入白棋图this->piece->setPixmap(QPixmap("./picture/white.png"));//棋盘相应位置进行标记chess[x/54][y/54] = 2;}//棋子显示this->piece->show();//输赢判定,并返回判定结果return this->winner();
}

3.输赢判定

  • 在玩家/电脑每次落子之后,将通过四个不同方向扫描整个棋盘进行一次输赢判定
bool chessboard::winner()
{//横向扫描for(int i=0;i<15;i++){for(int j=0;j<11;j++){if(chess[i][j]==1 && chess[i][j+1]==1 && chess[i][j+2]==1 && chess[i][j+3]==1 && chess[i][j+4]==1){QMessageBox::information(nullptr,"温馨提示","玩家获胜!");this->newGame();return true;}else if(chess[i][j]==2 && chess[i][j+1]==2 && chess[i][j+2]==2 && chess[i][j+3]==2 && chess[i][j+4]==2){QMessageBox::information(nullptr,"温馨提示","电脑获胜!");this->newGame();return true;}}}//纵向扫描for(int j=0;j<15;j++){for(int i=0;i<11;i++){if(chess[i][j]==1 && chess[i+1][j]==1 && chess[i+2][j]==1 && chess[i+3][j]==1 && chess[i+4][j]==1){QMessageBox::information(nullptr,"温馨提示","玩家获胜!");this->newGame();return true;}else if(chess[i][j]==2 && chess[i+1][j]==2 && chess[i+2][j]==2 && chess[i+3][j]==2 && chess[i+4][j]==2){QMessageBox::information(nullptr,"温馨提示","电脑获胜!");this->newGame();return true;}}}//对角扫描for(int i=0;i<11;i++){for(int j=0;j<11;j++){if(chess[i][j]==1 && chess[i+1][j+1]==1 && chess[i+2][j+2]==1 && chess[i+3][j+3]==1 && chess[i+4][j+4]==1){QMessageBox::information(nullptr,"温馨提示","玩家获胜!");this->newGame();return true;}else if(chess[i][j]==2 && chess[i+1][j+1]==2 && chess[i+2][j+2]==2 && chess[i+3][j+3]==2 && chess[i+4][j+4]==2){QMessageBox::information(nullptr,"温馨提示","电脑获胜!");this->newGame();return true;}}}//反对角扫描for(int j=0;j<11;j++){for(int i=14;i>3;i--){if(chess[i][j]==1 && chess[i-1][j+1]==1 && chess[i-2][j+2]==1 && chess[i-3][j+3]==1 && chess[i-4][j+4]==1){QMessageBox::information(nullptr,"温馨提示","玩家获胜!");this->newGame();return true;}else if(chess[i][j]==2 && chess[i-1][j+1]==2 && chess[i-2][j+2]==2 && chess[i-3][j+3]==2 && chess[i-4][j+4]==2){QMessageBox::information(nullptr,"温馨提示","电脑获胜!");this->newGame();return true;}}}return false;
}

4.重新开始

  • 游戏结束后,初始化棋盘,并释放主窗口中所有通过动态创建的标签显示的棋子图
void chessboard::newGame()
{//初始化棋盘for(int i=0;i<15;i++){for(int j=0;j<15;j++){chess[i][j] = 0;}}//释放棋盘窗口,包括棋子delete this->chessWin;//创建新棋盘窗口,并初始化this->chessWin = new QWidget(this);this->chessWin->resize(810,810);this->chessWin->show();
}

五、完整源码

1.main.cpp

#include "widget.h"
#include "chessboard.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);chessboard *five = chessboard::getInstance();   //创建棋盘窗口five->show();	//棋盘窗口显示return a.exec();
}

2.chessboard.h

#ifndef CHESSBOARD_H
#define CHESSBOARD_H#include <QLabel>
#include <QVector>
#include <QWidget>
#include <QMouseEvent>#define PLAYERS 0
#define COMPUTER 1class chessboard : public QWidget
{Q_OBJECT
public://静态公有的获取类对象指针的方法static chessboard* getInstance();//鼠标点击事件void mousePressEvent(QMouseEvent *event);//落子函数bool piecePress(bool object,int x,int y);//输赢判定函数bool winner();//重新开始游戏void newGame();
private://构造函数私有化explicit chessboard(QWidget *parent = 0);//静态私有的类对象指针static chessboard* pchessboard;//棋盘图片QLabel *bg;//棋子图片QLabel *piece;//棋盘落子情况:0无棋子,1有棋子static QVector<QVector<int>> chess;//棋盘窗口QWidget *chessWin;
signals:public slots:
};#endif // CHESSBOARD_H

3.chessboard.cpp

#include <QTime>
#include <QtGlobal>
#include <QMessageBox>
#include "chessboard.h"QVector<QVector<int>> chessboard::chess;	
chessboard* chessboard::pchessboard = nullptr;	chessboard *chessboard::getInstance()
{if(chessboard::pchessboard == nullptr){chessboard::pchessboard = new chessboard();}return chessboard::pchessboard;
}void chessboard::mousePressEvent(QMouseEvent *event)
{//若鼠标点击位置没有棋子,则玩家落子if(chess.at(event->x()/54).at(event->y()/54) == 0){//返回值判断一方是否获胜bool result = this->piecePress(PLAYERS,event->x(),event->y());//玩家胜利时,跳过电脑落子重新开始游戏if(result == true){return;}//直到生成随机数区域没有棋子,则电脑落子while(1){//生成随机横坐标int computerx = qrand()%800;//生成随机纵坐标int computery = qrand()%800;//判断该位置是否有棋子if(chess.at(computerx/54).at(computery/54) == 0){//电脑落子this->piecePress(COMPUTER,computerx,computery);break;}}}
}bool chessboard::piecePress(bool object, int x, int y)
{//动态创建标签插入棋子图,并初始化位置信息this->piece = new QLabel(this->chessWin);this->piece->setGeometry(x-x%54,y-y%54,54,54);this->piece->setScaledContents(true);//若下棋对象为玩家if(object == PLAYERS){//插入黑棋图this->piece->setPixmap(QPixmap("./picture/black.png"));//棋盘相应位置进行标记chess[x/54][y/54] = 1;}//若下棋对象为电脑else if(object == COMPUTER){//插入白棋图this->piece->setPixmap(QPixmap("./picture/white.png"));//棋盘相应位置进行标记chess[x/54][y/54] = 2;}//棋子显示this->piece->show();//输赢判定,并返回判定结果return this->winner();
}bool chessboard::winner()
{//横向扫描for(int i=0;i<15;i++){for(int j=0;j<11;j++){if(chess[i][j]==1 && chess[i][j+1]==1 && chess[i][j+2]==1 && chess[i][j+3]==1 && chess[i][j+4]==1){QMessageBox::information(nullptr,"温馨提示","玩家获胜!");this->newGame();return true;}else if(chess[i][j]==2 && chess[i][j+1]==2 && chess[i][j+2]==2 && chess[i][j+3]==2 && chess[i][j+4]==2){QMessageBox::information(nullptr,"温馨提示","电脑获胜!");this->newGame();return true;}}}//纵向扫描for(int j=0;j<15;j++){for(int i=0;i<11;i++){if(chess[i][j]==1 && chess[i+1][j]==1 && chess[i+2][j]==1 && chess[i+3][j]==1 && chess[i+4][j]==1){QMessageBox::information(nullptr,"温馨提示","玩家获胜!");this->newGame();return true;}else if(chess[i][j]==2 && chess[i+1][j]==2 && chess[i+2][j]==2 && chess[i+3][j]==2 && chess[i+4][j]==2){QMessageBox::information(nullptr,"温馨提示","电脑获胜!");this->newGame();return true;}}}//对角扫描for(int i=0;i<11;i++){for(int j=0;j<11;j++){if(chess[i][j]==1 && chess[i+1][j+1]==1 && chess[i+2][j+2]==1 && chess[i+3][j+3]==1 && chess[i+4][j+4]==1){QMessageBox::information(nullptr,"温馨提示","玩家获胜!");this->newGame();return true;}else if(chess[i][j]==2 && chess[i+1][j+1]==2 && chess[i+2][j+2]==2 && chess[i+3][j+3]==2 && chess[i+4][j+4]==2){QMessageBox::information(nullptr,"温馨提示","电脑获胜!");this->newGame();return true;}}}//反对角扫描for(int j=0;j<11;j++){for(int i=14;i>3;i--){if(chess[i][j]==1 && chess[i-1][j+1]==1 && chess[i-2][j+2]==1 && chess[i-3][j+3]==1 && chess[i-4][j+4]==1){QMessageBox::information(nullptr,"温馨提示","玩家获胜!");this->newGame();return true;}else if(chess[i][j]==2 && chess[i-1][j+1]==2 && chess[i-2][j+2]==2 && chess[i-3][j+3]==2 && chess[i-4][j+4]==2){QMessageBox::information(nullptr,"温馨提示","电脑获胜!");this->newGame();return true;}}}return false;
}void chessboard::newGame()
{//初始化棋盘for(int i=0;i<15;i++){for(int j=0;j<15;j++){chess[i][j] = 0;}}//释放棋盘窗口,包括棋子delete this->chessWin;//创建新棋盘窗口,并初始化this->chessWin = new QWidget(this);this->chessWin->resize(810,810);this->chessWin->show();
}chessboard::chessboard(QWidget *parent) : QWidget(parent)
{//隐藏标题栏this->setFixedSize(810,810);//创建棋盘背景this->bg = new QLabel(this);this->bg->setGeometry(0,0,810,810);this->bg->setPixmap(QPixmap("./picture/chessboard.png"));this->bg->setScaledContents(true);//创建棋盘窗口this->chessWin = new QWidget(this);this->chessWin->resize(810,810);//初始化棋盘for(int i=0;i<15;i++){QVector<int> row;for(int j=0;j<15;j++){row.append(0);}chess.append(row);}//随机数初始化qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
}

总结

   以上就是【QT项目】简易五子棋游戏(人机对战)的所有内容,希望大家阅读后都能有所收获!原创不易,转载请标明出处,若文章出现有误之处,欢迎读者留言指正批评!

在这里插入图片描述

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

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

相关文章

直线生成以及pcl直线拟合

目录写在前面codecompile&runresult参考写在前面 1、本文内容 pcl直线拟合&#xff0c;生成带噪声的直线并进行直线拟合的demo 2、平台 windows, pcl1.10.0 3、转载请注明出处&#xff1a; https://blog.csdn.net/qq_41102371/article/details/127147223 code line_seg…

国庆节日头像框小程序源码带流量主广告

国庆头像小程序最新可用源码&#xff0c;自己把图片链接换下&#xff0c;直接使用小程序开发工具修改即可&#xff01;&#xff0c;需要添加合法域名&#xff0c;教程我都放文档里了&#xff0c;类目选择信息查询。 需要源码的找我&#xff01;

(附源码)计算机毕业设计SSM本科培训班学员信息管理系统

毕设帮助&#xff0c;指导&#xff0c;本源码分享&#xff0c;调试部署(见文末) 3.3 系统功能分析 本科培训班学员信息管理系统主要包括两大功能模块&#xff0c;即管理员功能模块和学员模块。 &#xff08;1&#xff09;管理员模块&#xff1a;系统中的核心用户是系统管理员&a…

postgresql源码学习(44)—— 守护进程Postmaster与服务进程Postgres

一、 Postmaster与Postgres进程的关系 pg使用的是多进程架构&#xff0c;众多进程之中&#xff0c;最为重要的就是在前一节main函数中出现的Postmaster与Postgres进程。 守护进程Postmaster&#xff1a;负责PG的启动和关闭&#xff1b;监听和接收客户端连接请求&#xff0c;为…

宋宇-课堂对话领域研究热点与 前沿趋势探究

好家伙。。。 看这种论文容易自闭&#xff0c;&#xff0c;&#xff0c;怎么能写这么好呢。。。 下次看看博士的论文吧还是。。 定义 课堂对话( classroom dialogue /discourse) 是师生间或者生生间围绕教育教 学目标的实现所形成的良性的交流活动。&#xff3b;1&#xff3d…

大一作业HTML电影网页作业(HTML+CSS)

&#x1f329;️ 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f482; 作者主页: 【进入主页—&#x1f680;获取更多源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;HTML5网页期末作业 (1000套…

[leetcode]450.删除二叉树搜索树的节点

一.题目描述 给定一个二叉搜索树的根节点 root 和一个值 key&#xff0c;删除二叉搜索树中的 key 对应的节点&#xff0c;并保证二叉搜索树的性质不变。返回二叉搜索树&#xff08;有可能被更新&#xff09;的根节点的引用。 一般来说&#xff0c;删除节点可分为两个步骤&…

ES6--》读懂JS中—Class类

目录 Class类 初识class class中getter和setter设置 表达式方式书写 静态属性与静态方法 私有属性和私有方法 class继承 静态属性和方法继承 私有属性和方法继承 class显示原型与隐式原型关系 Class类 ES6提供了更接近传统语言的写法&#xff0c;引入了Class(类)这个…

脚本学习:1

今天所学的就俩个案例。 1.用脚本实现,鼠标移动到我的淘宝显示菜单&#xff0c;移除菜单隐藏 基本思路通过display来控制 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>脚本示例</title>&l…

03 NLP-神经网络基础常识复习3-梯度的推导和反向传播的实现

计算图的介绍结束了&#xff0c;下面我们来实现一些实用的层。这里&#xff0c;我们将实现Sigmoid层、全连接层,Affine层和Softmax with Loss层。 1.Sigmoid层 sigmoid函数由 表示&#xff0c; sigmoid函数的导数由下式表示 Sigmoid层的计算图可以绘制成如下图。这里&#x…

PWM实验(控制蜂鸣器,风扇,马达)

cortex-A7核实现PWM对蜂鸣器&#xff0c;风扇&#xff0c;马达的控制 1.PWM概念 PWM为一种对模拟信号电平进行数字编码的方法&#xff0c;通过高分辨率计数器的使用&#xff0c;方波的占空比被调制用来对一个具体模拟信号的电平进行编码。 A7核的芯片有控制PWM的脉冲宽度调制定…

【设计模式】-创建型模式-第2章第4讲-【原型模式】

目录 1、原型模式&#xff08;Prototype Pattern&#xff09;概念 2、浅拷贝与深拷贝 2.1、概念 2.2、Java 中的深浅拷贝 浅拷贝&#xff1a; 深拷贝&#xff1a; 实例 浅拷贝 深拷贝的两种实现方式 方式一 方式二 3、原型模式的优缺点 4、 结尾 1、原型模式&#…

带你一步步分析webpack是如何执行打包产物的

引入关系如图所示&#xff1a; 圈出来文件d是异步导入的文件。 wepback版本如图所示&#xff1a; 执行打包命令&#xff0c;产物如下图&#xff1a; 会生成两个js文件&#xff0c;一个是入口文件打包的testxx.js&#xff0c;还有一个是异步文件d生成的src_d_js.js。 打包后的…

CSS学习298~355(品优购+Web服务器)

1 品优购项目规划 1.1 网站制作流程 我们主要做前台页面设计 1.2 品优购项目整体介绍 项目名称: 品优购项目描述:品优购是一个电商网站,我们要完成PC端首页、列表页、注册页面的制作 1.3 品优购项目的学习目的 电商类网站比较综合,里面需要大量的布局技术,包括布局方式、…

数据结构-复杂度(深入学习版+Java版)

文章目录一、复杂度经典例子分析1、计算时间复杂度分析题1&#xff1a;O(NM)&#xff0c;循环题2&#xff1a;O(N^2)&#xff0c;冒泡排序题3&#xff1a;O(logN)&#xff0c;二分查找题4&#xff1a;O(N)&#xff0c;阶乘递归题5&#xff1a;O(2^N)&#xff0c;斐波那契递归(满…

ffmpeg、ffplay、ffprobe 常用命令详解(音视频必备)

前言&#xff1a; &#x1f604;作者简介&#xff1a;小曾同学.com,小伙伴们也可以叫我小曾&#xff0c;一个致力于测试开发的博主⛽️ 如果文章知识点有错误的地方&#xff0c;还请大家指正&#xff0c;让我们一起学习&#xff0c;一起进步。&#x1f60a; 座右铭&#xff1a;…

回溯算法 - 二叉树中和为某一值的路径 字符串的排列

目录 1.二叉树中和为某一值的路径 1.1 题目描述 1.2 回溯算法的一般步骤 1.3 解题思路 1.4 代码实现 2. 字符串的排列 2.1 题目描述 2.2 解题思路 2.3 代码实现 1.二叉树中和为某一值的路径 1.1 题目描述 输入一颗二叉树的根节点root和一个整数expectNumber&#xff…

华为模拟器ensp学习笔记

CSDN话题挑战赛第2期 参赛话题&#xff1a;学习笔记 目录前言1️⃣如何注册eNSP设备?2️⃣如何通过SecureCRT登录eNSP模拟设备&#xff1f;结语前言 记录华为模拟器使用中遇到的问题 1️⃣如何注册eNSP设备? 如何注册eNSP设备 重新注册AR、WLAN设备&#xff1a; 启动AR时&…

模块化:CommonJS规范

目录 CommonJS规范 模块使用环境区分 核心语法 如何使用 CommonJS&#xff1a;服务器端使用 CommonJS&#xff1a;浏览器端使用 CommonJS规范 模块使用环境区分 CommonJS规范中&#xff0c;每一个JS文件都可以作为一个模块。模块的引入&#xff0c;主要区分两个环境&…

基于Java后台(Springboot框架)+前端小程序(MINA框架)+Mysql数据库的医院预约挂号小程序系统设计与实现

项目背景和意义 目的&#xff1a;本课题主要目标是设计并能够实现一个基于微信小程序医院预约挂号系统&#xff0c;前台用户使用小程序&#xff0c;后台管理使用基JavaMySql技术&#xff1b;通过后台设置医院信息、录入医院科室信息、录入医生信息、设置医生排班信息、查看预约…