C语言+MySQL实现推箱子游戏

目录
  • 图片素材及源码
  • 数据库SQL语句
  • 操作数据库C++代码
    • database.h
    • database.cpp
  • 推箱子游戏代码
    • box_man.h
    • box_man.cpp

图片素材及源码

下载链接

数据库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 '下一关的id,0代表通关',
    primary key(id)
);
insert into users
    values(1,'Jack',md5(123456),1);
insert into levels
    values(1,'小试牛刀→第一关',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,'绝地强者→第二关',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,'天外强人→第三关',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,'死而复生→BOSS关',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);
 

操作数据库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;	// 关卡id
	string name;	// 关卡名字
	int map_row;	// 地图行数
	int map_column;	//地图列数
	string map_data;	// 二维地图数据
	int next_level;	//下一关卡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"    //数据库名
#define DB_HOST	"127.0.0.1"    //IP地址
#define DB_PORT 3306            //端口号
#define DB_USER "root"           //用户名
#define DB_USER_PASSWORD "123456"    //密码

/******************************
 *功能:数据库链接
 * 输入:
 *		mysql - 数据库访问句柄
 *
 * 返回值:
 *		true - 连接成功
 *		false - 连接失败
 *****************************/
bool connect_db(MYSQL& mysql) {
	//1.初始数据库句柄
	mysql_init(&mysql);

	//2.设置字符编码(为句柄设置)
	//windows支持中文,在windows上一般是gbk字符集,gbk包含中文简体和繁体,简体是gbk2312
	mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "gbk");

	//3.连接数据库
	//句柄,主机,用户名,密码,数据库,端口号,——,——
	if (mysql_real_connect(&mysql, DB_HOST, DB_USER, DB_USER_PASSWORD, DB_NAME, DB_PORT, 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的访问都是通过这个句柄(就是一个集合)
	MYSQL_RES* res;		// 查询的结果集
	MYSQL_ROW row;		// 如果结果集有多条,可以使用row获取
	char sql[256];
	bool ret = false;
	//1.连接数据库
	if (connect_db(mysql) == false) {
		return false;
	}
	//2.设置SQL查询语句
	//snprintf函数,设将可变参数(...)按照 format 格式化成字符串,并将字符串复制到 str 中,size 为要写入的字符的最大数目,超过 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("数据库查询出错,%s错误原因:%s\n", sql, mysql_error(&mysql));
		// 关闭数据库
		mysql_close(&mysql);
		return false;
	}

	//3.获取查到的结果
	res = mysql_store_result(&mysql);
	//row获得结果集里的一行记录,再通过下标访问记录里的数据,如果结果集有多行时可以通过 while(row = mysql_fetch_row(res)){ }循环获得
	row = mysql_fetch_row(res);

	if (row == NULL) {	//没有查到记录
		//1.释放结果集
		mysql_free_result(res);
		//1.关闭数据库
		mysql_close(&mysql);
		return false;
	}
	user.id = atoi(row[0]);	// 字符串转整数
	user.level_id = atoi(row[1]);
	//4.返回结果
	mysql_free_result(res);
	mysql_close(&mysql);
	return true;
}

/*********************************
 *功能:根据关卡id获取完整的关卡信息(如:地图,下一关等)
 * 输入:
 *		level - 保存关卡信息的结构体
 *		level_id - 获取关卡id
 * 返回值:
 *		-1 - 数据库连接或查询出错
 *		0  - 查找结果为空
 *		1 - 查找成功
 *********************************/
int fetch_level_info(levelinfo& level, int level_id) {
	MYSQL mysql;	//定义一个句柄,对mysql的访问都是通过这个句柄(就是一个集合)
	MYSQL_RES* res;		// 查询的结果集
	MYSQL_ROW row;		// 如果结果集有多条,可以使用row获取
	char sql[256];
	bool ret = false;
	//1.连接数据库
	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("数据库查询出错,%s错误原因:%s\n", sql, mysql_error(&mysql));
		// 关闭数据库
		mysql_close(&mysql);
		return -1;
	}

	//3.获取查到的结果
	res = mysql_store_result(&mysql);
	//row获得结果集里的一行记录,再通过下标访问记录里的数据,如果结果集有多行时可以通过 while(row = mysql_fetch_row(res)){ }循环获得
	row = mysql_fetch_row(res);

	if (row == NULL) {	//没有查到记录
		//1.释放结果集
		mysql_free_result(res);
		//1.关闭数据库
		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.返回结果
	mysql_free_result(res);
	mysql_close(&mysql);
	return 1;
}

