首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【在线五子棋对战】七、数据管理模块实现

【在线五子棋对战】七、数据管理模块实现

作者头像
利刃大大
发布2025-07-22 08:31:22
发布2025-07-22 08:31:22
12200
代码可运行
举报
文章被收录于专栏:csdn文章搬运csdn文章搬运
运行总次数:0
代码可运行

前言

数据管理模块主要负责对于数据库中数据进行统一的增删改查管理,其他模块要对数据操作都必须通过数据管理模块完成。主要分为下面的两大块进行设计:

  • 数据库表的设计
  • 数据管理模块的封装和实现

Ⅰ. 数据库表的设计

创建一个 user 表, 用来表示用户信息及积分信息:

  • 用户信息:用来实现登录、注册、游戏对战数据管理等功能
  • 积分信息:用来实现匹配功能

也就是说我们的表里面要有下面这些字段:

  • id:作为主键,用于表示用户的唯一性
  • username:用户名称
  • password:密码
  • score:用户的积分
  • total_count:用户总的比赛场次
  • win_count:用户总的胜利比赛场次

​ 所以我们创建一个 .sql 文件,创建一个数据库,叫做 gobang,然后创建一张表,叫做 user,然后将这些字段放到 user 表中!

代码语言:javascript
代码运行次数:0
运行
复制
create database if not exists gobang;
use gobang;
create table if not exists user(
    id int primary key auto_increment,
    username varchar(32) unique key not null,
    password varchar(128) not null,
    score int,
    total_count int,
    win_count int
);

​ 如果在测试代码的时候需要删掉该数据库中表,那么可以在上述代码最上方加入此行 mysql 指令:

代码语言:javascript
代码运行次数:0
运行
复制
drop database if exists gobang;

​ 然后重新将 db.sql 导入到客户端中即可!

​ 其中 username 我们设为具有唯一性的!

​ 接下来我们保存这个文件内容,然后将该文件内容重定向到 mysql -uroot 指令中去,也就是如下操作:

代码语言:javascript
代码运行次数:0
运行
复制
[root@VM-8-7-centos source]# mysql -uroot < db.sql
[root@VM-8-7-centos source]# mysql -uroot
……
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| gobang             |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

mysql> use gobang;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+------------------+
| Tables_in_gobang |
+------------------+
| stu              |
| user             |
+------------------+
2 rows in set (0.00 sec)

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)

Ⅱ. 数据管理模块的封装和实现

​ 数据库中有可能存在很多张表,每张表中管理的数据又有不同,要进行的数据操作也各不相同,因此我们可以为每⼀张表中的数据操作都设计一个类,通过类实例化的对象来管理这张数据库表中的数据,这样的话当我们要访问哪张表的时候,使用哪个类实例化的对象即可。

​ 这里创建一个 user_table 类, 该类的作用是负责通过 MySQL 接⼝管理用户数据。主要提供以下几种方法:

  • sign_up():新增用户,实现注册功能
  • login():登录验证,并获取完整的用户信息
  • select_by_name():根据用户名查找用户信息
  • select_by_id():根据 id 查找用户信息
  • win():胜利时天梯分数增加,战斗场次增加,胜利场次增加
  • lose():失败时天梯分数减少,战斗场次增加,其它不变

​ 除此之外,因为我们要操作这个数据库表,所以我们**得有 MYSQL* 操作句柄,另外因为有可能两个线程同时在访问或者修改数据库表,那么就会导致数据出现错误,所以必须加锁**!

​ 所以大体的类框架如下:

代码语言:javascript
代码运行次数:0
运行
复制
#ifndef __MY_DB_H__
#define __MY_DB_H__
#include "util.hpp"
#include <mutex>

