C++项目:在线五子棋对战网页版--数据模块开发

这篇具有很好参考价值的文章主要介绍了C++项目:在线五子棋对战网页版--数据模块开发。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

数据模块开发设计 

数据管理模块,基于mysql数据库进行数据管理以及封装数据管理模块实现数据库访问。因此,在数据库中,我需要为每一张表创建出对应类,通过类实例化的对象来访问这张数据库表中的数
据,这样的话当我们要访问哪张表的时候,使⽤哪个类实例化的对象即可。

那么在五子棋对战项目当中,数据库表只有一张user表,因此我只需要为user表创建一个类即可。

在user类中,该类的作用是通过数据库接口去管理用户数据,因此需要实现的方法:

select_by_name:根据用户名查找用户信息,用于实现登录功能

select_by_id:根据用户id查找用户信息

loser:给失败玩家修改分数

win:给胜利玩家修改分数

insert:注册用户时将用户数据插入到数据库智能

login:登录验证,获取完整的用户信息

接下来是代码的实现

成员变量

由于是对数据库进行操作,因此需要用到MySQL的操作句柄,而且在进行对数据库数据操作的时候,需要添加互斥锁,因此需要用到mutex。

因此,成员变量为MySQL操作句柄以及互斥锁。

class user_table
{
private:
    MYSQL* _mysql;//MySQL数据库操作句柄
    std::mutex _mutex;//互斥锁
public:
        /*.....*/
};

成员函数

成员函数即上述所说的六个方法,以及构造方法和析构方法。

    /*通过用户名获取用户信息*/
    /*返回值为bool,判断是否成功获取,参数username为用户名,输出型参数user用于保存获取到的用户数据*/
    bool select_by_name(const std::string& username,Json::Value& user);

    /*通过用户id获取用户信息*/
    /*返回值为bool,判断是否成功获取,参数id为用户id,输出型参数user用于保存获取到的用户数据*/
    bool select_by_id(uint16_t id,Json::Value& user);

    /*insert:用户注册时,将用户的数据插入到表中,即可注册成功*/
    bool insert(Json::Value& user);

    /*登录验证,并获取用户信息*/
    bool login(Json::Value& user);

    /*胜利时修改分数,传入胜利玩家的id,通过id查找出对应的数据并进行修改*/
    bool win(uint16_t id);

    /*失败时修改分数,传入失败玩家的id,通过id查找出对应的数据并进行修改*/
    bool loser(uint16_t id);

代码实现

①构造方法

我首先需要获取MySQL数据库的操作句柄,并且连接到MySQL的服务器中,将MySQL数据库的字符集设置成utf8,因此,在构造方法中,参数有MySQL数据库服务器的地址host、MySQL数据库的用户名、密码、数据库名称、端口号。

    user_table(
            const std::string& host,
            const std::string& username,
            const std::string& password,
            const std::string& dbname,
            uint16_t port = 3306)
    {
        _mysql = mysql_util::mysql_create(host,username,password,dbname,port);
        assert(_mysql!=nullptr);
    }

②析构方法

调用销毁句柄的方法即可;

    ~user_table()
    {
        mysql_util::mysql_destory(_mysql);
        _mysql==nullptr;
    }

③通过用户名获取用户信息的方法

返回值为bool,判断是否成功获取,参数username为用户名,输出型参数user用于保存获取到的用户数据。

流程:

1.先定义出MySQL的查询语句的字符串,将其保存到字符数组sql中。

2.我们需要对操作进行互斥锁,保护起来,以免其它线程进行了数据的修改。因此,划出一段空间出来,形成互斥锁的生命周期。

3.进行语句查询,查询后,获取结果集保存到本地,如果获取失败,则说明没有该用户,如果有,那么往下走。

4.获取结果集的行数,然后遍历结果集,将该用户的数据填入user中,返回回去。

5.最后释放结果集。