/******************************
 *功能:将获得的关卡数据转换到map地图数组中
 * 输入:
 *		level - 关卡数据
 *		map - 二维地图数组
 *
 * 返回值:
 *		false - 转换失败
 *		true - 转换成功
 *****************************/
bool transform_map_db2array(levelinfo& level, int map[][COLUMN]) {
	if (level.map_row > LINE || level.map_column > COLUMN) {
		printf("地图过大,请重新设置\n");
		return false;
	}
	if (level.map_data.length() < 1) {
		printf("地图数据有误,请重新设置!\n");
		return false;
	}
	long long start = 0, end = 0;
	int row = 0, column = 0;
	do {
		/******************************
		 *find返回size_t类型值,size_t在64位下是8字节长度,因此这里把start和end设置成long long类型(不设置会有“数据丢失”警告)。当然也可以简单粗暴的修改警告设置
		******************************/
		end = level.map_data.find('|', start);
		if (end == -1) {
			end = level.map_data.length();
		}
		//合法性检查,结束时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());
		// 对行数据进行解析:0,1,0,1,1,1,1,1,1,1,0,0
		char* next_token = NULL;
		//line转为const char*(C语言中的字符串),strtok_s会修改line里的值,按照某个特定字符,所以需要将line.c_str()转为char *
		// strtok_s第一个参数是要劈开的字符串(要求是一个char *类型的);第二个参数是按某个字符劈开(会把“,”逗号变成‘\0'结束符,也就是说会修改原来字符串,所以要把原来的const char*转为char*);第三个参数是这个接口
		// 需要的,用来做定位功能,
		//printf("%p\n", &line[2]);
		char* item = strtok_s((char*)line.c_str(), ",", &next_token);
		column = 0;
	    //printf("%p", next_token);
		//::system("pause");
		//如果某行数据个数多余这个地图列数,控制只读取level.map_column-1个
		while (item&&column<level.map_column) {
			map[row][column] = atoi(item);
			column++;
			//再使用strtok_s接口第一个参数可以写NULL,应该是next_token参数上一次做定位功能时已经记录了要劈开字符串给的某个位置
			item = strtok_s(NULL, ",", &next_token);
		}

		//合法性检查
		if (column < level.map_column) {	// 某行的数据个数小于这个地图的列数
			printf("地图数据解析出错,终止!\n");
			return false;
		}
		row++;

		//列数多余的话直接舍弃
		if (row >= level.map_row) {
			break;
		}
		start = end + 1;
	} while (1 == 1);
	//列数多余则直接报错
	if (row < level.map_row) {
		printf("地图行数少于设定,终止!");
		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.连接数据库
	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("数据库更新出错,%s错误原因:%s\n", sql, mysql_error(&mysql));
		// 关闭数据库
		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.连接数据库
	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.判断查询结果
	if (ret) {
		printf("数据库更新出错,%s错误原因:%s\n", sql, mysql_error(&mysql));
		// 关闭数据库
		mysql_close(&mysql);
		return false;
	}
	user.level_id = 1;
	//4.关闭数据库
	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,	//箱子命中目标
	MAN_DES,	//人站在目标上
	VECTOR	//通关图片
};

enum  _DIRECTION {
	UP,
	DOWN,
	LEFT,
	RIGHT
};

struct _POS {
	int x;	//小人所在二维数组的行数
	int y;	//小人所在二维数组的列数
};

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];

/*****************************
* 功能:判断游戏是否结束
* 输入:
*		无
* 输出:
*		true - 未结束
*		flase - 结束
*****************************/
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;
}

/*****************************
* 功能:加载游戏结束图片
* 输入:
*		无
* 输出:
*		无
*****************************/
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;
	//图片的宽,高最后一个参数“是否拉伸”
	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坐标,y为Y坐标
{

	// 变量初始化
	DWORD* dst = GetImageBuffer();    // GetImageBuffer()函数,用于获取绘图设备的显存指针,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();       //获取绘图区的宽度,EASYX自带
	int graphHeight = getheight();     //获取绘图区的高度,EASYX自带
	int dstX = 0;    //在显存里像素的角标

	// 实现透明贴图 公式: 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; //在显存里像素的角标
			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; //在显存里像素的角标
				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
			}
		}
	}
}

/*****************************
* 功能:载入“恭喜通关”图片
* 输入:
*		无
* 输出:
*		无
*****************************/
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 - 挡墙关卡数据
*		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()) {
				//更新用户下一关关卡信息(用户通关后直接跳转下一关)
				update_user_level(user, level.next_level);
				quit=true;
			}
		}
		wait(100);
	} while (quit == false);
}