class user_table
{
private:
    MYSQL* _mysql;   // 操作句柄
    std::mutex _mtx; // 互斥锁保护数据库的操作
public:
    user_table()
    {}
    ~user_table()
    {}
    // 注册函数
    bool sign_up(Json::Value& user)
    {}
    // 登录函数
    bool login(Json::Value& user)
    {}
    // 通过用户名获取用户信息
    bool select_by_name(const std::string& name, Json::Value& user)
    {}
    // 通过id获取用户信息
    bool select_by_id(uint64_t id, Json::Value& user)
    {}
    // 胜利处理函数
    bool win(uint64_t id)
    {}
    // 失败处理函数
    bool lose(uint64_t id)
    {}
};

#endif
构造函数

​ 构造函数就是对操作句柄的初始化嘛!

代码语言:javascript
代码运行次数:0
运行
复制
user_table(const std::string& host,
               const std::string& user,
               const std::string& passwd,
               const std::string& dbname,
               uint16_t port = 3306)
{
    _mysql = mysql_util::mysql_create(host, user, passwd, dbname, port);
    assert(_mysql != NULL);
}
析构函数

​ 析构函数就是释放句柄!

代码语言:javascript
代码运行次数:0
运行
复制
~user_table()
{
    mysql_util::mysql_destroy(_mysql);
}
sign_up注册函数
  1. 首先肯定是要判断用户是否提供了用户名和密码。如果连用户名和密码都没有的话,那么直接返回 false 即可
  2. 接着就是将我们宏定义的 sql 语句,通过 sprintf 函数格式化放到字符数组 query
  3. 最后就是执行 sql 语句啦,执行完判断一下是否成功即可!
代码语言:javascript
代码运行次数:0
运行
复制
bool sign_up(Json::Value& user)
{
#define SIGN_UP "insert user values(null, '%s', password('%s'), 1000, 0, 0);"
    // 1. 首先判断是否提供了用户名和密码 -- 并且用户名密码不能为空
    if(user["username"].isNull() || user["password"].isNull() || user["username"].asString().empty() || user["password"].asString().empty())
    {
        DLOG("user didn't enter an username or password!");
        return false;
    }

    // 2. 将语句格式化后放到query数组中
    char query[4096] = {0};
    sprintf(query, SIGN_UP, user["username"].asCString(), user["password"].asCString());

    // 3. 执行语句
    bool ret = mysql_util::mysql_exec(_mysql, query);
    if(ret == false)
    {
        DLOG("sign up user failed!");
        return false;
    }
    return true;
}
login登录函数

​ 登录函数相对前面来说就比较复杂了,因为我们要执行的是查询语句,查询语句又涉及到了保存结果集到本地,获取结果集等等的操作,那么相对来说会繁琐一些,但是步骤还是比较清晰的!下面是几大步骤:

  1. 首先判断是否提供了用户名和密码。如果连用户名和密码都没有的话,那么直接返回 false 即可
  2. 将语句格式化后放到 query 数组中
  3. 执行 sql 语句,并且保存结果集到本地
    • 为什么将这两个操作放到一步呢,因为我们要对这两个操作进行加锁,为什么要加锁呢❓❓❓
    • 因为查询完之后我们下一步就是将其结果集保存到本地,有可能此时还有其它的线程在执行 sql 语句,此时要是还没保存就被修改或者删除了,就造成线程安全问题了,所以必须加锁!
  4. 获取结果集条数,得到结果集
    • 这里行数肯定是只有一行,因为在表中我们规定了用户名是唯一的!
  5. 将数据库中的用户信息填写到 user 对象中去,作为输出型参数
    • 这里所需注意的就是类型问题,具体看代码
  6. 释放结果集