bool select_by_name(const std::string& username,Json::Value& user)
    {
        #define USER_BY_NAME "select id,score,total_count,win_count from user where username='%s';"
        char sql[4096]={0};
        sprintf(sql,USER_BY_NAME,username.c_str());/*将查询表的字符串写入到sql中*/
        /*MYSQL_RES保存查询结果到本地:mysql_store_resul(_mysql)*/
        MYSQL_RES* res=NULL;
        /*查询操作需要使用互斥锁进行保护*/
        {
            std::unique_lock<std::mutex> lock(_mutex);
            bool ret = mysql_util::mysql_exec(_mysql,sql);//执行查询语句
            if(ret==false)
            {
                DLOG("user select_by_name failed!!\n");
                return false;
            }
            //查询成功,将查询结果保存到本地
            res = mysql_store_result(_mysql);
            if(res==NULL)
            {
                DLOG("have no user info!!");
                return false;
            }

        }
        /*保存到本地之后,需要将结果放入到Json::Value user中
        因此,先获取到结果集的行数,然后遍历结果集,将其放入user中*/
        /*获取结果集的行数*/
        int row_num = mysql_num_rows(res);
        if(row_num!=1)
        {
            DLOG("the user information queried is not unique!");
            return false;
        }
        /*遍历结果集,将数据存储在user中,row是列数噢,row[0]为第0列*/
        MYSQL_ROW row = mysql_fetch_row(res);
        user["id"] = (Json::UInt64)std::stol(row[0]);/*先转化成长整型,然后转化成json形式的无符号整型*/
        user["username"] = username;
        user["score"] = (Json::UInt64)std::stol(row[1]);
        user["total_count"] = std::stoi(row[2]);
        user["win_count"] = std::stoi(row[3]);
        mysql_free_result(res);
        return true;
    }

④通过用户id获取用户信息

返回值为bool,判断是否成功获取,参数id为用户id,输出型参数user用于保存获取到的用户数据。

流程:

1.先定义出MySQL的查询语句的字符串,将其保存到字符数组sql中。

2.我们需要对操作进行互斥锁,保护起来,以免其它线程进行了数据的修改。因此,划出一段空间出来,形成互斥锁的生命周期。

3.进行语句查询,查询后,获取结果集保存到本地,如果获取失败,则说明没有该用户,如果有,那么往下走。

4.获取结果集的行数,然后遍历结果集,将该用户的数据填入user中,返回回去。

5.最后释放结果集。

bool select_by_id(uint16_t id,Json::Value& user)
    {
        #define USER_BY_ID "select username,score,total_count,win_count from user where id='%d';"
        char sql[4096]={0};
        sprintf(sql,USER_BY_ID,id);/*将查询表的字符串写入到sql中*/
        /*MYSQL_RES保存查询结果到本地:mysql_store_resul(_mysql)*/
        MYSQL_RES *res=NULL;
        /*查询操作需要使用互斥锁进行保护*/
        {
            std::unique_lock<std::mutex> lock(_mutex);
            bool ret = mysql_util::mysql_exec(_mysql,sql);//执行查询语句
            if(ret==false)
            {
                DLOG("user select_by_name failed!!\n");
                return false;
            }
            //查询成功,将查询结果保存到本地
            res = mysql_store_result(_mysql);
            if(res==NULL)
            {
                DLOG("have no user info!!");
                return false;
            }

        }
        /*保存到本地之后,需要将结果放入到Json::Value user中
        因此,先获取到结果集的行数,然后遍历结果集,将其放入user中*/
        /*获取结果集的行数*/
        int row_num = mysql_num_rows(res);
        if(row_num!=1)
        {
            DLOG("the user information queried is not unique!");
            return false;
        }
        /*遍历结果集,将数据存储在user中,row是列数噢,row[0]为第0列*/
        MYSQL_ROW row = mysql_fetch_row(res);
        user["id"] = (Json::UInt64)id;;/*化成json形式的无符号整型*/
        user["username"] = row[0];
        user["score"] = (Json::UInt64)std::stol(row[1]);
        user["total_count"] = std::stoi(row[2]);
        user["win_count"] = std::stoi(row[3]);
        mysql_free_result(res);
        return true;
    }

⑤用户注册方法

用户注册,即将用户名和用户的密码插入到数据库中,如果插入成功,即注册成功。在密码插入这一块,需要对密码进行加密。

流程:

1.首先判断传进来的用户的数据是否完整。

2.定义出MySQL的插入语句的字符串。

3.然后将字符串保存到字符数组中

4.然后上锁,接着执行插入语句。

5.成功插入,则注册成功。

bool insert(Json::Value& user)
    {
        #define INSERT_USER "insert user values(null,'%s',password('%s'),1000,0,0);"
        /*判断user中的用户数据是否完整*/
        if(user["username"].isNull() || user["password"].isNull())
        {
            DLOG("INPUT PASSWORD OR USERNAME");
            return false;
        }
        /*数据完整,可以进行注册*/
        char sql[4096]={0};
        /*将执行语句的字符串形式放入到sql中*/
        sprintf(sql,INSERT_USER,user["username"].asCString(),user["password"].asCString());
        bool ret = mysql_util::mysql_exec(_mysql,sql);/*执行*/
        if(ret==false)
        {
            ELOG("insert user info failed!!\n");
            return false;
        }
        return true;
    }

