C++项目:在线五子棋对战(网页版)

项目介绍

本项⽬主要实现⼀个⽹⻚版的五⼦棋对战游戏,其主要⽀持以下核⼼功能:

• 用户管理:实现用户注册,用户登录、获取用户信息、用户天梯分数记录、用户比赛场次记录等。
• 匹配对战:实现两个玩家在网页端根据天梯分数匹配游戏对⼿,并进行五子棋游戏对战的功能。
• 聊天功能:实现两个玩家在下棋的同时可以进⾏实时聊天的功能。

程序截图

开发环境

• Linux (Centos-7.6)

• VSCode/Vim
• g++/gdb
• Makefile

核心技术

• HTTP/WebSocket
• Websocket++
• JsonCpp
• Mysql
• C++11
• BlockQueue
• HTML/CSS/JS/AJAX

项目大流程

• 环境搭建(在Linux环境下安装需要用到的的工具以及第三方库)

• 框架设计

• 前置知识的了解

• 模块开发

配置开发环境

项目框架

项目期望:用户访问服务器获取注册页面,通过注册页面注册账号,注册成功后在登录页面进行登录。登录成功后进入游戏大厅,在游戏大厅中进行匹配对战,匹配成功,将进入游戏房间内与对手进行实时对战和实时聊天。

用户访问服务器获取的注册页面、登录页面、游戏大厅页面和游戏房间页面,属于静态资源请求。进行注册请求、登录请求、进入游戏大厅后展示个人信息的个人信息请求、匹配对战请求和下棋聊天请求属于动态功能请求。

服务器流程图:

模块解析

在项目中,需要用到6个模块,分别是:

数据管理模块:基于mysql数据库进行数据管理以及封装数据管理模块实现数据库访问。

在数据管理模块中,需要实现的功能有:注册新用户功能、登录验证功能、通过用户名获取用户信息功能、通过用户id获取用户信息功能,以及对战胜利和失败后,对数据的更新功能。

网络服务器模块:基于websocketpp库搭建websocket服务器,实现与客户端网络通信。

早网络服务器模块中,websocketpp支持http协议和websocket协议,需要实现的是http请求处理回调函数和websocket请求处理回调函数。其中,HTTP请求的处理回调函数包含了静态资源请求处理、用户注册请求处理、用户登录请求处理和用户信息请求处理。websocket请求处理回调函数包含游戏大厅、游戏房间等长连接的请求处理。

session管理模块:封装session管理,实现http客户端通信状态的维护及身份识别。

session管理模块是用于在浏览器中保存用户的通信状态和身份识别的,当用户在注册或登录后,进入了游戏大厅或游戏房间,那么将会永久保存其Cookie,当用户断开连接后,在一定的时间内,他的Cookie就会被销毁,在登录时需要重新输入账号密码。

在线用户管理模块:对于进入游戏大厅&游戏房间的长连接通信进行管理,实现随时能够获取客户端连接进行消息的主动推送。

在线用户管理模块的作用是将用户id与游戏大厅或游戏房间连接起来,在建立了websocket长连接后,将玩家加入到游戏大厅或游戏房间。当游戏结束,将玩家从游戏房间移除,当玩家退出客户端后,websocket连接断开,将玩家从游戏大厅移除。除此之外,还需要实现判断用户是否在线,即在游戏大厅中或游戏房间中,还需要通过玩家用户id去获取游戏大厅/游戏房间管理对应的通信连接。

游戏房间管理:对于同一个房间中的用户及动作进行处理(对战匹配,下棋,聊天,退出)。

在游戏房间中,游戏房间包含了房间id,玩家数量,房间状态、黑棋白棋玩家的id,以及棋盘,在线用户管理和数据模块管理的指针等字段。在游戏房间中,需要实现的是下棋的动作、处理下棋动作、处理聊天动作和处理玩家退出房间的动作,以及将动作处理广播给房间的所有玩家的方法。

游戏房间管理是需要实现的是对房间的管理,因此需要一个房间的计数器、需要实现的是创建一个游戏房间,通过房间id获取房间信息,通过用户id获取所在的房间的信息,删除房间等方法。

对战匹配管理:将所有玩家根据分数进行等级划分,进行不同等级的对战匹配。

匹配对战分有三个段位:普通、高手和大神三种段位,分别使用三个匹配队列进行玩家的匹配队列的进入等待,并且使用三个线程,异步高效地处理三种玩家的匹配对战。

