推箱子(数据库版)


本文章是由小主的<<推箱子游戏>>文章的升级版,加上了数据库

一.用户登录

步骤:(配合下边的代码)
首先请用户输入信息到一个结构体变量user中,输入后将user放到fetch_user_info()函数中判断(连数据库->查询记录->判断是否有该用户->接收记录),如果该用户在数据库中就开始游戏!

fetch_user_info()的判断步骤:
1.先用connect_db()函数连接数据库,
2.根据用户名和密码获取用户信息(本质就是在c++编译器中使用数据库中的语句,操作数据库,这里先定义一个字符串sql,然后用snprintf(),将用户输入的数据和查询语句一起放到qsl字符串中,因为用户信息不一样,所以用snprintf()复制,之后数据库会根据语句查询,如果成功返回真,否则返回假)
3.返回结果 将查询的所有记录传给res 在把res中的记录,一行一行用row表示出来,这里因为就一行,所以没有循环, 将一行记录中的用户id和关卡id传出来,atoi用来转换数据类型
4.关闭数据库

connect_db() 函数解释:
(1)先初始化句柄
(2)因为MYsQL的字符集和vs2019不一样,所以需要先转换一下
(3).连接数据库,这里需要数据库用户和密码,以及一些端口信息

数据库里关于用户和关卡的信息(这里用户james的密码为123456 用了md5加密 )
在这里插入图片描述

首先建立一个database.h和database.cpp文件,用来存储数据库的一些操作

database.h
定义一个用户的结构体用来存储信息
一个用户获取信息的函数

#pragma once
#include <string>
using namespace std;
//用户信息
typedef struct _userinfo {
	int id;            //用户id
	string username;   //用户名
	string passwd;     //密码
	int level_id;      //关卡id
}userinfo;

bool fetch_user_info(userinfo& user);

database.cpp

#include"database.h"
#include<mysql.h>
#include<stdio.h>

#define DB_NAME "box_man"
#define DB_HOST "127.0.0.1"
#define DB_POST 3306
#define DB_USER "root"
#define DB_USER_PASSWD "123456Aa"

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.根据用户名和密码获取用户信息
	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);
	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_POST, NULL, 0)==NULL) {
		printf("数据库连接失败,错误原因:%s\n",mysql_error(&mysql));
		return false;
	}
	return true;
}

二.通过关卡id获取关卡的信息

步骤:根据第一步获取的用户信息,将用户关卡id放入fetch_level_info()中获取挂关卡信息;

fetch_level_info()的判断步骤:
1.先用connect_db()函数连接数据库,
2.根据关卡id查询数据库 获取关卡地图信息
3.返回结果 将查询的所有记录传给res 在把res中的记录,一行一行用row表示出来,这里因为就一行,所以没有循环, 将一行记录中的用户id和关卡id传出来,atoi用来转换数据类型
4.关闭数据库

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

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_colum, 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[4]);
	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.关闭数据库
	mysql_free_result(res);
	mysql_close(&mysql);
	return true;
}

三.根据用户所在的关卡id获取关卡的数据

步骤:就是通过transform_map_dbtoarry()函数,将获取的地图信息的坐标赋值给map数组(将地图数据一行一行一个一个的分解,复制给)

transform_map_dbtoarry()函数讲解: 它有两个参数,分别是地图信息和二维数组map。
先判断是否是越界
将数据分解成一行一行的,用 | 来区一行的结尾在哪,之后line接收一行
再对这一行分解,利用strtok_s()进行分解,分解出一个后,赋值给map,
在分解每一个的时候列+1,分解行的时候行数+1,之后不断循环,即可找出