/*****************************
* 功能:根据“由用户ID获取关卡数据”的返回结果进行判断
* 输入:
*		result - 返回结果(-1:获取失败  0:用户已通关  1:获取成功)
*		level - 关卡数据
*		user - 用户信息
* 输出:
*		无
*****************************/
void judge_by_result(int result, levelinfo& level, userinfo& user) {
	if (result == 1) {
		return;
	}
	else if (result == -1) {
		closegraph();
		cout << "获取关卡数据失败,请重试!" << 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();
	//循环(读取关卡→用户操作)
	do {
		//根据用户信息加载关卡数据
		int result = fetch_level_info(level, user.level_id);
		judge_by_result(result, level, user);
		//将关卡数据数据转换到map游戏地图中
		transform_map_db2array(level, map);
		//加载游戏图片
		show_images(level);
		//小人移动
		game_operation(level, user);
		//恭喜通关
		promot_over();
	} while (1);
	std::system("pause");
	closegraph();
	return 0;
}

到此这篇关于C语言+MySQL实现推箱子游戏的文章就介绍到这了,更多相关C语言 MySQL推箱子内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言实现推箱子游戏的代码示例

    很早就想过做点小游戏了,但是一直没有机会动手.今天闲来无事,动起手来.过程还是蛮顺利的,代码也不是非常难.今天给大家分享一下~ 一.介绍 开发语言:C语言 开发工具:Dev-C++ 5.11 日期:2019年9月28日 作者:ZackSock 也不说太多多余的话了,先看一下效果图: 游戏中的人物.箱子.墙壁.球都是字符构成的.通过wasd键移动,规则的话就是推箱子的规则,也就不多说了. 二.代码实现 关于代码方面,我尽可能讲的细致.希望大家可以理解~ (1)方法列表 //主函数 void mai

  • C语言实现简单推箱子游戏

    使用C语言实现超简单的推箱子游戏,供大家参考,具体内容如下/p> 感谢您打开了这篇文章,下面我将讲述一下推箱子是如何实现的. 另外附赠适配该程序简单好用 专属推箱子地图编辑器 让您在16 * 16大地图的条件下也能轻松编辑地图. 链接:地图编辑器 本程序在没有检测到地图文件的情况下也能独自运行!代码中储存了推箱子游戏第一关的标准地图,让您在没有地图文件的情况下也能熟悉整个程序的流程! 当然,拥有地图文件会也会获得更好的游戏体验,请自行编辑. 废话不多说! 下面进入技术环节: C语言版 多功能推箱

  • C语言实现推箱子小游戏

    本文实例为大家分享了C语言实现推箱子游戏的具体代码,供大家参考,具体内容如下 #include<stdio.h> #include<string.h> #include<stdlib.h> #define N 1000 /* r目的地 o箱子 i人 x墙 路(空格) w上 a左 d右 s下 */ void menu(); int level1(); int level2(); void swap(char*,char*); int opera(char *p,int *

  • C语言实现推箱子游戏完整代码

    C语言实现推箱子游戏完整代码,供大家参考,具体内容如下 前言 自己做的,可能有些代码不够工整,或者有些小问题,但游戏的基本操作是可以实现的 代码效果 代码一共分为8个部分,4个控制上下左右移动,2个判断输赢,1个统计归为的个数,一个作图. 手动设置地图 用'0'表示空格,"1"表示墙,"2"表示箱子,"3"表示人,"4"表示终点 这样可以提高代码的移植性 如需改为手动输入地图可以直接定义一个二维数组,在给他赋值就可以了 int

  • C语言实现推箱子游戏

    每天学习一点点,每天容易一点点.一个简单的C语言程序,用来复习c语言,代码通俗易懂.有什么问题望各位不吝赐教. 本文用最简单的C语言语句写个推箱子的程序,分享给大家: /******************************************* 用最简单的C语言语句写个推箱子的程序. ********************************************/ #include <stdio.h> #include <conio.h> #include&l

  • C语言推箱子游戏实现代码

    推箱子游戏的运行规则:在街道上上小人推动箱子移动,直到把箱子移动到目的地. 思路分析: 小人及箱子的移动就是小人或者箱子和路的交换: 1 定义二维字符数组,存储地图 2 显示地图,提示游戏玩法 3 记录小人及箱子位置,并定义字符变量接收用户输入方向 4 循环判断语句 1).小人的下一步是否为路,如果为路,则移动并记录小人新位置信息 2).小人的下一步如果不是路,在判断是否为箱子,如果是箱子,在判断箱子的下一个位置是否是路,如果是路,则移动箱子和小人 3). 刷新地图 4) .判断箱子的位置,如果

  • C语言+MySQL实现推箱子游戏

    目录 图片素材及源码 数据库SQL语句 操作数据库C++代码 database.h database.cpp 推箱子游戏代码 box_man.h box_man.cpp 图片素材及源码 下载链接 数据库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, passwor

  • C语言系列之推箱子游戏

    本文实例为大家分享了C语言系列之推箱子游戏的具体代码,供大家参考,具体内容如下 输入WSAD控制行走,只需要把一个方向的代码写好了,剩下的是三个方向就是复制粘贴和简单的修改就可以了. #include <stdio.h> #include <conio.h> //键盘输入函数库 //0:空地 1:墙 2:箱子要放的位置 5:人与星号重叠5:箱子与星号重叠 3:人+-3 4:箱子:+-4 int map[10][10] = {1,1,1,1,1,1,1,1,1,1, 1,0,0,0,

  • 用C语言编写推箱子游戏

    本文实例为大家分享了C语言推箱子游戏的具体实现代码,供大家参考,具体内容如下 #include <stdio.h> #include <stdlib.h> #include<string.h> #include <conio.h> //行和列 #define ROW 10 #define COL 11 /* run this program using the console pauser or add your own getch, system(&quo

  • C语言实现推箱子游戏的地图编辑器

    推箱子地图编辑器,供大家参考,具体内容如下 由于我在写推箱子的时候苦于没有地图可以试验程序运行效果,而且去搜了好长时间都没有找到一个储存16*16地图版本的推箱子关卡数据信息的文件. 于是想到了写了一个地图编辑器用来自己设计地图的想法. 原本以为这个伟大的创意只有我才想的出来,结果搜索后才发现还有很多人有着与我相同的想法. 但,其他人写的编辑器大部分都不是C语言版本的,而这一个是C语言版本的. 另外说明一下,该编辑器的想法完全是我个人想法写出来的,不敢保证编辑习惯符合别人的习惯. 但本着,能够实

  • 基于C语言实现推箱子游戏

    本文实例为大家分享了C语言实现推箱子游戏的具体代码,供大家参考,具体内容如下 代码在vs2013上测试运行. 思想: 1):地图用二维数组实现,箱子.墙壁.人等事物用不同的数字表示,遍历二维数组,遇到不同的数字打印相应的图案即可. 2):按键移动原理:判断要移动的方向是怎样的障碍物,如果理论上可以移动的话,只需把对应位置的数字作相应更改即可. #include<stdio.h> #include<stdlib.h> #include<windows.h> #includ

  • C语言代码实现推箱子小游戏

    本文实例为大家分享了C语言实现推箱子小游戏的具体代码,供大家参考,具体内容如下 本次游戏是个推箱子第一关最简单的小游戏 有详细注释,下面是做出来的游戏界面 游戏操作说明和功能说明: 1.按wasd控制小人的上下左右移动. 2.按 r 重新开始游戏 3.游戏开始有操作介绍 4.游戏结束有胜利提示 游戏原理分析 1.游戏开始时的星星个数 = 箱子在星星上的个数时 , 游戏胜利. 2.按 r 键重新开始游戏, 我们需要定义一个量 map_1[8][8] 来保存游戏初始时的界面, 操作时我们将其赋值给

  • C语言实现简单的推箱子游戏

    本文实例为大家分享了C语言实现简单的推箱子游戏的具体代码,供大家参考,具体内容如下 项目实现的具体方案: 先安装VS2019,后安装画图工具Easyx,安装以后就可以将推箱子中的(人物,墙壁,箱子目的地,箱子)的图片加载到程序中显示出来.游戏的实现是通过程序读取键盘中输入的字母,后控制加载到程序中的人物图片的移动实现小人的移动,通过人物图片和地板图片交换位置实现人物的行走,如果人物前面是箱子图片,箱子图片前面是地板图片,则人物图片和箱子图片一起移动,直到箱子图片前面是箱子目的地图片则箱子图片将箱

  • 用C语言实现推箱子游戏实例

    目录 前言 游戏效果图 游戏开发思路 游戏逻辑的分析 源代码实现 头文件 PushBackGame.c文件 test.c文件 总结 前言 本游戏需要用到的核心技术,如下: 二维数组分支语句 技术难点: 二维数组的应用和游戏的判断逻辑 只要会以上的技术的萌新都能做出很棒的游戏,博主本身也是一枚小白,如果源代码的某些地方有不足,请大佬在评论区指出. 游戏效果图 实际游玩效果图​​​​​ 游戏开发思路 分析游戏逻辑,再根据游戏分析游戏代码逻辑写出伪代码,再分析可能存在的问题,最后一步才是开发游戏. 游

随机推荐