对于匹配队列来说,不是使用队列,而是使用双向链表来作为匹配队列。匹配队列需要的功能是:出队入队、阻塞线程、移除指定元素等功能。

对于匹配队列的管理,需要实现将玩家进行入队,出队等操作。

将6个模块整合起来,在服务器中进行业务处理:通过网络通信获取到客户端的请求,提供不同的业务处理。

前置知识的学习:

1.websocketpp的学习和使用。

本项目中,使用websocketpp来搭建服务器,因为websocketpp同时支持http和websocket。在本项目中,HTTP用于注册、登录等服务请求中提供短链接服务。而websocket用于在游戏大厅或游戏房间中,提供长连接,并且服务器主动发送消息给客户端的服务。下面链接是关于websocket的介绍以及使用websocketpp搭建简单服务器的框架:

websocket协议

我在做项目时的难点:①HTTP请求响应和websocket请求响应的区别。②服务器搭建流程。③为什么连接句柄是使用lib::weak_ptr管理起来,而不是使用lib::shared_ptr来管理。

解决:

①TTP请求响应和websocket请求响应的区别:

HTTP请求回调处理函数主要是处理来自客户端的HTTP请求,它从连接对象中获取HTTP请求的正文,并通过请求对象获取URI和方法等信息,然后根据不同的方法和URI来进行相应的处理,最后构建HTTP响应对象并发送回客户端。HTTP是一种无状态协议,每个请求都是独立的。

WebSocket消息处理回调函数主要是处理来自客户端的WebSocket消息,它从连接对象中获取WebSocket消息的内容,并进行相应的处理逻辑。不像HTTP请求那样需要获取URI和方法等信息,WebSocket是一种双向通信协议,服务器和客户端可以在持久连接上进行实时双向通信。这个回调函数通过使用连接对象的 send 方法直接将响应消息发送回客户端。

服务器搭建流程:先实例化出websocketpp的server类对象,通过server类对象设置日志等级、调度器、四种处理回调函数、进入监听状态、获取客户端新连接,最后启动服务器。

③为什么连接句柄是使用lib::weak_ptr管理起来,而不是使用lib::shared_ptr来管理。

hdl是wssrv.start_accept()创建出来的连接对象的引用,他们两者会有互相引用的关系,如果使用了lib::weak_ptr来管理hdl,就不会发生内存泄漏。

MySQLClient库

JsonCpp

模块开发

数据库代码

数据库设计这边,玩家的信息包含了玩家的用户id、用户名、用户密码、天梯分数、排位总场次和胜场总场次。其中,用户id作为主键,并且是自增长的,而用户名和用户密码不能为空,且用户名唯一。根据这个需求,写出以下代码:

drop database if exists online_gobang;
create database if not exists online_gobang;
use online_gobang;
create table if not exists user(id int primary key auto_increment comment '用户id',username varchar(32) unique key not null comment '用户名',password varchar(128) not null comment '用户密码',score int comment '分数',total_count int comment '总场次',win_count int comment '胜利场次'
);

日志打印

#ifndef _M_LOGGER_H_
#define _M_LOGGER_H_
#include<stdio.h>
#include<time.h>//正常
#define INF 0
//调试信息
#define DBG 1
//错误信息
#define ERR 2//strftime:将时间转换为指定格式的字符串
#define LOG(level,format,...) do{\time_t t = time(NULL);\struct tm *lt = localtime(&t);\char buf[32];\strftime(buf,21,"%H:%M:%S",lt);\fprintf(stdout,"[%s %s:%d] " format "\n",buf,__FILE__,__LINE__,##__VA_ARGS__);\
}while(0)#define ILOG(format,...) LOG(INF,format,##__VA_ARGS__);
#define DLOG(format,...) LOG(DBG,format,##__VA_ARGS__);
#define ELOG(format,...) LOG(ERR,format,##__VA_ARGS__);

工具类模块开发

工具类模块开发代码

数据管理模块开发

数据管理模块开发代码

在测试代码的时候,发现插入的数据长度太长,也就是密码在被加密之后,长度超过了我原本设置的password varchar(32)。因此,我需要将其改成varchar(128),并且重新导入:

[wjmhlh@VM-12-9-centos myspace]$ mysql -uroot -p < online_gobang.sql   --重新导入
Enter password: 
[wjmhlh@VM-12-9-centos myspace]$ mysql -uroot -p
Enter password: Database changed
mysql> desc user;
+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| id          | int(11)      | NO   | PRI | NULL    | auto_increment |
| username    | varchar(32)  | NO   | UNI | NULL    |                |
| password    | varchar(128) | NO   |     | NULL    |                |
| score       | int(11)      | YES  |     | NULL    |                |
| total_count | int(11)      | YES  |     | NULL    |                |
| win_count   | int(11)      | YES  |     | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)mysql> select * from user;
+----+----------+-------------------------------------------+-------+-------------+-----------+
| id | username | password                                  | score | total_count | win_count |
+----+----------+-------------------------------------------+-------+-------------+-----------+
|  1 | xiaoming | *E56A114692FE0DE073F9A1DD68A00EEB9703F3F1 |  1000 |           0 |         0 |
+----+----------+-------------------------------------------+-------+-------------+-----------+
1 row in set (0.00 sec)

在线用户管理模块开发

在线用户管理模块开发代码

在实现代码中,需要注意的是,当websocket的长连接断开后,我在移除游戏大厅或游戏房间的在线用户管理的uid时,而由于是使用unordered_map作为容器,因此与之对应的通信连接conn就会失去一个映射关系,而通信连接使用了uinque_ptr进行管理,计数器直接减为0,这个通信连接就会自动销毁。

房间管理模块开发

房间管理模块开发代码

session管理模块开发

session管理模块开发

游戏对战匹配模块开发

匹配对战模块开发代码

服务器网络通信模块开发

服务器网络通信模块开发​​​​​​​

项目总结

1. 为什么做这个项目

为什么做这个C++五子棋对战网页版的项目,我总结了三点:

①我学习了网络编程,比如HTTP、socket编程等,还没有通过项目实践过,开发经验不足,因此我需要做一个关于网络通信连接的项目来加深我对网络编程的理解和使用。

②我是学习C++的一名计算机专业的学生,对自己掌握的C++的程度,需要有项目的实践操作去检验自己的学习成果。

③在之前学习计算机技术,实践都是通过从一些做题网站中,去做题目来检验自己对知识的掌握,以及写代码的能力,但是却没有过去写一个项目来检验自己的代码逻辑和写代码的能力的,而这个项目的开发,能够很好地检验我自己的代码逻辑和写代码的能力。


2. 项目中都用到了那些技术

在项目中,主要运用到了websocket协议和HTTP协议,以及C++11中的一些新特性,比如包装器,bing方法,互斥锁、智能指针等等,还有就是使用到了STL,比如vector、list、unordered_map等,以及是g++/gcc,makefile,vim/vscode等。


3. 讲一下项目都有那些功能,大概是怎么实现的

在线五子棋对战网页版,主要的功能有:让用户通过浏览器访问服务器,从而实现用户注册,用户登录,对战匹配,实时对战和实时聊天功能。

实现的大概思路是:

实现了6个模块,第一个模块是数据管理模块,这个模块是基于MySQL数据库进行数据管理,并且封装了MySQL的C语言接口,来进行数据管理。第二个模块是在线用户管理模块,这个模块对于进入了的游戏大厅和游戏房间的长连接通信进行管理,通过用户的uid与相对于的客户端的通信连接建立起映射关系,服务器可以实现随时获取客户端通信连接进行消息的主动推送。第三个模块是房间管理模块,在这个模块里面,先是实现了房间类,在房间类中,实现了下棋、聊天等动作,而再实现了一个房间管理的类,通过房间的管理,可以进行房间的创建、销毁、通过用户的id获取房间信息,通过房间id获取房间信息等功能。第四个模块是session模块,这个模块封装了session的管理,实现了HTTP通信连接中客户端通信状态的维护和登录或进入游戏大厅或游戏房间时进行身份识别。第五个模块是游戏对战匹配模块,在这个模块里面是将所有玩家根据分数吗,进行了档次的划分,使用多线程,分别对同档次的玩家进行不同的对战匹配。第六个模块是网络服务器的模块开发,在这个模块里面,是基于了websocketpp来搭建了服务器,实现了与客户端进行通信的功能。


4. 做的时候遇到过什么问题,当时是怎么想的,最后是怎么解决的

在做项目的过程中,遇到了不少的技术问题。

①比如在使用websocketpp协议的时候,一开始的时候没有掌握好HTTP协议和websocket协议的使用,比如说在接受请求和发送响应,它们是有区别的。一开始以为在响应的时候,需要获取uri和方法,然后根据uri和方法将那些响应的。然后当时在网上查了文档,别人写的文章,还问了一些类似chargpt的ai,最后才发现,原来websocket不需要获取请求中的uri,可以直接通过send方法给客户端做出响应。