bool transform_map_dbtoarry(levelinfo& level, int map[MAP_X][MAP_Y])
{
	if (level.map_row > MAP_X || level.map_column > MAP_Y) {
		printf("地图太大,请重新设置!\n");
		return false;
	}
	if (level.map_data.length() < 1) {
		printf("地图数据有误,请重新设置!\n");
		return false;
	}
	int strat = 0, end = 0;
	int row = 0, column = 0;
	//一行一行的获取(通过|来分割),然后对一行中的每一个数据进行解析,把他们放到数组中
	do {
		end = level.map_data.find('|', strat);
		if (end < 0) {
			end = level.map_data.length();
			//如果到达了最后一行,因为最后一行没有|,所以返回-1,
			//但是因为这一行也需要解析,所以end为最后那一个数据位置
		}
		if (strat >= end) {
		    break;
		}
		string line = level.map_data.substr(strat, end - strat);
		printf("get line:%s\n", line.c_str());
		//对地图进行解析
		char* next_token = NULL;
		char* item = strtok_s((char*)line.c_str(), ",", &next_token);
		//strtok_s()函数,将line字符串进行分割,第一次需要写入字符串,以后就可以设置为空
		//截断后的首地址赋值给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;
		}
		strat = end + 1;
	} while (1);
	if (row < level.map_row) {
		printf("地图行数少于设定,%d(need:%d),终止!\n",row,level.map_row);
		return false;
	}
	return true;
}

四.跳转下一关

步骤: 修改以前的代码,以前的玩了一个就结束了,而如果想跳转的话需要加循环,
如果本关闯过去了,判断是否还有下一关,如果有,那么将下一关的id赋值给用户关卡id,之后下次循环的时候,数据库通过访问
用户就可以获取新的关卡id了,再将这些信息赋值给level完成闭环

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;
	}
	return true;
}

五.数据库信息

建立了一个box_man数据库,里面有两个表,一个是用户信息,一个是关卡信息
这里一共写了七关.
在这里插入图片描述

六.全部代码

datebase.h

#pragma once
#include <string>
#include"boxman.h"
using namespace std;
//用户信息
typedef struct _userinfo {
	int id;            //用户id
	string username;   //用户名
	string passwd;     //密码
	int level_id;      //关卡id
}userinfo;
typedef struct _levelinfo {
	int id;            //关卡的id
	string name;      //关卡的名字
	int map_row;      //地图的总行数
	int map_column;   //地图的总列数
	string map_data;  //二维地图的数据
	int next_level;   //下一关卡的id
}levelinfo;
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);

datebase.cpp

#include"database.h"
#include<mysql.h>
#include<stdio.h>