代码语言:javascript
代码运行次数:0
运行
复制
bool login(Json::Value& user)
{
#define LOGIN_SQL "select id, score, total_count, win_count from user where username='%s' and password=password('%s');"
    // 1. 首先判断是否提供了用户名和密码 -- 并且用户名密码不能为空
    if(user["username"].isNull() || user["password"].isNull() || user["username"].asString().empty() || user["password"].asString().empty())
    {
        DLOG("user didn't enter an username or password!");
        return false;
    }

    // 2. 将语句格式化后放到query数组中
    char query[4096] = {0};
    sprintf(query, LOGIN_SQL, user["username"].asCString(), user["password"].asCString());

    // 3. 执行sql语句,因为查询之后需要保存到本地,为了保证保存过程的线程安全,这段代码需要加锁
    //    这里不直接使用加锁,而是通过守卫锁来管理锁,更加安全
    //    并且因为守卫锁是当前作用域有效,所以只对要加锁的区域放在一个空代码块中当作一个作用域
    MYSQL_RES* res = nullptr;
    {
        std::unique_lock<std::mutex> lock(_mtx); // 相当于加锁了

         // 执行sql语句
        bool ret = mysql_util::mysql_exec(_mysql, query);
        if(ret == false)
        {
            if(ret == false)
            {
                DLOG("user login failed!");
                return false;
            }
        }

        // 保存查询结果到本地
        res = mysql_store_result(_mysql);
        if(res == nullptr)
        {
            DLOG("mysql_store_result!");
            return false;
        }
    }

    // 4. 获取结果集条数,得到结果集 -- 这里行数肯定是只有一行,因为在表中我们规定了用户名是唯一的
    int row_num = mysql_num_rows(res);
    if(row_num == 0)
    {
        DLOG("the user information is not found!");
        return false;
    }
    else if (row_num != 1) 
    {
        DLOG("the user information queried is not unique!");
        return false;
    }
    MYSQL_ROW row = mysql_fetch_row(res);

    // 5. 将数据库中的用户信息填写到user对象中去,作为输出型参数
    //     这里有细节,因为结果集中的数据都是字符串,所以转化为整型,最好是长整型
    //     但是转化为长整型会报错,所以再强转为json的数据类型,如下面的Json::UInt64
    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]);

    // 6. 别忘了释放结果集
    mysql_free_result(res);
    return true;
}
select_by_name获取信息函数

​ 因为涉及到的依然是查询语句,其实大体的过程和上面的登录函数是类似的,不同的就是 sql 语句改变了、一些日志内容改变、用户信息填写时候多填一个姓名的字段,仅此而已,这里就不多赘述了,具体参考上面登录函数,结合下面的代码注释:

代码语言:javascript
代码运行次数:0
运行
复制
bool select_by_name(const std::string& name, Json::Value& user)
{
#define SELECT_BY_NAME "select id, score, total_count, win_count from user where username='%s';"
    // 1. 将语句格式化后放到query数组中
    char query[4096] = {0};
    sprintf(query, SELECT_BY_NAME, name.c_str());

    // 2. 执行语句,并且保存结果集到本地 -- 因为是查询语句,所以还是依然要加锁保证线程安全
    MYSQL_RES* res = nullptr;
    {
        std::unique_lock<std::mutex> lock(_mtx); // 相当于加锁

        // 执行语句
        bool ret = mysql_util::mysql_exec(_mysql, query);
        if(ret == false)
        {
            DLOG("get user by name failed!!");
            return false;
        }

        // 保存结果集
        res = mysql_store_result(_mysql);
        if(res == nullptr)
        {
            DLOG("mysql_store_result failed");
            return false;
        }
    }

    // 3. 获取结果集条数,得到结果集
    int row_num = mysql_num_rows(res);
    if(row_num == 0)
    {
        DLOG("the user information is not found!");
        return false;
    }
    else if(row_num != 1)
    {
        DLOG("the user information queried is not unique!!");
        return false;
    }
    MYSQL_ROW row = mysql_fetch_row(res);

    // 4. 将数据库中的用户信息填写到user对象中去,作为输出型参数
    user["id"] = (Json::UInt64)std::stol(row[0]);
    user["username"] = name;
    user["score"] = (Json::UInt64)std::stol(row[1]);
    user["total_count"] = std::stoi(row[2]);
    user["win_count"] = std::stoi(row[3]);

    // 5. 释放结果集
    mysql_free_result(res);
    return true;
}
select_by_id获取信息函数

​ 上面的 select_by_name 函数修改细节就能变成这个函数!