②一开始在设计user表的时候,我把密码的长度设置了32个字符长度。开始的时候,我给用户注册密码都是6位,我没弄清楚为什么在报错的时候,提示我是密码长度超出了设置的长度。于是我在MySQL的客户端上,重新查看了describe user命令查看了表结构,发现是32位,然后我于是通过SHOW VARIABLES LIKE 'validate_password%'命令,去查看密码等级的设置,并没有出现设置不匹配的原因,后来我查了很多资料,问了老师,才知道,是在密码加密之后,密码长度会变长,于是我就设置成128位。


5. 项目中最难的一个知识点

我认为,在这个项目中最难的一个知识点是对于如何去使用websocketpp去搭建服务器这个点上。因为在做这个项目之前,我都只用过HTTP去做过一个简单的服务器,没有拓展到去学习websocket协议,从而使用websocket去搭建一个拥有HTTP协议和websocket协议的服务器。


6. 有想过怎么扩展吗

想过给下棋玩家设置一个时间限制,在规定时间内没有下棋动作,那么就直接轮到对方下棋。

还有就是增加一个AI选手,可以让玩家与AI进行对战。

项目整体代码链接

代码链接

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

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

相关文章

Java版企业电子招标采购系统源码Spring Cloud + Spring Boot +二次开发+ MybatisPlus + Redis tbms

​ 功能描述 1、门户管理&#xff1a;所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含&#xff1a;招标公告、非招标公告、系统通知、政策法规。 2、立项管理&#xff1a;企业用户可对需要采购的项目进行立项申请&#xff0c;并提交审批&#xff0c;查…

HarmonyOS应用开发者基础认证考试题库

此博文为HarmonyOS应用开发者基础认证考试的最后的大考&#xff0c;要求100分取得90分方可获取证书、现将考试的题库进行分享&#xff0c;希望能帮到大家。但是需要注意的是&#xff0c;题库会不定时的进行题目删减&#xff0c;但是大概的内容是不会进行改变的。真心希望这篇博…

第126天:内网安全-隧道技术SSHDNSICMPSMB上线通讯LinuxMac

知识点 #知识点&#xff1a; 1、入站规则不出网上线方案 2、出站规则不出网上线方案 3、隧道技术-SMB&ICMP&DNS&SSH 4、控制上线-Linux&Mac&IOS&Android-连接方向&#xff1a;正向&反向&#xff08;基础课程有讲过&#xff09; -内网穿透&#xf…

centos linux 安装RDMA Soft-RoCE|虚拟机安装Soft-RoCE

什么是Soft-RoCE softRoCE的目标是在所有支持以太网的设备上都可以部署RDMA传输&#xff0c;可以使不具备RoCE能力的硬件和支持RoCE的硬件间进行基于IB语义的交流。 大白话就是模拟RDMA的软件栈&#xff0c;使得在没有RDMA网卡的环境上&#xff0c;也可以运行基于RDMA写的传输…

leetcode870. 优势洗牌(java)

优势洗牌 leetcode870. 优势洗牌题目描述双指针 排序代码 滑动窗口 leetcode870. 优势洗牌 难度 - 中等 leetcode870. 优势洗牌 题目描述 给定两个长度相等的数组 nums1 和 nums2&#xff0c;nums1 相对于 nums2 的优势可以用满足 nums1[i] > nums2[i] 的索引 i 的数目来描…

博客网站添加复制转载提醒弹窗Html代码

网站如果是完全禁止右键&#xff08;复制、另存为等&#xff09;操作&#xff0c;对用户来说体验感会降低&#xff0c;但是又不希望自己的原创内容直接被copy&#xff0c;今天飞飞和你们分享几行复制转载提醒弹窗Html代码。 效果展示&#xff1a; 复制以下代码&#xff0c;将其…

matplotlib 笔记:基本用法

1 axis 1.0 对比原始图像 import numpy as np import matplotlib.pyplot as plt xrange(5) yrange(10,20,2) plt.plot(x,y) 1.1 plt.axis(equal) x轴和y轴单位长度相同 import numpy as np import matplotlib.pyplot as plt plt.axis(equal) xrange(5) yrange(10,20,2) pl…

【iOS】autoreleasepool