⑥登录验证方法

流程:

1.首先对传过来的用户数据进行验证,是否具有完整性,不能缺失用户名和密码。

2.接着定义出MySQL的查询语句,目的是,通过查询语句,去查询是否能够通过该用户名和密码查询出结果,而且结果只能由一条。

3.定义出MySQL的查询语句的字符串之后,将其存储在字符数组中。

4.我们需要对操作进行互斥锁,保护起来,以免其它线程进行了数据的修改。因此,划出一段空间出来,形成互斥锁的生命周期。

5.进行语句查询,查询后,获取结果集保存到本地,如果获取失败,则说明没有该用户,因此验证失败。如果由,那么往下走。

6.获取结果集的行数,然后遍历结果集,将该用户的其它数据进行填入,返回回去。

7.最后释放结果集。

    bool login(Json::Value& user)
    {
        /*先判断登录的数据是否完整*/
        if(user["password"].isNull() || user["username"].isNull())
        {
            DLOG("INPUT PASSWORD OR USERNAME");
            return false;
        }
        /*以用户名和密码共同作为查询过滤条件,查询到数据则表示用户密码一致,否则错误*/
        #define LOGIN_USER "select id, score, total_count, win_count from user where username='%s' and password=password('%s');"
        char sql[4096]={0};
        sprintf(sql,LOGIN_USER,user["username"].asCString(),user["password"].asCString());
        /*查询语句执行,查看是否有数据,如果有,也只能有一条数据,如果没数据,说明登录验证不通过*/
        /*查看数据,使用保存结果到本地的函数mysql_store_result()*/
        MYSQL_RES* res=NULL;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            bool ret = mysql_util::mysql_exec(_mysql,sql);
            if(ret==false)
            {
                DLOG("user login failed!!\n");
                return false;
            }
            res = mysql_store_result(_mysql);
            if(res==NULL)/*没有数据,登录验证失败*/
            {
                DLOG("have no login user info!!");
                return false;
            }
        }
        /*有数据,获取该用户的其它数据:分数、场次等*/
        int row_num = mysql_num_rows(res);
        if(row_num!=1)
        {
            DLOG("the user information queried is not unique!");
            return false;
        }
        MYSQL_ROW row = mysql_fetch_row(res);
        user["id"] = (Json::UInt64)std::stol(row[0]);
        user["score"] = (Json::UInt64)std::stol(row[1]);
        user["total_count"] = std::stoi(row[2]);
        user["win_count"] = std::stoi(row[3]);
        mysql_free_result(res);
        return true;
    }

⑦胜利时修改分数

流程:先定义出MySQL更新语句的字符串,由于是胜利的,因此分数+30,对战总场次+1,胜利场次+1。

将字符串保存到sql数组中,然后上互斥锁,不能让修改数据的时候,有其它线程同时访问,造成数据的错误。

最后执行语句

    bool win(uint16_t id)
    {
        #define USER_WIN "update user set score=score+30, total_count=total_count+1, win_count=win_count+1 where id=%d;"
        char sql[4096]={0};
        sprintf(sql,USER_WIN,id);
        std::unique_lock<std::mutex> lock(_mutex);
        bool ret =  mysql_util::mysql_exec(_mysql,sql);
        if(ret==false)
        {
            DLOG("update winner info failed!\n");
            return false;
        } 
        return true;
    }

⑧失败时修改分数

流程:先定义出MySQL更新语句的字符串,由于是失败的,因此分数减去30,对战总场次+1。

将字符串保存到sql数组中,然后上互斥锁,不能让修改数据的时候,有其它线程同时访问,造成数据的错误。

最后执行语句。文章来源地址https://www.toymoban.com/news/detail-638543.html

    bool loser(uint16_t id)
    {
        #define USER_LOSER "update user set score=score-30, total_count=total_count+1 where id=%d;"
        char sql[4096]={0};
        sprintf(sql,USER_LOSER,id);
        std::unique_lock<std::mutex> lock(_mutex);
        bool ret =  mysql_util::mysql_exec(_mysql,sql);
        if(ret==false)
        {
            DLOG("update loser info failed!\n");
            return false;
        } 
        return true;
    }