代码语言:javascript
代码运行次数:0
运行
复制
bool select_by_id(uint64_t id, Json::Value& user)
{
#define SELECT_BY_ID "select username, score, total_count, win_count from user where id='%d';"
    // 1. 将语句格式化后放到query数组中
    char query[4096] = {0};
    sprintf(query, SELECT_BY_ID, id);

    // 2. 执行语句,并且保存结果集到本地 -- 因为是查询语句,所以还是依然要加锁保证线程安全
    MYSQL_RES* res = nullptr;
    {
        std::unique_lock<std::mutex> lock(_mtx); // 相当于加锁

        // 执行语句
        bool ret = mysql_util::mysql_exec(_mysql, query);
        if(ret == false)
        {
            DLOG("get user by id failed!!");
            return false;
        }

        // 保存结果集
        res = mysql_store_result(_mysql);
        if(res == nullptr)
        {
            DLOG("mysql_store_result failed");
            return false;
        }
    }

    // 3. 获取结果集条数,得到结果集
    int row_num = mysql_num_rows(res);
    if(row_num == 0)
    {
        DLOG("the user information is not found!");
        return false;
    }
    else if(row_num != 1)
    {
        DLOG("the user information queried is not unique!!");
        return false;
    }
    MYSQL_ROW row = mysql_fetch_row(res);

    // 4. 将数据库中的用户信息填写到user对象中去,作为输出型参数
    user["id"] = (Json::UInt64)id;
    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]);

    // 5. 释放结果集
    mysql_free_result(res);
    return true;
}
win胜利处理函数

​ 这函数比较简单了,因为用到的 sql 语句是修改语句,不需要做太多工作,具体看代码:

代码语言:javascript
代码运行次数:0
运行
复制
// 胜利处理函数 -- 胜利时天梯分数增加30分,战斗场次增加1,胜利场次增加1
bool win(uint64_t id)
{
#define WIN "update user set score=score+30, total_count=total_count+1, win_count=win_count+1 where id='%d';"
    // 1. 将语句格式化后放到query数组中
    char query[4096] = {0};
    sprintf(query, WIN, id);

    // 2. 执行语句
    bool ret = mysql_util::mysql_exec(_mysql, query);
    if(ret == false)
    {
        DLOG("update win user info failed!!\n");
        return false;
    }
    return true;
}
lose失败处理函数

​ 上面的 win 函数修改一下就变成了这里的函数!

代码语言:javascript
代码运行次数:0
运行
复制
// 失败处理函数 -- 失败时天梯分数减少30,战斗场次增加1,其他不变
bool lose(uint64_t id)
{
#define LOSE "update user set score=score-30, total_count=total_count+1 where id='%d';"
    // 1. 将语句格式化后放到query数组中
    char query[4096] = {0};
    sprintf(query, LOSE, id);

    // 2. 执行语句
    bool ret = mysql_util::mysql_exec(_mysql, query);
    if(ret == false)
    {
        DLOG("update lose user info failed!!\n");
        return false;
    }
    return true;
}

测试代码

代码语言:javascript
代码运行次数:0
运行
复制
void db_test()
{
    user_table ut(HOST, USER, PASSWD, DBNAME, PORT);
    Json::Value user;
    // user["username"] = "xiaoming";
    // user["password"] = "123456";

    bool ret = ut.lose(1);
    if(ret == false)
    {
        DLOG("login failed!");
        return;
    }
    std::string body;
    json_util::serialize(user, body);
    std::cout << body << std::endl;
}

完整代码

代码语言:javascript
代码运行次数:0
运行
复制
#ifndef __MY_DB_H__
#define __MY_DB_H__
#include "util.hpp"
#include <mutex>
#include <cassert>

class user_table
{
private:
    MYSQL* _mysql;   // 操作句柄
    std::mutex _mtx; // 互斥锁保护数据库的操作
public:
    user_table(const std::string& host,
               const std::string& user,
               const std::string& passwd,
               const std::string& dbname,
               uint16_t port = 3306)
    {
        _mysql = mysql_util::mysql_create(host, user, passwd, dbname, port);
        assert(_mysql != NULL);
    }