来说一下最近在了解的autoreleasepool吧&#xff0c;我们可能平时书写过许多脑残代码&#xff0c;其有很多的缺陷但是我们可能当时学的比较浅就也不太了解&#xff0c;就像下面这样的&#xff1a; for (int i 0; i < 1000000; i) {NSNumber *num [NSNumber numberWithInt…

SAP MIGO 移动原因维护

在OMJJ中维护 在OMJJ中&#xff0c;选择你要维护的移动类型&#xff0c;在“对话结构”中选择“移动原因”&#xff0c;可以修改和添加了。

Java用方法实现登录名和密码的校验

Java用方法实现登录名和密码的校验 需求分析代码实现小结Time 需求分析 系统正确的登录名和密码是:学习/123&#xff0c;请在控制台开发一个登录界面&#xff0c;接收用户输入的登录名和密码&#xff0c;判断用户是否登录成功&#xff0c;登录成功后展示:“欢迎进入系统!”&…

C# OpenCvSharp 去水印 图像修复

效果 项目 VS2022.net4.8OpenCvSharp4 代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; usi…

Improved Deep Metric Learning with Multi-class N-pair Loss Objective

Improved Deep Metric Learning with Multi-class N-pair Loss Objective 来源&#xff1a; NIPS’2016NEC Laboratories America 文章目录 Improved Deep Metric Learning with Multi-class N-pair Loss ObjectiveDistance Metric LearningDeep Metric Learning with Multip…

时间复杂度空间复杂度相关练习题

1.消失的数字 【题目】&#xff1a;题目链接 思路1&#xff1a;排序——》qsort快排——》时间复杂度O&#xff08;n*log2n&#xff09; 不符合要求 思路2&#xff1a;&#xff08;0123...n)-(a[0]a[1][2]...a[n-2]) ——》 时间复杂度O&#xff08;N&#xff09;空间复杂度…

spring cloud智慧工地源码(项目端+监管端+数据大屏+APP)

spring cloud智慧工地源码&#xff08;项目端监管端数据大屏APP&#xff09; 系统功能介绍 【智慧工地PC项目端功能总览】 一.项目人员管理 包括&#xff1a;信息管理、信息采集、证件管理、考勤管理、考勤明细、工资管理、现场统计、WIFI教育、工种管理、分包商管理、班组管…

STM32 HAL 驱动PM2.5传感器(GP2Y10AU气体检测模块)

目录 1、简介 2、CubeMX初始化配置 2.1 基础配置 2.1.1 SYS配置 2.1.2 RCC配置 2.2 ADC外设配置 2.3 串口外设配置 2.4 项目生成 3、KEIL端程序整合 3.1 串口重映射 3.2 ADC数据采集 3.3 主函数代 3.4 效果展示 1、简介 本文通过STM32F103C8T6单片机通过HAL库方式对G…

Qt 使用QLabel的派生类实现QLabel的双击响应

1 介绍 在QLabel中没有双击等事件响应&#xff0c;需要构建其派生类&#xff0c;自定义信号(signals)、重载事件函数(event)&#xff0c;最后在Qwidget中使用connect链接即可&#xff0c;进而实现响应功能。 对于其余没有需求事件响应的QObject同样适用。 此外&#xff0c;该功…

利用appium抓取app中的信息

一、appium简介 二、appium环境安装 三、联调测试环境 四、利用appium自动控制移动设备并提取数据

年轻代频繁GC ParNew导致http变慢

背景介绍 某日下午大约四点多&#xff0c;接到合作方消息&#xff0c;线上环境&#xff0c;我这边维护的某http服务突然大量超时&#xff08;对方超时时间设置为300ms&#xff09;&#xff0c;我迅速到鹰眼平台开启采样&#xff0c;发现该服务平均QPS到了120左右&#xff0c;平…

希尔排序——C语言andPython

前言 步骤 代码 C语言 Python 总结 前言 希尔排序&#xff08;Shell Sort&#xff09;是一种改进的插入排序算法&#xff0c;它通过将数组分成多个子序列进行排序&#xff0c;逐步减小子序列的长度&#xff0c;最终完成整个数组的排序。希尔排序的核心思想是通过排序较远距…

SQL server 异地备份数据库

异地备份数据库 1.备份服务器中设置共享文件夹 2.源服务器数据库中添加异地备份代理作业 EXEC sp_configure show advanced options, 1;RECONFIGURE; EXEC sp_configure xp_cmdshell, 1;RECONFIGURE; declare machine nvarchar(50) 192.168.11.10 --服务器IP declare pa…