网络对战五子棋(web-gobang)项目

这是一个使用C++在Linux环境下开发的网络对战五子棋项目,支持用户登录注册、在线匹配、游戏重开等功能。采用多线程、互斥锁、条件变量等技术实现,利用MySQL存储数据。游戏状态通过AJAX异步请求实时同步,数据以JSON格式交互。项目结构清晰,包含HTTP模块、用户管理、房间管理等多个模块。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.开发背景

  五子棋是一种传统的棋种,它不仅容易上手,老少皆宜,而且趣味横生,引人入胜:它不仅能增强思维能力,提高智力,而且富含哲理,有助于修身养性。为了将自己所学到的知识更系统地用起来,也为了检测自己对Linux相关知识的掌握情况,所以这款网络对战五子棋项目就诞生了~~

2.项目功能&&效果展示

① 支持用户登陆、注册功能
② 支持用户在线匹配功能
③ 游戏结束后,支持重新匹配功能
④将对局信息持久化存储在数据库中

用户登录界面:
在这里插入图片描述
用户注册界面:
在这里插入图片描述
游戏界面:
在这里插入图片描述
对局情况:
在这里插入图片描述

3.开发环境&&主要技术

开发环境

① Linux平台
② gcc/g++:7.3.1版本
③ C++语言
④ MySQL数据库

主要技术

① 多线程
② 互斥锁
③ 条件变量
④ JSON
⑤ AJAX异步请求
⑥ MySQL数据库

4.项目模块&&设计思路

  • HTTP模块:用来接收来自网络的请求,使用到开源库 httplib
  • 用户管理模块:① 管理用户信息② 用户信息持久化(room_player.hpp
  • 房间管理模块:针对两个匹配用户创建房间,保存游戏属性(room_player.hpp
  • 会话模块:针对登录用户创建唯一的会话ID,通过Cookie返回给浏览器(session.hpp
  • 数据库管理模块database.hpp
  • 工具模块tools.hpp
  • 项目驱动模块webgobang.hpp、webgobang.cpp

设计思路:

此项目大体的数据流向是前端通过AJAX请求将JSON格式的数据传送到后端,后端通过httplib库中的方法获取到前端当中的JSON数据,然后对该数据进行相应操作后,将结果返回给前端,前端根据返回的结果,走相应的逻辑,并向用户反馈一个结果

项目架构图:
在这里插入图片描述

5.项目主要功能实现

5.1 登陆注册

  用户点击登录按钮后,前端会对用户输入的邮箱和密码进行获取,将数据转为JSON格式(序列化),并通过AJAX,采用POST的http请求方法将该数据发送到后端去,后端校验该数据之后,将其持久化到数据库中,并且根据输入的邮箱和密码生成相应的MD5码作为当前用户的cookie信息返回回去。当前端接收到http服务端的响应后,会回调success:function(data)函数,做出相应的操作;
在这里插入图片描述
在这里插入图片描述

后端代码如下:

http_svr_.Post("/login", [this](const Request& res, Response& resp){
   
                    //1.校验用户提交的账号和密码(同数据库当中的数据进行校验)
                   Json::Reader r;
                   Json::Value v;
                   r.parse(res.body, v);
                   //将请求正文中的内容反序列化
                   cout << res.body << endl;

                    //在数据库中校验邮箱、密码,若正确返回用户id
                   int user_id = this->db_svr_->QueryUserExist(v);
                   //2.组织http响应进行回复(json)
                   string tmp = "";
                   if(user_id > 0)
                   {
   
                        Session sess(v, user_id);
                        string session_id = sess.GetSessionId();
                        //回复的会话格式 JSESSIONID=xxxxx
                        tmp = "JSESSIONID=" + session_id;
                        all_sess_->SetSessionInfo(session_id, sess);

                        //放到用户管理类当中, 进行管理
                        //当用户登录之后, 将登录的用户保存在map当中
                        this->pm_->InsertPlayer2Map(user_id);
                   }

                   Json::Value resp_json;
                   resp_json["status"] = user_id <= 0 ? false:true;
                   //将该Json-Value对象序列化 并进行响应
                   resp.body = this->Serializa(resp_json);
                   resp.set_header("Set-Cookie", tmp.c_str());
                   resp.set_header("Content-Type", "application/json");
            });

注册逻辑与登录逻辑类似,此处不再详解

5.2 匹配功能

此游戏玩家一共有三个状态在线状态(ONLINE)、匹配状态(MATCH)、游戏状态(PLAYING),当玩家登录上来后会将用户的状态改为在线状态,当玩家点击开始匹配按钮时,玩家状态会变为MATCHING,并且将其加入匹配池(vector) 当中,唤醒匹配线程进行匹配,如果匹配池中匹配玩家数量 < 2,则匹配线程(从匹配池中获取玩家进行匹配的线程) 不进行匹配,如果匹配池中匹配玩家数量为奇数,则匹配池中最后一个玩家不进行匹配,等待下一次匹配,其余玩家两两配对。
在这里插入图片描述
匹配池:使用vector用来存放MATCH状态的玩家
匹配线程:从匹配池中获取到两个玩家信息后,为这两名玩家创建一个房间,并将这两名玩家的状态变为PALYING状态,为其分配创建出的房间号和对应所执的黑棋/白棋。

将玩家放入匹配池代码如下:

        int PushPlayer2MatchPool(int user_id)
        {
   
            //1.设置用户的状态为MATCHING状态
            pm_->SetUserStatus(user_id, MATCHING);
            //2.放到匹配池当中
            pthread_mutex_lock(&vec_lock_);
            match_pool_.push_back(user_id);
            match_pool_num_++;
            printf("match_pool_num_: %d\n", match_pool_num_);
            pthread_mutex_unlock(&vec_lock_);

            //通知匹配线程工作
            pthread_cond_broadcast(&vec_cond_);
            return 0;
        }

匹配线程代码如下:

        static void* MatchServer(void* arg)
        {
   
            pthread_detach(pthread_self());
            WebGobang* wg = (WebGobang*)arg;

            while(1)
            {
   
                pthread_mutex_lock(&wg->vec_lock_);
                while(wg->match_pool_num_ < 2)
                {
   
                    pthread_cond_wait(&wg->vec_cond_, &wg->vec_lock_);
                    printf("i am MatchServer, i working\n");
                }

                //匹配池当中的人数一定为大于等于2
                //  奇数: 一定由一个玩家要轮空
                //  偶数:两两进行匹配
                int last_id = -1;
                auto& vec 
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值