    ~user_table()
    {
        mysql_util::mysql_destroy(_mysql);
        _mysql = NULL;
    }

    // 注册函数
    bool sign_up(Json::Value& user)
    {
#define SIGN_UP "insert user values(null, '%s', password('%s'), 1000, 0, 0);"
        // 1. 首先判断是否提供了用户名和密码 -- 并且用户名密码不能为空
        if(user["username"].isNull() || user["password"].isNull() || user["username"].asString().empty() || user["password"].asString().empty())
        {
            DLOG("user didn't enter an username or password!");
            return false;
        }

        // 2. 将语句格式化后放到query数组中
        char query[4096] = {0};
        sprintf(query, SIGN_UP, user["username"].asCString(), user["password"].asCString());

        // 3. 执行语句
        bool ret = mysql_util::mysql_exec(_mysql, query);
        if(ret == false)
        {
            DLOG("sign up user failed!");
            return false;
        }
        return true;
    }

    // 登录函数
    bool login(Json::Value& user)
    {
#define LOGIN_SQL "select id, score, total_count, win_count from user where username='%s' and password=password('%s');"
        // 1. 首先判断是否提供了用户名和密码 -- 并且用户名密码不能为空
        if(user["username"].isNull() || user["password"].isNull() || user["username"].asString().empty() || user["password"].asString().empty())
        {
            DLOG("user didn't enter an username or password!");
            return false;
        }

        // 2. 将语句格式化后放到query数组中
        char query[4096] = {0};
        sprintf(query, LOGIN_SQL, user["username"].asCString(), user["password"].asCString());

        // 3. 执行sql语句,因为查询之后需要保存到本地,为了保证保存过程的线程安全,这段代码需要加锁
        //    这里不直接使用加锁,而是通过守卫锁来管理锁,更加安全
        //    并且因为守卫锁是当前作用域有效,所以只对要加锁的区域放在一个空代码块中当作一个作用域
        MYSQL_RES* res = nullptr;
        {
            std::unique_lock<std::mutex> lock(_mtx); // 相当于加锁了
            
             // 执行sql语句
            bool ret = mysql_util::mysql_exec(_mysql, query);
            if(ret == false)
            {
                if(ret == false)
                {
                    DLOG("user login failed!");
                    return false;
                }
            }

            // 保存查询结果到本地
            res = mysql_store_result(_mysql);
            if(res == nullptr)
            {
                DLOG("mysql_store_result!");
                return false;
            }
        }

        // 4. 获取结果集条数,得到结果集 -- 这里行数肯定是只有一行,因为在表中我们规定了用户名是唯一的
        int row_num = mysql_num_rows(res);
        if(row_num == 0)
        {
            DLOG("the user information is not found!");
            return false;
        }
        else if (row_num != 1) 
        {
            DLOG("the user information queried is not unique!");
            return false;
        }
        MYSQL_ROW row = mysql_fetch_row(res);

        // 5. 将数据库中的用户信息填写到user对象中去,作为输出型参数
        //     这里有细节,因为结果集中的数据都是字符串,所以转化为整型,最好是长整型
        //     但是转化为长整型会报错,所以再强转为json的数据类型,如下面的Json::UInt64
        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]);

        // 6. 别忘了释放结果集
        mysql_free_result(res);
        return true;
    }

    // 通过用户名获取用户信息
    bool select_by_name(const std::string& name, Json::Value& user)
    {
#define SELECT_BY_NAME "select id, score, total_count, win_count from user where username='%s';"
        // 1. 将语句格式化后放到query数组中
        char query[4096] = {0};
        sprintf(query, SELECT_BY_NAME, name.c_str());

        // 2. 执行语句,并且保存结果集到本地 -- 因为是查询语句,所以还是依然要加锁保证线程安全
        MYSQL_RES* res = nullptr;
        {
            std::unique_lock<std::mutex> lock(_mtx); // 相当于加锁

            // 执行语句
            bool ret = mysql_util::mysql_exec(_mysql, query);
            if(ret == false)
            {
                DLOG("get user by name failed!!");
                return false;
            }

            // 保存结果集
            res = mysql_store_result(_mysql);
            if(res == nullptr)
            {
                DLOG("mysql_store_result failed");
                return false;
            }
        }

        // 3. 获取结果集条数,得到结果集
        int row_num = mysql_num_rows(res);
        if(row_num == 0)
        {
            DLOG("the user information is not found!");
            return false;
        }
        else if(row_num != 1)
        {
            DLOG("the user information queried is not unique!!");
            return false;
        }
        MYSQL_ROW row = mysql_fetch_row(res);

        // 4. 将数据库中的用户信息填写到user对象中去,作为输出型参数
        user["id"] = (Json::UInt64)std::stol(row[0]);
        user["username"] = name;
        user["score"] = (Json::UInt64)std::stol(row[1]);
        user["total_count"] = std::stoi(row[2]);
        user["win_count"] = std::stoi(row[3]);

        // 5. 释放结果集
        mysql_free_result(res);
        return true;
    }

    // 通过id获取用户信息
    bool select_by_id(uint64_t id, Json::Value& user)
    {
#define SELECT_BY_ID "select username, score, total_count, win_count from user where id='%d';"
        // 1. 将语句格式化后放到query数组中
        char query[4096] = {0};
        sprintf(query, SELECT_BY_ID, id);

        // 2. 执行语句,并且保存结果集到本地 -- 因为是查询语句,所以还是依然要加锁保证线程安全
        MYSQL_RES* res = nullptr;
        {
            std::unique_lock<std::mutex> lock(_mtx); // 相当于加锁

            // 执行语句
            bool ret = mysql_util::mysql_exec(_mysql, query);
            if(ret == false)
            {
                DLOG("get user by id failed!!");
                return false;
            }

            // 保存结果集
            res = mysql_store_result(_mysql);
            if(res == nullptr)
            {
                DLOG("mysql_store_result failed");
                return false;
            }
        }

        // 3. 获取结果集条数,得到结果集
        int row_num = mysql_num_rows(res);
        if(row_num == 0)
        {
            DLOG("the user information is not found!");
            return false;
        }
        else if(row_num != 1)
        {
            DLOG("the user information queried is not unique!!");
            return false;
        }
        MYSQL_ROW row = mysql_fetch_row(res);

        // 4. 将数据库中的用户信息填写到user对象中去,作为输出型参数
        user["id"] = (Json::UInt64)id;
        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]);

        // 5. 释放结果集
        mysql_free_result(res);
        return true;
    }

    // 胜利处理函数 -- 胜利时天梯分数增加30分,战斗场次增加1,胜利场次增加1
    bool win(uint64_t id)
    {
#define WIN "update user set score=score+30, total_count=total_count+1, win_count=win_count+1 where id='%d';"
        // 1. 将语句格式化后放到query数组中
        char query[4096] = {0};
        sprintf(query, WIN, id);

        // 2. 执行语句
        bool ret = mysql_util::mysql_exec(_mysql, query);
        if(ret == false)
        {
            DLOG("update win user info failed!!\n");
            return false;
        }
        return true;
    }

    // 失败处理函数 -- 失败时天梯分数减少30,战斗场次增加1,其他不变
    bool lose(uint64_t id)
    {
#define LOSE "update user set score=score-30, total_count=total_count+1 where id='%d';"
        // 1. 将语句格式化后放到query数组中
        char query[4096] = {0};
        sprintf(query, LOSE, id);

        // 2. 执行语句
        bool ret = mysql_util::mysql_exec(_mysql, query);
        if(ret == false)
        {
            DLOG("update lose user info failed!!\n");
            return false;
        }
        return true;
    }
};

#endif
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-07-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • Ⅰ. 数据库表的设计
  • Ⅱ. 数据管理模块的封装和实现
    • 构造函数
    • 析构函数
    • sign_up注册函数
    • login登录函数
    • select_by_name获取信息函数
    • select_by_id获取信息函数
    • win胜利处理函数
    • lose失败处理函数
  • 测试代码
  • 完整代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档