到了这里,关于C++项目:在线五子棋对战网页版--数据模块开发的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 网页版Java(Spring/Spring Boot/Spring MVC)五子棋项目(四)对战模块

    匹配成功返回数据 1. message消息类别 2. ok 3. reson 4. 房间id 5. 双方id 6.白色玩家 一个类记录房间中的信息(房间id,两个用户id,是否为白棋) 信息提示框 处理匹配API 初始化游戏(棋盘,下一个棋子,接受棋子处理响应,判断是否结束) 1. 客户端连接到游戏房间后, 服务器返回

    2024年02月13日
    浏览(38)
  • 在线五子棋对战 --- 人机对战的实现

    要增添一个人机对战的模块, 最大的难点就是如何让人机知道下在什么位置是最好的, 不仅要具备进攻的能力, 还需要具备防守的能力. 这里当人机第一次走的时候, 采用标准开局, 下子在最中间. 当玩家走了之后, 人机就需要去判定下在什么位置合理. 这里采用的是评分表的方法

    2024年02月05日
    浏览(31)
  • C++ 实现对战AI五子棋

     个人主页: 日刷百题 系列专栏 : 〖C/C++小游戏〗 〖Linux〗 〖数据结构〗   〖 C语言 〗 🌎 欢迎各位 → 点赞 👍+ 收藏 ⭐️+ 留言 📝  ​ ​      为了能够快速上手一门语言,我们往往在学习了基本语法后,采用写一个小项目的方式来加深理解语言的语法及运用,本文采

    2024年02月03日
    浏览(43)
  • 【项目设计】网络对战五子棋(上)

    想回家过年… 1.1 http1.0/1.1和websocket协议 1. a. http协议在Linux的学习部分我们就已经学习过了,当时http和https是一块学的,我们当时其实已经了解了http的大部分知识内容,比如http请求和响应的格式,各自的报头字段都有哪些,cookie和session机制,http1.1的长连接策略keep-alive,还有

    2024年02月07日
    浏览(35)
  • Linux项目实战——五子棋(单机人人对战版)

    Linux操作系统项目实战——五子棋 GIF: 目录            Linux操作系统项目——五子棋 一、问题导引: 二、实现要求: 三、五子棋原理: 1.落子数据信息保存载体: 2.落子思路: 3.判断“五子连珠” 四、项目实现步骤: Ⅰ.创建目录及文件: 1.在Linux环境下创建名为Gobang的文

    2024年02月03日
    浏览(38)
  • 2.6.C++项目:网络版五子棋对战之数据管理模块-游戏房间管理模块的设计

    对匹配成功的玩家创建房间,建立起一个小范围的玩家之间的关联关系! 房间里一个玩家产生的动作将会广播给房间里的其他用户。 将这些房间管理起来,以便于进行房间生命周期的控制! 游戏房间类: // 实现两个部分: // 1. 房间的设计 // 2. 房间管理的设置 // 游戏房间的

    2024年02月08日
    浏览(33)
  • 基于FPGA(basys3)的双人对战人机对战五子棋(vivado)课程设计项目

    目录 主界面显示与选择模式 双人对战 人机对战 胜利界面显示 部分源码 VGA显示器显示图片,显示图片利用Block Memory Generator将图片像素点储存在RAM里面。 效果图:(防止侵权打了马赛克)  通过开发板上的按键进行模式选择,模式确定 双人对战就是采用简单的存数组的办法

    2024年01月18日
    浏览(31)
  • 基于Python的五子棋人机对战

    在之前的博文基于tkinter的五子棋游戏中使用tkinter做了一个简单的五子棋游戏,只能实现人人对战,后来想着加上人机对战的功能。 不过,最初想想还是挺麻烦的,计算机怎么评估当前的棋局,找到最佳或者较佳的落子点呢,脑子真是越来越不灵光了。站在巨人的肩膀上,科

    2024年02月04日
    浏览(30)
  • python实现五子棋-人机对战/人人对战(动图演示+源码分享)

    大家好,我是梦执,对梦执着。希望能和大家共同进步!   五子棋对战-所有文件文末自取 前言 人人对战 动态演示 源码分享 cheackboard.py 人人对战.py 导入模块 设置棋盘和棋子参数 局内字体设置 落子循坏体 画棋盘 画棋子 运行框返回落子坐标 执行文件 人机对战 动态演示

    2023年04月08日
    浏览(42)
  • JAVA五子棋手机网络对战游戏的设计与实现(源代码+论文)

    在现代社会中,手机及其它无线设备越来越多的走进普通老百姓的工作和生活。 随着3G技术的普及与应用,基于Java开发的软件在手机上的使用非常的广泛,手机增值服务的内容也是越来越多,对丰富人们的生活内容、提供快捷的资讯起着不可忽视的作用。 本文基于J2ME技术,以

    2024年02月09日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包