#define DB_NAME "box_man"
#define DB_HOST "127.0.0.1"
#define DB_POST 3306
#define DB_USER "root"
#define DB_USER_PASSWD "123456Aa"

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.根据用户名和密码获取用户信息
	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);
	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;
}
/*************************************
*功能:通过关卡的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_colum, 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[4]);
	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.关闭数据库
	mysql_free_result(res);
	mysql_close(&mysql);
	return true;
}

bool transform_map_dbtoarry(levelinfo& level, int map[MAP_X][MAP_Y])
{
	if (level.map_row > MAP_X || level.map_column > MAP_Y) {
		printf("地图太大,请重新设置!\n");
		return false;
	}
	if (level.map_data.length() < 1) {
		printf("地图数据有误,请重新设置!\n");
		return false;
	}
	int strat = 0, end = 0;
	int row = 0, column = 0;
	//一行一行的获取(通过|来分割),然后对一行中的每一个数据进行解析,把他们放到数组中
	do {
		end = level.map_data.find('|', strat);
		if (end < 0) {
			end = level.map_data.length();
			//如果到达了最后一行,因为最后一行没有|,所以返回-1,
			//但是因为这一行也需要解析,所以end为最后那一个数据位置
		}
		if (strat >= end) {
		    break;
		}
		string line = level.map_data.substr(strat, end - strat);
		printf("get line:%s\n", line.c_str());
		//对地图进行解析
		char* next_token = NULL;
		char* item = strtok_s((char*)line.c_str(), ",", &next_token);
		//strtok_s()函数,将line字符串进行分割,第一次需要写入字符串,以后就可以设置为空
		//截断后的首地址赋值给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;
		}
		strat = 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_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;
	}
	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_POST, NULL, 0)==NULL) {
		printf("数据库连接失败,错误原因:%s\n",mysql_error(&mysql));
		return false;
	}
	return true;
}

boxman.h

#pragma once
#define KEY_UP 'w'
#define KEY_DOWN 's'
#define KEY_LEFT 'a'
#define KEY_RIGHT 'd'
#define KEY_QUITE 'q'
#define MAP_X 48  
#define MAP_Y 48
#define RATIO 61   //像素点
#define SCREEN_WIDTH 960
#define SCREEN_HEIGHT 768
#define isValid(pos)  pos.x>=0 && pos.x<MAP_X&&pos.y>=0 &&pos.y<MAP_Y
#define MAX_RETRY_TIMES 3
typedef enum _PROPS			PROPS;
typedef enum _DIRECTION		DIRECTION;
typedef struct _POS			POS;

struct _POS {
	int x;  //小人所在二维数组的行
	int y;  //小人所在二维数组的列
};
enum _PROPS {
	WALL,    //墙
	FLOOR,	//地板
	BOX_DES,//箱子的目的地
	MAN,    //主角
	BOX,    //箱子 
	HIT,   //箱子已经退到目的地
	ALL    //道具的个数
};
enum _DIRECTION {
	UP,
	DOWN,
	LEFT,
	RIGHT
};

boxman.cpp

#include<graphics.h>
#include<Windows.h>
#include<stdlib.h>
#include<string>
#include<iostream>
#include<conio.h>
#include"boxman.h"
#include <iostream>
#include"database.h"

using namespace std;
int hold = 0;  //用来标记是否小人踩在目的地上
struct _POS man;  //小人在二维数组中的位置
IMAGE images[ALL];    //加载图片的数组
int map[MAP_X][MAP_Y] = {0};
/*int map[MAP_X][MAP_Y] = {
	{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},
};*/
void changeMap(POS* pos, PROPS prop);
void gameControl(DIRECTION direction);
bool isGameover();
void Gameover(IMAGE* bg);
void gameNextScene(IMAGE* bg);
bool login(userinfo& user);
void welcome(IMAGE& bg_img);
void init_game_graph(IMAGE& bg_img);
int main() {
	//用户身份验证
	userinfo user;
	levelinfo level;
	bool ret = false;
	IMAGE bg_img;          //用来承接图片
	if (!login(user)) {
		cout << "登录失败,请重新登录" << endl;
		::system("pause");
		exit(-1);
	}
	else {
		cout << "登录成功,稍后进入游戏" << endl;
		::system("pause");
	}
	//初始化舞台
	welcome(bg_img);
	::system("pause");
	init_game_graph(bg_img);

	bool quite = false; 
	do {
		hold = 0;//每次到新的一关人物肯定不在目的地
		//根据用户所在的关卡id获取关卡的数据
		ret = fetch_level_info(level, user.level_id);
		if (!ret) {
			cout << "获取关卡数据失败,请重试!" << endl;
			::system("pause");
			exit(-1);
		}
		//把数据库中的地图数据转换到map中
		ret = transform_map_dbtoarry(level, map);
		if (!ret) {
			cout << "转化地图失败,请重试!" << endl;
			::system("pause");
			exit(-1);
		}
		if (!ret) {
			printf("适配失败!\n");
			exit(-1);
		}
		//::system("pause");


		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(100 + j * 61, 150 + i * 61, &images[map[i][j]]);
			}
		}
	
		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 == KEY_QUITE) {
					quite = true;
				}
				else if (ch == KEY_RENWE) {
					break;
				}
				if (isGameover()) {
					
					if (level.next_level < 1) {
						Gameover(&bg_img);
						quite = 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;
					//quite = true;
				}
			}
		    Sleep(100);
		} while (!quite);

	}while(quite == false);
	::system("pause");
	closegraph();
	return 0;
}
/************
*   作用:显示道具
*   line:道具在数组的列坐标
*	cloumn:道具在数组的行坐标
*	prop:道具的类型
*
**************/
void changeMap(POS* pos, PROPS prop) {
	map[pos->x][pos->y] = prop;
	putimage(100 + pos->y * RATIO, 150 + pos->x * RATIO, &images[prop]);
}
/************
实现游戏四个方向(上,下,左,右)的控制
**************/
void gameControl(DIRECTION direction) {
	POS next_pos = man;
	POS next_next_pos = man;
	switch (direction) {
	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;

	}   //isValid()为宏展开
	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) {//小人前方是否为目的地
		if (hold == 1) {
			changeMap(&next_pos, MAN);
			changeMap(&man, BOX_DES);
			man = next_pos;
		}
		else {
			changeMap(&next_pos, MAN);
			changeMap(&man, FLOOR);
			man = next_pos;
			hold = 1;
		}
	}
	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) {  //判断箱子前面是都为地板
			if (hold == 0) {
				changeMap(&next_pos, MAN);
				changeMap(&man, FLOOR);
				man = next_pos;
				changeMap(&next_next_pos, BOX);
			}
			else {
				changeMap(&next_pos, MAN);
				changeMap(&man, BOX_DES);
				man = next_pos;
				changeMap(&next_next_pos, BOX);
				hold = 0;
			}
		}
		else if (map[next_next_pos.x][next_next_pos.y] == BOX_DES) { //判断箱子前方是否为目的地
			if (hold==1) {
				changeMap(&next_pos, MAN);
				changeMap(&man, BOX_DES);
				man = next_pos;
				changeMap(&next_next_pos, HIT);
				hold = 0;
			}
			else {
				changeMap(&next_pos, MAN);
				changeMap(&man, FLOOR);
				man = next_pos;
				changeMap(&next_next_pos, HIT);
			}
		}
	}
	else if (isValid(next_next_pos) && map[next_pos.x][next_pos.y] == HIT) { //判断小人前方是否箱子目的地重合的地方
		if (hold == 1) {
			changeMap(&next_pos, MAN);
			changeMap(&man, BOX_DES);
			man = next_pos;
			changeMap(&next_next_pos, BOX);
		}else {
			changeMap(&next_pos, MAN);
			changeMap(&man, FLOOR);
			man = next_pos;
			changeMap(&next_next_pos, BOX);
			hold = 1;
		}
	}
}
/*根据用户输入的数据,访问数据库进行登录*/
bool login(userinfo& user) {
	int times = 0;
	bool ret = false;
	do {
		cout << "请输入用户名:";
		cin >> user.username;
		cout << "请输入密码:";
		cin >> user.passwd;

		ret = fetch_user_info(user);
		times++;
		if (times >= MAX_RETRY_TIMES) {
			break;
		}
		if (ret == false) {
			cout << "登录失败,请重新尝试!" << endl;
		}
	} while (!ret);
	return ret;
}
void init_game_graph(IMAGE& bg_img) {

	initgraph(960, 768);   //搭建戏台
	loadimage(&bg_img, _T("blackground.bmp"), 960, 768, true);//加载背景图片
	putimage(0, 0, &bg_img);  //显示图片
	loadimage(&images[WALL], _T("wall.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.bmp"), RATIO, RATIO, true);
	loadimage(&images[HIT], _T("box.bmp"), RATIO, RATIO, true);

}
/************
*判断游戏是否结束
*如果数组中不存在任何一个箱子目的地,就代表游戏结束
*
*
**************/
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 welcome(IMAGE& bg_img){
	initgraph(960, 768);   //搭建戏台
	loadimage(&bg_img, _T("welcome.bmp"), 960, 768, true);//加载背景图片
	putimage(0, 0, &bg_img);  //显示图片
}
/*
显示游戏结束画面
*/
void Gameover(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);
}
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();
}

七.演示效果

开始界面:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值