C++实战小项目贪吃蛇网游化框架搭建4数据库连接

数据库采用开源的MySQL 5.7,使用windows平台的ODBC连接,MySQL安装部分就直接略过了,安装完成之后,打开一个Query创建一个snakes数据库以及相应的表:

create DATABASE snakes;
use snakes;
CREATE TABLE usersdata (
	users varchar(20) NOT NULL,
	codes` varchar(20) DEFAULT '0000',
	PRIMARY KEY (users)
) ENGINE=InnoDB DEFAULT CHARSET=utf8'

create table snakesdata
(
	food varchar(4),
    body varchar(200),
    direction varchar(3),
    score varchar(3),
    record varchar(3),
	user_id varchar(20) NOT NULL PRAMARY KEY,
    FOREIGN KEY (user_id) REFERENCES usersdata (users) ON DELETE CASCADE ON UPDATE CASCADE
);

这样就创建了两个相互关联的表usersdata和snakesdata,前者保存用户账户和密码,后者保存用户的游戏数据,这里创建一个测试账户,用户名aa,密码bb:

insert into usersdata values ('uaa','bb');
insert into snakesdata (user_id) values ('uaa'); 

到这里在MySQL里的工作就基本完成了,之后在window下搜索ODBC数据源,在用户DSN中加入snakes数据库,设置好账户和密码,确定后数据源添加成功:
  
  
  下面在服务端中添加与数据库连接以及操作数据库的相关代码,通过ODBC连接和操作数据库的优势在于可使用标准SQL语句对任意的数据库进行操作,msdn中有关于ODBC操作数据库的详细指导:https://docs.microsoft.com/en-us/sql/connect/odbc/microsoft-odbc-driver-for-sql-server
  主要代码如下:

SQLHENV  henv = SQL_NULL_HENV;//定义环境句柄
SQLHDBC  hdbc1 = SQL_NULL_HDBC;//定义数据库连接句柄     
SQLHSTMT  hstmt1 = SQL_NULL_HSTMT;//定义语句句柄

short connecttodb() {
	RETCODE retcode;//错误返回码
	retcode = SQLAllocHandle(SQL_HANDLE_ENV, NULL, &henv);//allocate environment handle
	if (retcode < 0)//错误处理 
	{
		printf("allocate ODBC Environment handle errors.\n");
		return 0;
	}
	retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,
		(SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);//set environment handle attributes
	if (retcode < 0) //错误处理
	{
		printf("the  ODBC is not version3.0\n ");
		return 0;
	}
	retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc1);//allocate connection handle based on allocated environment handle
	if (retcode < 0) //错误处理
	{
		printf("allocate ODBC connection handle errors.\n");
		return 0;
	}

	char* szDSN = "mysqltest";//添加数据源时,为其起的名字
	char* szUID = "root";
	char* szAuthStr = "VIvi3154";

	retcode = SQLConnect(hdbc1,
		(SQLCHAR*)szDSN,
		(SWORD)strlen(szDSN),
		(SQLCHAR*)szUID,
		(SWORD)strlen(szUID),
		(SQLCHAR*)szAuthStr,
		(SWORD)strlen(szAuthStr));

	if (retcode < 0) //错误处理
	{
		printf("connect to  ODBC datasource errors.\n");
		return 0;
	}

	retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc1, &hstmt1);  //allocte s
	if (retcode < 0)
	{
		printf("allocate ODBC statement handle errors.\n");
		return 0;
	}
	return 1;
}

首先分配一个环境句柄,设置环境属性,分配一个连接句柄,调用SQLconnect函数进行连接,结合连接句柄分配一个语句句柄,完成之后就可以通过该语句句柄调用SQLexecDirect或SQLexecute函数对数据库进行相应的操作。先分别定义一个对数据库进行读写的函数:

char body[8] = { 'b',20,20,20,21,20,22 };
char food[4] = { 'f',14,18 };//横坐标一定为偶数
char direction[3]="dd";
char score[3] = { 's',0 };
char record[3] = { 'r',1 };

short readdb(const char *user)
{
	char buff[200];
	sprintf(buff, "select users,codes,body,food,direction,score,record from usersdata join snakesdata on users=user_id where users='%s';" , user);
	RETCODE retcode;
	while ((retcode = SQLExecDirect(hstmt1, buff, SQL_NTS)) < 0) {
		if (retcode = SQL_ERROR) {
			SQLSMALLINT errmsglen;
			SQLINTEGER errnative;
			UCHAR errmsg[255];
			UCHAR errstate[5];
			SQLGetDiagRec(SQL_HANDLE_STMT, hstmt1, 1, errstate, errnative, errmsg, sizeof(errmsg), &errmsglen);
			if(strcmp("42S02", errstate)==0)//读取不到该数据,即账号不存在
				return 0;
		}
		printf("readdata from database error,press any key to retry...\n");
		system("pause>>nul");
	}
	return 1;
}

void writedb(user)
 {
	char buff[1000];
	sprintf(buff, "update snakesdata set body ='%s',food='%s',direction='%s',score='%s',record='%s' where user_id='%s'", body, food, direction, score, record, user);
	RETCODE retcode;
	while ((retcode = SQLExecDirect(hstmt1, buff, SQL_NTS)) < 0) {
		printf("senddata to database error,press any key to retry...\n");
		system("pause>>nul");
		}
	}

void reset(const char *user)
{
	writedb(user);
}

两个函数的逻辑基本一致,先调用sprintf函数生成要执行的SQL语句,再调用SQLExecDirect函数对语句进行执行,在之后的程序运行过程中,当客户端发送账户数据时,服务端调用readdb从数据库读取数据,若账户验证成功则加载游戏数据到缓存中,若密码也验证成功则将缓存中的游戏数据发送到客户端,客户端读取相应的数据后开始游戏;而每当客户端关闭连接后,需要调用writedb函数将缓存中数据写入进数据库。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值