表名 | Users | ||||
字段名 | 类型 | 是否为空 | 默认值 | 主、外键 | 备注 |
id | int(11) | NOT | 1,自增长 | PK | 用户id |
username | varchar(64) | NOT | 用户名:英文字符、数字和特殊符号的组合 | ||
password | varchar(32) | NOT | 密码:英文字符、数字和特殊符号的组合,8-16位 | ||
level_id | int | 1 | 当前关卡,关联Levels表中的id |
表名 | Levels | |||||
字段名 | 类型 | 是否为空 | 默认值 | 主、外键 | 备注 | |
id | int | NOT | 1 | PK | 游戏关卡序号,从1开始 | |
name | varchar(64) | NOT | 地图名称 | |||
map_row | int | NOT | 地图二位组的总行数 | |||
map_column | int | NOT | 地图二维组的总列数 | |||
map_data | varchar(4096) | NOT | 地图数据,二维数组对应的行列式,多行以|分开,列以逗号分隔,最大接近支持45x45的地图 | |||
next_level_id | int | 0 | 下一关的关卡id,0代表通关 | |||
mysql> create database box_man; #创建数据库box_man mysql> mysql> create table users( #创建用户表 id int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT, username varchar(64) NOT NULL UNIQUE, password varchar(32) NOT NULL , level_id int default 1 ); mysql> create table levels( #创建关卡表 id int NOT NULL PRIMARY KEY default 1, name varchar(64) NOT NULL UNIQUE, map_row int NOT NULL, map_column int NOT NULL, map_data varchar(4096) NOT NULL, next_level_id int default 0 ); mysql> insert into users values(1000, 'martin', md5('123456qweQWE'), 1); mysql> insert into levels values(1, '牛刀小试', 9, 12, '0,0,0,0,0,0,0,0,0,0,0,0|0,1,0,1,1,1,1,1,1,1,0,0|0,1,4,1,0,2,1,0,2,1,0,0|0,1,0,1,0,1,0,0,1,1,1,0|0,1,0,2, 0,1,1,4,1,1,1,0|0,1,1,1,0,3,1,1,1,4,1,0|0,1,2,1,1,4,1,1,1,1,1,0|0,1,0,0,1,0,1,1,0,0,1,0|0,0,0,0,0,0,0,0,0,0, 0,0',0);
|
database.cpp
#include "database.h" #include #include #define DB_NAME "box_man" #define DB_HOST "127.0.0.1" #define DB_PORT 3306 #define DB_USER "root" #define DB_USER_PASSWD "123456qweQWE" static bool connect_db(MYSQL& mysql); /*************************************************** *功能:通过用户名和密码从数据库获取用户信息 *输入: * user - 用户信息结构体 * *返回值: * 获取成功返回true, 失败false ***************************************************/ bool fetch_user_info(userinfo& user) { MYSQL mysql; MYSQL_RES* res; //查询结果集 MYSQL_ROW row; //记录结构体 char sql[256]; bool ret = false; //1.连接到数据库 if (connect_db(mysql) == false) { return false; } //2.根据用户名和密码获取用户信息(id, level_id) snprintf(sql, 256, "select id, level_id from users where username='%s' and password=md5('%s');", user.username.c_str(), user.passwd.c_str()); ret = mysql_query(&mysql, sql); //成功返回0 if (ret) { printf("数据库查询出错,%s 错误原因: %s\n", sql, mysql_error(&mysql)); mysql_close(&mysql); return false; } //3.获取结果 res = mysql_store_result(&mysql); row = mysql_fetch_row(res); if (row == NULL) {//没有查找到记录 mysql_free_result(res); mysql_close(&mysql); return false; } user.id = atoi(row[0]); user.level_id = atoi(row[1]); printf("userid: %d level_id: %d\n", user.id, user.level_id); //打印ID //4.返回结果 //释放结果集 mysql_free_result(res); //关闭数据库 mysql_close(&mysql); return true; } bool connect_db(MYSQL& mysql) { //1.初始化数据库句柄 mysql_init(&mysql); //2.设置字符编码 mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "gbk"); //3.连接数据库 if (mysql_real_connect(&mysql, DB_HOST, DB_USER, DB_USER_PASSWD, DB_NAME, DB_PORT, NULL, 0) == NULL) { printf("数据库连接出错, 错误原因: %s\n", mysql_error(&mysql)); return false; } return true; } |
database.h
#pragma once #include using namespace std; //用户信息 typedef struct _userinfo{ int id; //用户id string username; //用户名 string passwd; //密码 int level_id; //关卡id }userinfo; bool fetch_user_info(userinfo &user); |
boxman.cpp
bool login(userinfo& user) { int times = 0; bool ret = false; do{ cout << "请输入用户名: "; cin >> user.username; cout << "请输入密码: "; cin >> user.passwd; //返回 bool ,成功返回true ,失败返回false . ret = fetch_user_info(user); times++; if (times >= MAX_RETRY_TIMES) { break; } if (ret == false) { cout << "登陆失败,请重新输入!" << endl; } } while (!ret); return ret; } |
//database.h typedef struct _levelinfo { int id; //关卡的id string name; //关卡的名字 int map_row; //地图总行数 int map_column; //地图总列数 string map_data; //二维地图数据 int next_level; //下一关卡的id }levelinfo; bool fetch_level_info(levelinfo &level, int level_id); //database.cpp /*************************************************** *功能:根据关卡id 获取完整的关卡信息(如: 地图,下一关等) *输入: * level - 保存关卡信息的结构体变量 * level_id - 要获取详细关卡信息的关卡id *返回值: * 获取成功返回true, 失败false ***************************************************/ bool fetch_level_info(levelinfo& level, int level_id) { MYSQL mysql; MYSQL_RES* res; //查询结果集 MYSQL_ROW row; //记录结构体 char sql[256]; bool ret = false; //1.连接到数据库 if (connect_db(mysql) == false) { return false; } //2.根据关卡id查询数据库获取关卡地图信息 snprintf(sql, 256, "select name, map_row, map_column, map_data, next_level_id from levels where id=%d;", level_id); ret = mysql_query(&mysql, sql); //成功返回0 if (ret) { printf("数据库查询出错,%s 错误原因: %s\n", sql, mysql_error(&mysql)); mysql_close(&mysql); return false; } //3.获取结果 res = mysql_store_result(&mysql); row = mysql_fetch_row(res); if (row == NULL) {//没有查找到记录 mysql_free_result(res); mysql_close(&mysql); return false; } level.id = level_id; level.name = row[0]; level.map_row = atoi(row[1]); level.map_column = atoi(row[2]); level.map_data = row[3]; level.next_level = atoi(row[5]); if(debug) printf("level id: %d name: %s map row: %d map column: %d map data: %s next level: %d\n", level.id, level.name.c_str(), level.map_row, level.map_column, level.map_data.c_str(), level.next_level);
//释放结果集 mysql_free_result(res); //关闭数据库 mysql_close(&mysql); return true; } |
//database.h bool transform_map_db2array(levelinfo &level, int map[LINE][COLUMN]); //database.cpp bool transform_map_db2array(levelinfo& level, int map[LINE][COLUMN]) { if (level.map_row > LINE || level.map_column > COLUMN) { printf("地图超大,请重新设置!\n"); return false; } if (level.map_data.length() < 1) { printf("地图数据有误,请重新设置!\n"); return false; } int start = 0, end = 0; int row = 0, column = 0; do { end = level.map_data.find('|', start); if (end < 0) { end = level.map_data.length(); } if (start >= end) break; string line = level.map_data.substr(start, end - start); printf("get line: %s\n", line.c_str()); //对行地图数据进行解析 char *next_token = NULL; char* item = strtok_s((char*)line.c_str(), ",", &next_token); column = 0; while (item && column < level.map_column) { printf("%s ", item); map[row][column] = atoi(item); column++; item = strtok_s(NULL, ",", &next_token); } if (column < level.map_column) { printf("地图数据解析出错,终止!\n"); return false; } printf("\n"); row++; if (row >= level.map_row) { break; } start = end + 1; } while (1 == 1); if (row < level.map_row) { printf("地图行数少于设定, %d(need: %d),终止!\n", row, level.map_row); return false; } return true; } //boxman.cpp //把数据库中的地图数据转换到map 中 ret = transform_map_db2array(level, map); |
//database.h bool update_user_level(userinfo& user, int next_level_id); //database.cpp bool update_user_level(userinfo& user, int next_level_id) { MYSQL mysql; MYSQL_RES* res; //查询结果集 MYSQL_ROW row; //记录结构体 char sql[256]; bool ret = false; //1.连接到数据库 if (connect_db(mysql) == false) { return false; } //2.根据用户id 更新下一关的level_id snprintf(sql, 256, "update users set level_id = %d where id=%d;", next_level_id, user.id); ret = mysql_query(&mysql, sql); if (ret) { printf("数据库更新出错,%s 错误原因: %s\n", sql, mysql_error(&mysql)); mysql_close(&mysql); return false; } //关闭数据库 mysql_close(&mysql); return true; } //boxman.cpp //...............前面省略N行代码.................... void gameNextScene(IMAGE* bg) { putimage(0, 0, bg); settextcolor(WHITE); RECT rec = { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT }; settextstyle(20, 0, _T("宋体")); drawtext(_T("恭喜您~ \n此关挑战成功,任意键跳转到下一关!"), &rec, DT_CENTER | DT_VCENTER | DT_SINGLELINE); ::system("pause"); cleardevice(); } //...............中间省略N行代码.................... if (isGameOver()) { if (level.next_level < 1) { gameOverScene(&bg_img); quit = true; break; } gameNextScene(&bg_img); //更新用户下一关的关卡信息 if (update_user_level(user, level.next_level)) { user.level_id = level.next_level; }
break; //quit = true; } |
#pragma once
#include #define KEY_UP 'w'
#define KEY_DOWN 's'
#define KEY_LEFT 'a'
#define KEY_RIGHT 'd'
#define KEY_QUIT 'q'#define START_X 100 //x轴偏移
#define START_Y 150 //y轴偏移#define WEIGHT 960 //舞台长
#define HEIGHT 768 //舞台宽#define RATIO 61#define isValid(pos) pos.x>=0 && pos.x=0 && pos.y
#include
#include
#include
#include
#include "box_man.h"
#include "database.h"using namespace std;int map[MAP_X][MAP_Y] = { 0 };int hold = 0;IMAGE pic[ALL]; //资源图片bool fetch_user_info(userinfo& user);
bool fetch_level_info(levelinfo& level, int level_id);
bool transform_map_dbtoarry(levelinfo& level, int map[MAP_X][MAP_Y]);
bool update_user_level(userinfo& user, int next_level_id);void changeMap(struct _POS* pos, enum _RES prop)
{map[pos->x][pos->y] = prop;putimage(START_X + pos->y * RATIO, START_Y + pos->x * RATIO, &pic[prop]);
}struct _POS man;bool isGameOver()
{int i, j;if (hold == 1){return false;}for (i = 0; i < MAP_X; i++){for (j = 0; j < MAP_Y; j++){if (map[i][j] == BOX_DES){return false;}}}return true;
}void gameOverScene(IMAGE* bg)
{putimage(0, 0, bg);settextcolor(WHITE);RECT rec = { 0,0,WEIGHT,HEIGHT };settextstyle(20, 0, _T("宋体"));drawtext(_T("恭喜您~\n通关了!再见"), &rec, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}void gameNextScene(IMAGE* bg)
{putimage(0, 0, bg);settextcolor(WHITE);RECT rec = { 0,0,WEIGHT,HEIGHT };settextstyle(20, 0, _T("宋体"));drawtext(_T("恭喜您~\n此关挑战成功,任意键跳转到下一关!"), &rec, DT_CENTER | DT_VCENTER | DT_SINGLELINE);::system("pause");cleardevice();
}void gameCotrol(enum _DIRECT direct)
{struct _POS next_pos = man;struct _POS next_next_pos = man;switch (direct){case UP:next_pos.x--;next_next_pos.x -= 2;break;case DOWN:next_pos.x++;next_next_pos.x += 2;break;case LEFT:next_pos.y--;next_next_pos.y -= 2;break;case RIGHT:next_pos.y++;next_next_pos.y += 2;break;}if (isValid(next_pos) && map[next_pos.x][next_pos.y] == FLOOR) //小人前是地板{if (hold == 0){changeMap(&next_pos, MAN);changeMap(&man, FLOOR);man = next_pos;}else{changeMap(&next_pos, MAN);changeMap(&man, BOX_DES);man = next_pos;hold = 0;}}else if (isValid(next_pos) && map[next_pos.x][next_pos.y] == BOX_DES) //小人前是箱子目的地{changeMap(&next_pos, MAN);changeMap(&man, FLOOR);man = next_pos;hold = 1;}else if (isValid(next_pos) && map[next_pos.x][next_pos.y] == BOX) //小人前是箱子{if (isValid(next_next_pos) && map[next_next_pos.x][next_next_pos.y] == BOX_DES){changeMap(&next_next_pos, HIT);changeMap(&next_pos, MAN);changeMap(&man, FLOOR);man = next_pos;}else if (isValid(next_next_pos) && map[next_next_pos.x][next_next_pos.y] == FLOOR) //箱子前面是地板{if (hold == 1){changeMap(&next_next_pos, BOX);changeMap(&next_pos, MAN);changeMap(&man, BOX_DES);man = next_pos;hold = 0;}else{changeMap(&next_next_pos, BOX);changeMap(&next_pos, MAN);changeMap(&man, FLOOR);man = next_pos;}}}else if (isValid(next_next_pos) && map[next_pos.x][next_pos.y] == HIT) //小人前方箱子和目的地重合{changeMap(&next_next_pos, BOX);changeMap(&next_pos, MAN);changeMap(&man, FLOOR);man = next_pos;hold = 1;}}bool login(userinfo& user)
{int times = 0; //登录次数int ret = false;do{cout << "请输入用户名:";cin >> user.username;cout << "请输入登录密码:";cin >> user.passwd;if (times > MAX_REIRY_TIMES){cout << "输入用户名或密码错误过多!" << endl;return false;}ret = fetch_user_info(user);} while (ret == false);return ret;
}void init_game_graph(IMAGE &bg_img)
{initgraph(WEIGHT, HEIGHT);loadimage(&bg_img, L"blackground.bmp", WEIGHT, HEIGHT, true);putimage(0, 0, &bg_img);loadimage(&pic[WALL], L"wall_right.bmp", RATIO, RATIO, true);loadimage(&pic[FLOOR], L"floor.bmp", RATIO, RATIO, true);loadimage(&pic[BOX_DES], L"des.bmp", RATIO, RATIO, true);loadimage(&pic[MAN], L"man.bmp", RATIO, RATIO, true);loadimage(&pic[BOX], L"box.bmp", RATIO, RATIO, true);loadimage(&pic[HIT], L"box.bmp", RATIO, RATIO, true);
}int main(void)
{userinfo user;levelinfo level;bool ret = false;IMAGE bg_img;if (!login(user)){cout << "登录失败" << endl;}else{cout << "登录成功!请开始你的表演" << endl;}//初始化游戏舞台init_game_graph(bg_img);::system("pause");bool quit = false;do{hold = 0; //每次到新的一关人物肯定不在目的地//根据用户所在的关卡id获取关卡数据ret = fetch_level_info(level, user.level_id);if (!ret){cout << "获取关卡数据失败,请重试!" << endl;::system("pause");exit(-1);}else{cout << "登录成功,用户id:" << user.id << ",您所在的关卡是:" << user.level_id << ",请开始您的表演!" << endl;}//把数据库中的地图数据转换到map中ret = transform_map_dbtoarry(level, map);if (!ret){cout << "转换地图失败,请重试!" << endl;::system("pause");exit(-1);}for (int i = 0; i < level.map_row; i++){for (int j = 0; j < level.map_column; j++){if (map[i][j] == MAN){man.x = i;man.y = j;}putimage(START_X + j * RATIO, START_Y + i * RATIO, &pic[map[i][j]]);}}do{if (_kbhit()){char ch = _getch();if (ch == KEY_UP){gameCotrol(UP);}else if (ch == KEY_DOWN){gameCotrol(DOWN);}else if (ch == KEY_LEFT){gameCotrol(LEFT);}else if (ch == KEY_RIGHT){gameCotrol(RIGHT);}else if (ch == KEY_QUIT){quit = false;}if (isGameOver()){if (level.next_level < 1){gameOverScene(&bg_img);quit = true;break;}gameNextScene(&bg_img);if (update_user_level(user, level.next_level)){user.level_id = level.next_level;putimage(0, 0, &bg_img); //显示图片}break;}}Sleep(100);} while (!quit);} while (quit == false);::system("pause");closegraph();return 0;
}
#include
#include
#include "database.h"using namespace std;#define DB_NAME "box_man"
#define DB_HOST "127.0.0.1"
#define DB_POST 3306
#define DB_USER "root"
#define DB_USER_PASSWD "rfly"//static bool connect_db(MYSQL& mysql);bool connect_db(MYSQL& mysql)
{mysql_init(&mysql);mysql_options(&mysql,MYSQL_SET_CHARSET_NAME,"gbk");if (mysql_real_connect(&mysql, DB_HOST, DB_USER, DB_USER_PASSWD, DB_NAME, DB_POST, NULL, 0) == NULL){printf("数据库连接失败,错误原因:%s\n", mysql_error(&mysql));return false;}return true;
}/****************************
*功能:通过用户名和密码获取用户信息
*输入:
* user - 用户信息结构体
*
* 返回值:
* 获取成功返回true
* 获取失败返回false
*****************************/bool fetch_user_info(userinfo& user)
{MYSQL mysql;MYSQL_RES* res; //查询结果集MYSQL_ROW row; //查询记录行char a[256]; //用来保存字符串查询语句int ret = false;//1.连接数据库if (connect_db(mysql) == false) {cout << "数据库连接失败" << endl;return false;}snprintf(a, 256, "select id,level_id from users where username = '%s' and password = md5('%s');", user.username.c_str(), user.passwd.c_str());ret = mysql_query(&mysql, a); //等于0,表示查询成功if (ret){printf("数据库查询出错,%s 错误原因:%s\n", a, mysql_error(&mysql));mysql_close(&mysql);return false;}res = mysql_store_result(&mysql);row = mysql_fetch_row(res);if (row == NULL){cout <<"查询到空数据,失败!" << endl;mysql_free_result(res);mysql_close(&mysql);return false;}user.id = atoi(row[0]);user.level_id = atoi(row[1]);cout << "用户名id:" << user.id << "\t" << "用户关卡:" << user.level_id;mysql_free_result(res);mysql_close(&mysql);return true;
}bool fetch_level_info(levelinfo& level, int level_id)
{MYSQL mysql;MYSQL_RES* res; //查询结果集MYSQL_ROW row; //查询记录行char sql[256];bool ret = false;if (connect_db(mysql) == false){cout << "数据库连接失败" << endl;return false;}snprintf(sql, 256, "select name,map_row,map_column,map_data,next_level_id from levels where id = %d;", level_id);ret = mysql_query(&mysql, sql);if (ret){printf("数据库查询出错,%s 错误原因:%s\n", sql, mysql_error(&mysql));mysql_close(&mysql);return false;}res = mysql_store_result(&mysql);row = mysql_fetch_row(res);if (row == NULL){cout << "查询到空数据,失败!" << endl;mysql_free_result(res);mysql_close(&mysql);return false;}level.id = level_id;level.name = row[0];level.map_row = atoi(row[1]);level.map_column = atoi(row[2]);level.map_data = row[3];level.next_level = atoi(row[4]);mysql_free_result(res);mysql_close(&mysql);return true;
}bool transform_map_dbtoarry(levelinfo& level, int map[MAP_X][MAP_Y])
{//1.合法性检查if (level.map_row > MAP_X || level.map_column > MAP_Y){cout << "给定的地图太大!" << endl;return false;}if (level.map_data.length() < 1){printf("地图数据有误,请重新设置!\n");return false;}int start = 0, end = 0;int row = 0, column = 0;do{end = level.map_data.find('|', start);//find找到最后一行,没有'|'返回-1if (end < 0){end = level.map_data.length();}if (start >= end){break;}string line = level.map_data.substr(start, end - start);printf("get line:%s\n", line.c_str());//去除逗号char* next_token = NULL;char* item = strtok_s((char*)line.c_str(), ",", &next_token);column = 0;while (item && column < level.map_column){printf("%s ", item);map[row][column] = atoi(item);column++;item = strtok_s(NULL, ",", &next_token);}if (column < level.map_column){printf("地图解析错误!\n");return false;}printf("\n");row++;if (row >= level.map_row){break;}start = end + 1;} while (1);if (row < level.map_row){printf("地图行数少于设定,%d(need:%d),终止!\n", row, level.map_row);return false;}return true;
}/******************************
* 功能:更新用户的关卡id
* 输入:user -将下一关的id赋值给user
*
* next_level_id 下一关id
*******************************/
bool update_user_level(userinfo& user, int next_level_id)
{MYSQL mysql;MYSQL_RES* res; //查询结果集MYSQL_ROW row; //记录结构体char sql[256];bool ret = false;//1.连接数据库if (connect_db(mysql) == false){return false;}//2.根据用户id更新下一关的level_idsnprintf(sql, 256, "update users set level_id = %d where id = %d;", next_level_id, user.id);ret = mysql_query(&mysql, sql);if (ret){printf("数据库更新出错,%s 错误原因:%s\n", sql, mysql_error(&mysql));mysql_close(&mysql);return false;}return true;
}
#pragma once
#include
#include "box_man.h"
#include using namespace std;typedef struct _userinfo
{int id;string username;string passwd;int level_id;
}userinfo;typedef struct _levelinfo
{int id; //关卡的idstring name; //关卡的名字int map_row; //地图的总行数int map_column; //地图的总列数string map_data; //二维地图的数据int next_level; //下一关卡的id
}levelinfo;
上一篇:正态分布,二维正态分布,卡方分布,学生t分布——概率分布学习 python
下一篇:MPViT : Multi-Path Vision Transformer for Dense Prediction