C語言+MySQL實現(xiàn)推箱子游戲
更新時間:2022年02月21日 09:52:24 作者:霸道小明
經(jīng)典的推箱子是一個來自日本的古老游戲,目的是在訓(xùn)練你的邏輯思考能力。本文將通過C語言和MySQL實現(xiàn)推箱子這一經(jīng)典游戲,感興趣的可以了解一下
圖片素材及源碼
數(shù)據(jù)庫SQL語句
create database box_man if not exists; use box_man; create table users ( id int not null auto_increment, username varchar(64) not null, password varchar(32) not null, level_id int default 1, primary key(id), unique key username(username) ); create table levels( id int not null auto_increment, name varchar(64) not null, map_row int not null, map_column int not null, map_data varchar(4096) not null, next_level_id int default 0 comment '下一關(guān)的id,0代表通關(guān)', primary key(id) ); insert into users values(1,'Jack',md5(123456),1); insert into levels values(1,'小試牛刀→第一關(guān)',8,10,'-1,0,0,0,0,0,0,0,-1,-1|-1,0,2,2,2,2,1,0,-1,-1|0,0,0,2,2,2,4,0,0,0|0,1,1,4,0,4,1,4,1,0|0,1,4,4,1,1,0,4,1,0|0,1,1,1,3,0,1,1,1,0|0,0,0,0,1,1,1,0,0,0,|-1,-1,-1,0,0,0,0,0,-1,-1',2), (2,'絕地強者→第二關(guān)',6,6,'0,0,0,0,0,0|0,2,2,1,1,0|0,4,4,1,3,0|0,2,1,4,0,0|0,1,1,1,0,-1|0,0,0,0,0,-1',3), (3,'天外強人→第三關(guān)',8,10,'-1,-1,0,0,0,0,0,0,-1,-1|0,0,0,1,1,1,0,0,0,0|0,1,1,1,4,1,4,1,1,0|0,1,4,1,1,1,4,1,3,0|0,0,0,4,4,0,0,0,0,0,|-1,-1,0,1,1,2,2,0,-1,-1|-1,-1,0,2,2,2,2,0,-1,-1|-1,-1,0,0,0,0,0,0,-1,-1',4), (4,'死而復(fù)生→BOSS關(guān)',8,8,'-1,0,0,0,0,0,0,-1|-1,0,2,1,2,2,0,-1|-1,0,2,1,4,2,0,-1|0,0,0,1,1,4,0,0|0,1,4,1,1,4,1,0|0,1,0,4,0,0,1,0|0,1,1,1,3,1,1,0|0,0,0,0,0,0,0,0',0);
操作數(shù)據(jù)庫C++代碼
database.h
#pragma once #include<string> using namespace std; #define LINE 48 #define COLUMN 48 typedef struct _userinfo { //這里將字符串初始為空 _userinfo() :id(0), username(""), password(""), level_id(0) {}; int id; // 用戶id string username; string password; // 密碼 int level_id; }userinfo; typedef struct _levelinfo { _levelinfo() :id(0), name(""), map_row(0), map_column(0), map_data(""), next_level(0) {}; int id; // 關(guān)卡id string name; // 關(guān)卡名字 int map_row; // 地圖行數(shù) int map_column; //地圖列數(shù) string map_data; // 二維地圖數(shù)據(jù) int next_level; //下一關(guān)卡id }levelinfo; bool fetch_user_info(userinfo& user); int fetch_level_info(levelinfo& level, int level_id); bool transform_map_db2array(levelinfo& level, int map[][COLUMN]); bool update_user_level(userinfo& user, int next_level_id); bool resiting_data(userinfo& user);
database.cpp
記得更改自己的用戶名和密碼
#include"database.h" #include<mysql.h> #include<stdio.h> // 會使用C的接口 #define DB_NAME "box_man" //數(shù)據(jù)庫名 #define DB_HOST "127.0.0.1" //IP地址 #define DB_PORT 3306 //端口號 #define DB_USER "root" //用戶名 #define DB_USER_PASSWORD "123456" //密碼 /****************************** *功能:數(shù)據(jù)庫鏈接 * 輸入: * mysql - 數(shù)據(jù)庫訪問句柄 * * 返回值: * true - 連接成功 * false - 連接失敗 *****************************/ bool connect_db(MYSQL& mysql) { //1.初始數(shù)據(jù)庫句柄 mysql_init(&mysql); //2.設(shè)置字符編碼(為句柄設(shè)置) //windows支持中文,在windows上一般是gbk字符集,gbk包含中文簡體和繁體,簡體是gbk2312 mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "gbk"); //3.連接數(shù)據(jù)庫 //句柄,主機,用戶名,密碼,數(shù)據(jù)庫,端口號,——,—— if (mysql_real_connect(&mysql, DB_HOST, DB_USER, DB_USER_PASSWORD, DB_NAME, DB_PORT, NULL, 0) == NULL) { printf("數(shù)據(jù)庫連接失敗,錯誤原因:%s\n", mysql_error(&mysql)); return false; } return true; } /****************************** *功能:通過用戶名和密碼獲取用戶信息 * 輸入: * user - 用戶信息結(jié)構(gòu)體 * * 返回值: * 獲取成功返回true,失敗false *****************************/ bool fetch_user_info(userinfo& user) { MYSQL mysql; //定義一個句柄,對mysql的訪問都是通過這個句柄(就是一個集合) MYSQL_RES* res; // 查詢的結(jié)果集 MYSQL_ROW row; // 如果結(jié)果集有多條,可以使用row獲取 char sql[256]; bool ret = false; //1.連接數(shù)據(jù)庫 if (connect_db(mysql) == false) { return false; } //2.設(shè)置SQL查詢語句 //snprintf函數(shù),設(shè)將可變參數(shù)(...)按照 format 格式化成字符串,并將字符串復(fù)制到 str 中,size 為要寫入的字符的最大數(shù)目,超過 size 會被截斷。 snprintf(sql, 256, "select id,level_id from users where username='%s' and password = md5('%s');", user.username.c_str(), user.password.c_str()); ret = mysql_query(&mysql, sql); //mysql查詢,成功返回0 if (ret) { printf("數(shù)據(jù)庫查詢出錯,%s錯誤原因:%s\n", sql, mysql_error(&mysql)); // 關(guān)閉數(shù)據(jù)庫 mysql_close(&mysql); return false; } //3.獲取查到的結(jié)果 res = mysql_store_result(&mysql); //row獲得結(jié)果集里的一行記錄,再通過下標(biāo)訪問記錄里的數(shù)據(jù),如果結(jié)果集有多行時可以通過 while(row = mysql_fetch_row(res)){ }循環(huán)獲得 row = mysql_fetch_row(res); if (row == NULL) { //沒有查到記錄 //1.釋放結(jié)果集 mysql_free_result(res); //1.關(guān)閉數(shù)據(jù)庫 mysql_close(&mysql); return false; } user.id = atoi(row[0]); // 字符串轉(zhuǎn)整數(shù) user.level_id = atoi(row[1]); //4.返回結(jié)果 mysql_free_result(res); mysql_close(&mysql); return true; } /********************************* *功能:根據(jù)關(guān)卡id獲取完整的關(guān)卡信息(如:地圖,下一關(guān)等) * 輸入: * level - 保存關(guān)卡信息的結(jié)構(gòu)體 * level_id - 獲取關(guān)卡id * 返回值: * -1 - 數(shù)據(jù)庫連接或查詢出錯 * 0 - 查找結(jié)果為空 * 1 - 查找成功 *********************************/ int fetch_level_info(levelinfo& level, int level_id) { MYSQL mysql; //定義一個句柄,對mysql的訪問都是通過這個句柄(就是一個集合) MYSQL_RES* res; // 查詢的結(jié)果集 MYSQL_ROW row; // 如果結(jié)果集有多條,可以使用row獲取 char sql[256]; bool ret = false; //1.連接數(shù)據(jù)庫 if (connect_db(mysql) == false) { return -1; } //2.編寫SQL語句 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); //mysql查詢,成功返回0 if (ret) { printf("數(shù)據(jù)庫查詢出錯,%s錯誤原因:%s\n", sql, mysql_error(&mysql)); // 關(guān)閉數(shù)據(jù)庫 mysql_close(&mysql); return -1; } //3.獲取查到的結(jié)果 res = mysql_store_result(&mysql); //row獲得結(jié)果集里的一行記錄,再通過下標(biāo)訪問記錄里的數(shù)據(jù),如果結(jié)果集有多行時可以通過 while(row = mysql_fetch_row(res)){ }循環(huán)獲得 row = mysql_fetch_row(res); if (row == NULL) { //沒有查到記錄 //1.釋放結(jié)果集 mysql_free_result(res); //1.關(guān)閉數(shù)據(jù)庫 mysql_close(&mysql); return 0; } 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]); //string用printf輸出,使用.c_str()可以返回一個const char* 的指針 //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); //4.返回結(jié)果 mysql_free_result(res); mysql_close(&mysql); return 1; } /****************************** *功能:將獲得的關(guān)卡數(shù)據(jù)轉(zhuǎn)換到map地圖數(shù)組中 * 輸入: * level - 關(guān)卡數(shù)據(jù) * map - 二維地圖數(shù)組 * * 返回值: * false - 轉(zhuǎn)換失敗 * true - 轉(zhuǎn)換成功 *****************************/ bool transform_map_db2array(levelinfo& level, int map[][COLUMN]) { if (level.map_row > LINE || level.map_column > COLUMN) { printf("地圖過大,請重新設(shè)置\n"); return false; } if (level.map_data.length() < 1) { printf("地圖數(shù)據(jù)有誤,請重新設(shè)置!\n"); return false; } long long start = 0, end = 0; int row = 0, column = 0; do { /****************************** *find返回size_t類型值,size_t在64位下是8字節(jié)長度,因此這里把start和end設(shè)置成long long類型(不設(shè)置會有“數(shù)據(jù)丟失”警告)。當(dāng)然也可以簡單粗暴的修改警告設(shè)置 ******************************/ end = level.map_data.find('|', start); if (end == -1) { end = level.map_data.length(); } //合法性檢查,結(jié)束時end=level.map_data.length,start=end+1 if (start >= end) break; string line = level.map_data.substr(start, end - start); //printf("get-line:%s\n", line.c_str()); // 對行數(shù)據(jù)進行解析:0,1,0,1,1,1,1,1,1,1,0,0 char* next_token = NULL; //line轉(zhuǎn)為const char*(C語言中的字符串),strtok_s會修改line里的值,按照某個特定字符,所以需要將line.c_str()轉(zhuǎn)為char * // strtok_s第一個參數(shù)是要劈開的字符串(要求是一個char *類型的);第二個參數(shù)是按某個字符劈開(會把“,”逗號變成‘\0'結(jié)束符,也就是說會修改原來字符串,所以要把原來的const char*轉(zhuǎn)為char*);第三個參數(shù)是這個接口 // 需要的,用來做定位功能, //printf("%p\n", &line[2]); char* item = strtok_s((char*)line.c_str(), ",", &next_token); column = 0; //printf("%p", next_token); //::system("pause"); //如果某行數(shù)據(jù)個數(shù)多余這個地圖列數(shù),控制只讀取level.map_column-1個 while (item&&column<level.map_column) { map[row][column] = atoi(item); column++; //再使用strtok_s接口第一個參數(shù)可以寫NULL,應(yīng)該是next_token參數(shù)上一次做定位功能時已經(jīng)記錄了要劈開字符串給的某個位置 item = strtok_s(NULL, ",", &next_token); } //合法性檢查 if (column < level.map_column) { // 某行的數(shù)據(jù)個數(shù)小于這個地圖的列數(shù) printf("地圖數(shù)據(jù)解析出錯,終止!\n"); return false; } row++; //列數(shù)多余的話直接舍棄 if (row >= level.map_row) { break; } start = end + 1; } while (1 == 1); //列數(shù)多余則直接報錯 if (row < level.map_row) { printf("地圖行數(shù)少于設(shè)定,終止!"); return false; } return true; } /****************************** *功能:更新用戶游戲進度信息 * 輸入: * user - 用戶信息 * next_level_id - 游戲進度 * * 返回值: * 獲取成功返回true,失敗false *****************************/ bool update_user_level(userinfo& user, int next_level_id) { MYSQL mysql; //定義一個句柄,對mysql的訪問都是通過這個句柄(就是一個集合) char sql[256]; bool ret = false; //1.連接數(shù)據(jù)庫 if (connect_db(mysql) == false) { return false; } //2.編寫SQL語句 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("數(shù)據(jù)庫更新出錯,%s錯誤原因:%s\n", sql, mysql_error(&mysql)); // 關(guān)閉數(shù)據(jù)庫 mysql_close(&mysql); return false; } user.level_id = next_level_id; mysql_close(&mysql); return true; } /****************************** *功能:重置用戶游戲進度信息 * 輸入: * user - 用戶信息 * * 返回值: * false - 重置失敗 * true - 重置成功 *****************************/ bool resiting_data(userinfo& user) { MYSQL mysql; //定義一個句柄,對mysql的訪問都是通過這個句柄(就是一個集合) char sql[256]; bool ret = false; //1.連接數(shù)據(jù)庫 if (connect_db(mysql) == false) { return false; } //2.編寫SQL語句 snprintf(sql, 256, "update users set level_id=1 where id=%d", user.id); ret = mysql_query(&mysql, sql); //3.判斷查詢結(jié)果 if (ret) { printf("數(shù)據(jù)庫更新出錯,%s錯誤原因:%s\n", sql, mysql_error(&mysql)); // 關(guān)閉數(shù)據(jù)庫 mysql_close(&mysql); return false; } user.level_id = 1; //4.關(guān)閉數(shù)據(jù)庫 mysql_close(&mysql); return true; }
推箱子游戲代碼
box_man.h
#pragma once #define RATIO 40 #define SCREEN_WIDTH 740 #define SCREEN_HEIGHT 500 #define START_X 50 #define START_Y 75 #define KEY_UP 'W' #define KEY_LEFT 'A' #define KEY_RIGHT 'D' #define KEY_DOWN 'S' #define KEY_OUT 'Q' #define GAME_AGAIN 'R' #define MAX_RETRY_TIMES 4 #define BG_IMAGE -1 #define isValid(next_pos) next_pos.x > 0 && next_pos.x < LINE && next_pos.y>0 && next_pos.y < COLUMN typedef enum _PROPS PROPS; typedef enum _DIRECTION DIRECTION; typedef struct _POS POS; enum _PROPS { WALL, //墻 FLOOR, //地板 BOX_DES,//箱子目的地 MAN, //小人 BOX, //箱子 HIT, //箱子命中目標(biāo) MAN_DES, //人站在目標(biāo)上 VECTOR //通關(guān)圖片 }; enum _DIRECTION { UP, DOWN, LEFT, RIGHT }; struct _POS { int x; //小人所在二維數(shù)組的行數(shù) int y; //小人所在二維數(shù)組的列數(shù) };
box_man.cpp
#include<graphics.h> #include<iostream> #include<stdlib.h> #include<string> #include<conio.h> //??? #include"box_man.h" #include"database.h" using namespace std; int map[LINE][COLUMN] = { 0 }; POS man; IMAGE images[9]; /***************************** * 功能:判斷游戲是否結(jié)束 * 輸入: * 無 * 輸出: * true - 未結(jié)束 * flase - 結(jié)束 *****************************/ bool isGameOver() { for (int i = 0; i < LINE; ++i) { for (int j = 0; j < COLUMN; ++j) { if (map[i][j] == BOX_DES) return false; } } return true; } /***************************** * 功能:加載游戲結(jié)束圖片 * 輸入: * 無 * 輸出: * 無 *****************************/ void show_over() { cleardevice(); IMAGE game_over; loadimage(&game_over, _T("gameover.png"), SCREEN_WIDTH, SCREEN_HEIGHT, true); putimage(0, 0, &game_over); } /***************************** * 功能:在指定位置更改地圖信息 顯示指定圖片 * 輸入: * next_pos - 指定位置 * prop - 指定圖片 * 輸出: * 無 *****************************/ void changeMap(POS* next_pos, PROPS prop) { map[next_pos->x][next_pos->y] = prop; putimage(START_X + next_pos->y * RATIO, START_Y + next_pos->x * RATIO, &images[prop]); } /***************************** * 功能:在指定位置顯示指定圖片 * 輸入: * next_pos - 指定位置 * prop - 指定圖片 * 輸出: * 無 *****************************/ void changeMap2(POS* next_pos, PROPS prop) { putimage(START_X + next_pos->y * RATIO, START_Y + next_pos->x * RATIO, &images[prop]); } /***************************** * 功能:控制小人向指定方向移動 * 輸入: * direct - 指定方向 * 輸出: * 無 *****************************/ void gameControl(DIRECTION direct) { POS next_pos = man; 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; } //宏展開next_pos.x > 0 && next_pos.x < LINE && next_pos.y>0 && next_pos.y < COLUMN // 人的前方是地板 if (isValid(next_pos) && map[next_pos.x][next_pos.y] == FLOOR) { //人的腳下是目的地 if (map[man.x][man.y] == BOX_DES) { changeMap(&next_pos, MAN); changeMap2(&man, BOX_DES); } else { changeMap(&man, FLOOR); changeMap(&next_pos, MAN); } man = next_pos; } // 人的前方是箱子 else if (isValid(next_next_pos) && map[next_pos.x][next_pos.y] == BOX) { if (map[next_next_pos.x][next_next_pos.y] == FLOOR) { // 箱子的前方是地板 changeMap(&next_next_pos, BOX); changeMap(&next_pos, MAN); if (map[man.x][man.y] == BOX_DES) { changeMap(&man, BOX_DES); } else { changeMap(&man, FLOOR); } man = next_pos; } else if (map[next_next_pos.x][next_next_pos.y] == BOX_DES) { // 箱子前面是目的地 changeMap(&next_next_pos, HIT); changeMap(&next_pos, MAN); if (map[man.x][man.y] == BOX_DES) { changeMap(&man, BOX_DES); } else { changeMap(&man, FLOOR); } man = next_pos; } } //前方是目的地 else if (isValid(next_pos) && map[next_pos.x][next_pos.y] == BOX_DES) { //小人腳下也是目的地 if (map[man.x][man.y] == BOX_DES) { changeMap2(&next_pos, MAN_DES); changeMap(&man, BOX_DES); } else { changeMap(&man, FLOOR); changeMap2(&next_pos, MAN_DES); } man = next_pos; } //前方是箱子命中點 else if (isValid(next_pos) && map[next_pos.x][next_pos.y] == HIT) { if (map[next_next_pos.x][next_next_pos.y] == FLOOR) { // 箱子的前方是地板 changeMap(&next_next_pos, BOX); changeMap(&next_pos, BOX_DES); changeMap2(&next_pos, MAN_DES); //人的腳下是目的地 if (map[man.x][man.y] == BOX_DES) { changeMap(&man, BOX_DES); } else { changeMap(&man, FLOOR); } man = next_pos; } else if (map[next_next_pos.x][next_next_pos.y] == BOX_DES) { // 箱子前面是目的地 changeMap(&next_next_pos, HIT); changeMap(&next_pos, BOX_DES); changeMap2(&next_pos, MAN_DES); //人的腳下是目的地 if (map[man.x][man.y] == BOX_DES) { changeMap(&man, BOX_DES); } else { changeMap(&man, FLOOR); } man = next_pos; } } } /***************************** * 功能:用戶登錄 * 輸入: * user - 用戶信息 * 輸出: * false - 登錄失敗 * true - 登錄成功 *****************************/ bool login(userinfo& user) { int times = 0; bool ret = false; do { cout << "請輸入用戶名:"; cin >> user.username; cout << "請輸入密碼:"; cin >> user.password; ret = fetch_user_info(user); times++; if (times >= MAX_RETRY_TIMES) break; if (ret == false) { cout << "登錄失敗,請重新輸入!" << endl; } } while (!ret); return ret; } /***************************** * 功能:加載游戲素材 * 輸入: * 無 * 輸出: * 無 *****************************/ void init_graph() { initgraph(SCREEN_WIDTH, SCREEN_HEIGHT); loadimage(&images[WALL], _T("wall_right.bmp"), RATIO, RATIO, true); loadimage(&images[FLOOR], _T("floor.bmp"), RATIO, RATIO, true); loadimage(&images[BOX_DES], _T("des.bmp"), RATIO, RATIO, true); loadimage(&images[MAN], _T("man.bmp"), RATIO, RATIO, true); loadimage(&images[BOX], _T("box.jpg"), RATIO, RATIO, true); loadimage(&images[HIT], _T("box_des.jpg"), RATIO, RATIO, true); loadimage(&images[MAN_DES], _T("man_des.bmp"), RATIO, RATIO, true); loadimage(&images[VECTOR], _T("vector.png"), 6*RATIO, 6*RATIO, true); } /***************************** * 功能:顯示指定地圖 * 輸入: * level - 指定地圖 * 輸出: * 無 *****************************/ void show_images(levelinfo& level) { cleardevice(); // 每次貼圖清屏一下 IMAGE bg_img; //圖片的寬,高最后一個參數(shù)“是否拉伸” loadimage(&bg_img, _T("bgimage.png"), SCREEN_WIDTH, SCREEN_HEIGHT, true); putimage(0, 0, &bg_img); 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; } if (map[i][j] == BG_IMAGE) continue; putimage(START_X + j * RATIO, START_Y + i * RATIO, &images[map[i][j]]); } } const char* str = level.name.c_str(); setbkmode(TRANSPARENT); setfont(RATIO, 0, _T("華文楷體")); setcolor(WHITE); outtextxy(200, 25, str); } /***************************** * 功能:載入PNG圖并去透明部分 * 輸入: * 無 * 輸出: * 無 *****************************/ void drawAlpha(IMAGE* picture, int picture_x, int picture_y) //x為載入圖片的X坐標(biāo),y為Y坐標(biāo) { // 變量初始化 DWORD* dst = GetImageBuffer(); // GetImageBuffer()函數(shù),用于獲取繪圖設(shè)備的顯存指針,EASYX自帶 DWORD* draw = GetImageBuffer(); DWORD* src = GetImageBuffer(picture); //獲取picture的顯存指針 int picture_width = picture->getwidth(); //獲取picture的寬度,EASYX自帶 int picture_height = picture->getheight(); //獲取picture的高度,EASYX自帶 int graphWidth = getwidth(); //獲取繪圖區(qū)的寬度,EASYX自帶 int graphHeight = getheight(); //獲取繪圖區(qū)的高度,EASYX自帶 int dstX = 0; //在顯存里像素的角標(biāo) // 實現(xiàn)透明貼圖 公式: Cp=αp*FP+(1-αp)*BP , 貝葉斯定理來進行點顏色的概率計算 for (int iy = 0; iy < picture_height; iy++) { for (int ix = 0; ix < picture_width; ix++) { int srcX = ix + iy * picture_width; //在顯存里像素的角標(biāo) int sa = ((src[srcX] & 0xff000000) >> 24); //0xAArrggbb;AA是透明度 int sr = ((src[srcX] & 0xff0000) >> 16); //獲取RGB里的R int sg = ((src[srcX] & 0xff00) >> 8); //G int sb = src[srcX] & 0xff; //B if (ix >= 0 && ix <= graphWidth && iy >= 0 && iy <= graphHeight && dstX <= graphWidth * graphHeight) { dstX = (ix + picture_x) + (iy + picture_y) * graphWidth; //在顯存里像素的角標(biāo) int dr = ((dst[dstX] & 0xff0000) >> 16); int dg = ((dst[dstX] & 0xff00) >> 8); int db = dst[dstX] & 0xff; draw[dstX] = ((sr * sa / 255 + dr * (255 - sa) / 255) << 16) //公式: Cp=αp*FP+(1-αp)*BP ; αp=sa/255 , FP=sr , BP=dr | ((sg * sa / 255 + dg * (255 - sa) / 255) << 8) //αp=sa/255 , FP=sg , BP=dg | (sb * sa / 255 + db * (255 - sa) / 255); //αp=sa/255 , FP=sb , BP=db } } } } /***************************** * 功能:載入“恭喜通關(guān)”圖片 * 輸入: * 無 * 輸出: * 無 *****************************/ void promot_over() { setbkmode(TRANSPARENT); drawAlpha(&images[VECTOR], 250, 130); // 載入PNG圖并去透明部分 Sleep(1100); } /***************************** * 功能:休眠 * 輸入: * interval - 休眠時間 * 輸出: * 無 *****************************/ void wait(int interval) { int count = interval / 10; for (int i = 0; i < count; ++i) { Sleep(10); if (_kbhit()) return; } } /***************************** * 功能:游戲控制 * 輸入: * level - 擋墻關(guān)卡數(shù)據(jù) * user - 用戶信息 * 輸出: * 無 *****************************/ void game_operation(levelinfo& level, userinfo& user) { bool quit = false; do { //判斷是否有按鍵按下 if (_kbhit()) { //無緩沖讀取 char ch = _getch(); if (ch == KEY_UP) { gameControl(UP); } else if (ch == KEY_DOWN) { gameControl(DOWN); } else if (ch == KEY_LEFT) { gameControl(LEFT); } else if (ch == KEY_RIGHT) { gameControl(RIGHT); } else if (ch == GAME_AGAIN) { fetch_level_info(level, user.level_id); transform_map_db2array(level, map); show_images(level); } else if (ch == KEY_OUT) { closegraph(); exit(0); } if (isGameOver()) { //更新用戶下一關(guān)關(guān)卡信息(用戶通關(guān)后直接跳轉(zhuǎn)下一關(guān)) update_user_level(user, level.next_level); quit=true; } } wait(100); } while (quit == false); } /***************************** * 功能:根據(jù)“由用戶ID獲取關(guān)卡數(shù)據(jù)”的返回結(jié)果進行判斷 * 輸入: * result - 返回結(jié)果(-1:獲取失敗 0:用戶已通關(guān) 1:獲取成功) * level - 關(guān)卡數(shù)據(jù) * user - 用戶信息 * 輸出: * 無 *****************************/ void judge_by_result(int result, levelinfo& level, userinfo& user) { if (result == 1) { return; } else if (result == -1) { closegraph(); cout << "獲取關(guān)卡數(shù)據(jù)失敗,請重試!" << endl; std::system("pause"); exit(-1); } else if (result == 0) { show_over(); do { //判斷是否有按鍵按下 if (_kbhit()) { //無緩沖讀取 char ch = _getch(); if (ch == KEY_OUT) { closegraph(); exit(0); } else if (ch == GAME_AGAIN) { if (!resiting_data(user)) { std::system("pause"); closegraph(); exit(0); } break; } } Sleep(50); } while (1); fetch_level_info(level, user.level_id); } } int main() { //用戶身份驗證 userinfo user; levelinfo level; if (!login(user)) { cout << "登錄失敗,請重新登錄!" << endl; ::system("pause"); exit(-1); } init_graph(); //循環(huán)(讀取關(guān)卡→用戶操作) do { //根據(jù)用戶信息加載關(guān)卡數(shù)據(jù) int result = fetch_level_info(level, user.level_id); judge_by_result(result, level, user); //將關(guān)卡數(shù)據(jù)數(shù)據(jù)轉(zhuǎn)換到map游戲地圖中 transform_map_db2array(level, map); //加載游戲圖片 show_images(level); //小人移動 game_operation(level, user); //恭喜通關(guān) promot_over(); } while (1); std::system("pause"); closegraph(); return 0; }
到此這篇關(guān)于C語言+MySQL實現(xiàn)推箱子游戲的文章就介紹到這了,更多相關(guān)C語言 MySQL推箱子內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++編譯報錯:||error: ld returned 1 exit 
這篇文章主要介紹了C++編譯報錯:||error: ld returned 1 exit status|的解決方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01C++ 中的虛函數(shù)表及虛函數(shù)執(zhí)行原理詳解
這篇文章主要介紹了C++ 中的虛函數(shù)表及虛函數(shù)執(zhí)行原理詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03VS2010+Opencv+MFC讀取圖像和視頻顯示在Picture控件
這篇文章主要為大家詳細介紹了VS2010+Opencv+MFC讀取圖像和視頻顯示在Picture控件,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-08-08