实现一个基本的推箱子游戏,包括地图初始化、显示、玩家和箱子的移动逻辑,以及游戏循环。通过键盘控制玩家可以移动玩家和箱子,游戏的目标是将所有箱子推到目标位置。
本游戏参考地图
#define green "\033[42;31m \033[0m"
#define red "\033[41;31m \033[0m"//红色
#define black "\033[40;31m \033[0m"//黑色
#define yellow "\033[43;37m \033[0m"
#define blue "\033[44;37m \033[0m"
#define pink "\033[45;37m \033[0m"
#define l_blue "\033[46;37m \033[0m"
#define white "\033[47;37m \033[0m"
//初始化渲染颜色类型
//0路 1墙 2目的地 3箱子 4玩家 5箱子目的地 6玩家目的地 7背景
#define bg_color white
#define wall_color yellow
#define space_color green //"\033[42;31m \033[0m"
#define box_color black
#define target_color pink //"\033[43;31m \033[0m"
#define self_color blue//"\033[46;31m \033[0m"浅蓝色
#define boxTarget_color red
#define selfTarget_color l_blue
使用ANSI转义序列定义了多种颜色宏,用于在控制台输出时改变文本的颜色。这些宏通过\033[
后跟颜色代码来设置颜色,然后\033[0m
用于重置颜色。
粗略参考如下
地图因为只做了一关的缘故,所以只有一个maps1如果以后做多个关卡或者想存入数据库,可以改成三维数组的形式例如maps[index][mapX][mapY]
#define map1X 10
#define map1Y 10
int maps1[map1X][map1Y] =
{
{7,1,1,1,1,1,1,7,7,7},
{7,1,2,0,2,2,1,7,7,7},
{7,1,2,0,3,2,1,7,7,7},
{1,1,1,0,0,3,1,1,7,7},
{1,0,3,0,0,3,0,1,7,7},
{1,0,1,3,1,1,0,1,7,7},
{1,0,0,0,4,0,0,1,7,7},
{1,1,1,1,1,1,1,1,7,7},
{7,7,7,7,7,7,7,7,7,7},
{7,7,7,7,7,7,7,7,7,7}
};
void maps_Init(int map[][map1Y]) {
// 使用memcpy复制maps1的内容到map
//TODO加一个该关卡参数,通过不同的关卡值初始化不同的地图
int maps1[map1X][map1Y] =
{
{7,1,1,1,1,1,1,7,7,7},
{7,1,2,0,2,2,1,7,7,7},
{7,1,2,0,3,2,1,7,7,7},
{1,1,1,0,0,3,1,1,7,7},
{1,0,3,0,0,3,0,1,7,7},
{1,0,1,3,1,1,0,1,7,7},
{1,0,0,0,4,0,0,1,7,7},
{1,1,1,1,1,1,1,1,7,7},
{7,7,7,7,7,7,7,7,7,7},
{7,7,7,7,7,7,7,7,7,7}
};
memcpy(map, maps1, map1X * map1Y * sizeof(int));
}
maps_Show函数负责显示当前的地图状态。它首先清空控制台,然后遍历地图数组,对每个元素根据其值打印相应的颜色和符号。
在遍历过程中,如果发现有箱子没有被推到目标位置,就设置isWin为0,表示游戏未赢。
void maps_Show() {
printf("\033[H\033[2J");
int isWin = 1;
for (int i = 0; i < map1X; i++) {
for (int j = 0; j < map1Y; j++) {
switch (maps1[i][j])
{
case 0: {
printf(space_color);
break;
}
case 1: {
printf(wall_color);
break;
}
case 2: {
printf(target_color);
break;
}
case 3: {
printf(box_color);
break;
}
case 4: {
printf(self_color);
break;
}
case 5: {
printf(boxTarget_color);
break;
}
case 6: {
printf(selfTarget_color);
break;
}
case 7: {
printf(bg_color);
break;
}
default:
break;
}
}
printf("\n");
}
for (int i = 0; i < map1X; i++) {
for (int j = 0; j < map1Y; j++) {
if (maps1[i][j] == 3) {
isWin = 0;
break;
}
}
if (!isWin) {
break;
}
}
if (isWin) {
printf("\033[H\033[2J");
printf("#####宝宝,你好厉害#####\n");
Sleep(5000);
maps_Init(maps1);
}
}
moveP函数处理玩家的移动操作。根据用户的键盘输入(w/a/s/d),更新玩家的位置,并尝试将箱子移动到目标位置。
如果玩家或箱子移动到目标位置,会更新地图中的相应元素。
void moveP()
{
//获取玩家坐标
int pX = 0, pY = 0;
for (pX = 0; pX < map1X; pX++) {
for (pY = 0; pY < map1Y; pY++) {
if (maps1[pX][pY] == 4 || maps1[pX][pY] == 6) {
break;
}
}
if (maps1[pX][pY] == 4 || maps1[pX][pY] == 6) {
break;
}
}
switch (_getch())
{
case 'w':
case 'W':
if (maps1[pX - 1][pY] == 0 || maps1[pX - 1][pY] == 2)
{
maps1[pX - 1][pY] += 4; // 玩家移动到上方
maps1[pX][pY] -= 4; // 玩家消失在原位置
}
else if (maps1[pX - 1][pY] == 3 || maps1[pX - 1][pY] == 3 + 2) // BOX + DEST
{
if (maps1[pX - 2][pY] == 0 || maps1[pX - 2][pY] == 2)
{
maps1[pX - 2][pY] += 3; // BOX移动到上方
maps1[pX - 1][pY] = maps1[pX - 1][pY] - 3 + 4; // BOX + PLAYER
maps1[pX][pY] -= 4; // 玩家消失在原来位置
}
}
break;
case 'a':
case 'A':
if (maps1[pX][pY - 1] == 0 || maps1[pX][pY - 1] == 2)
{
maps1[pX][pY - 1] += 4;
maps1[pX][pY] -= 4;
}
else if (maps1[pX][pY - 1] == 3 || maps1[pX][pY - 1] == 3 + 2)
{
if (maps1[pX][pY - 2] == 0 || maps1[pX][pY - 2] == 2)
{
maps1[pX][pY - 2] += 3;
maps1[pX][pY - 1] = maps1[pX][pY - 1] - 3 + 4;
maps1[pX][pY] -= 4;
}
}
break;
case's':
case'S':
if (maps1[pX + 1][pY] == 0 || maps1[pX + 1][pY] == 2)
{
maps1[pX + 1][pY] += 4;
maps1[pX][pY] -= 4;
}
else if (maps1[pX + 1][pY] == 3 || maps1[pX + 1][pY] == 3 + 2)
{
if (maps1[pX + 2][pY] == 0 || maps1[pX + 2][pY] == 2)
{
maps1[pX + 2][pY] += 3;
maps1[pX + 1][pY] = maps1[pX + 1][pY] - 3 + 4;
maps1[pX][pY] -= 4;
}
}
break;
case'd':
case'D':
if (maps1[pX][pY + 1] == 0 || maps1[pX][pY + 1] == 2)
{
maps1[pX][pY + 1] += 4;
maps1[pX][pY] -= 4;
}
else if (maps1[pX][pY + 1] == 3 || maps1[pX][pY + 1] == 3 + 2)
{
if (maps1[pX][pY + 2] == 0 || maps1[pX][pY + 2] == 2)
{
maps1[pX][pY + 2] += 3;
maps1[pX][pY + 1] = maps1[pX][pY + 1] - 3 + 4;
maps1[pX][pY] -= 4;
}
}
break;
case 'r':
case 'R':
{
maps_Init(maps1);
}
default:
break;
}
}
main函数首先隐藏光标(printf("\033[?25l")),然后调用pushBoxStart_Init启动游戏。
pushBoxStart_Init函数启动游戏,首先调用maps_Init初始化地图,然后显示地图和游戏规则,进入游戏循环。
在游戏循环中,调用moveP处理玩家的移动操作,然后调用maps_Show更新地图显示。
以后可以在Start_Init里加入选关卡菜单,并且定义一个变量用来获取关卡值通过这个变量改变初始化的地图
//TODO关卡选择菜单
void pushBoxStart_Init() {
maps_Init(maps1);
maps_Show();
printf(" **** **** **** **** **** **** **** **** \n");
printf(" * * \n");
printf(" * 这是一个推箱子游戏 * \n");
printf(" * 按wasd移动 * \n");
printf(" * 按r重置地图 * \n");
printf(" * 按q退出游戏 * \n");
printf(" * 黑色是箱子 * \n");
printf(" * 紫色是目的地 * \n");
printf(" * 蓝色是玩家 * \n");
printf(" * 绿色是路 * \n");
printf(" **** **** **** **** **** **** **** **** \n");
while (1) {
moveP();
maps_Show();
}
}
int main() {
printf("\033[?25l");
pushBoxStart_Init();
return 0;
}
#include<Windows.h>
#include<stdio.h>
#include<conio.h>
#define green "\033[42;31m \033[0m"
#define red "\033[41;31m \033[0m"//红色
#define black "\033[40;31m \033[0m"//黑色
#define yellow "\033[43;37m \033[0m"
#define blue "\033[44;37m \033[0m"
#define pink "\033[45;37m \033[0m"
#define l_blue "\033[46;37m \033[0m"
#define white "\033[47;37m \033[0m"
//初始化渲染颜色类型
//0路 1墙 2目的地 3箱子 4玩家 5箱子目的地 6玩家目的地 7背景
#define bg_color white
#define wall_color yellow
#define space_color green //"\033[42;31m \033[0m"
#define box_color black
#define target_color pink //"\033[43;31m \033[0m"
#define self_color blue//"\033[46;31m \033[0m"浅蓝色
#define boxTarget_color red
#define selfTarget_color l_blue
#define map1X 10
#define map1Y 10
int maps1[map1X][map1Y] =
{
{7,1,1,1,1,1,1,7,7,7},
{7,1,2,0,2,2,1,7,7,7},
{7,1,2,0,3,2,1,7,7,7},
{1,1,1,0,0,3,1,1,7,7},
{1,0,3,0,0,3,0,1,7,7},
{1,0,1,3,1,1,0,1,7,7},
{1,0,0,0,4,0,0,1,7,7},
{1,1,1,1,1,1,1,1,7,7},
{7,7,7,7,7,7,7,7,7,7},
{7,7,7,7,7,7,7,7,7,7}
};
void maps_Init(int map[][map1Y]) {
// 使用memcpy复制maps1的内容到map
//TODO加一个该关卡参数,通过不同的关卡值初始化不同的地图
int maps1[map1X][map1Y] =
{
{7,1,1,1,1,1,1,7,7,7},
{7,1,2,0,2,2,1,7,7,7},
{7,1,2,0,3,2,1,7,7,7},
{1,1,1,0,0,3,1,1,7,7},
{1,0,3,0,0,3,0,1,7,7},
{1,0,1,3,1,1,0,1,7,7},
{1,0,0,0,4,0,0,1,7,7},
{1,1,1,1,1,1,1,1,7,7},
{7,7,7,7,7,7,7,7,7,7},
{7,7,7,7,7,7,7,7,7,7}
};
memcpy(map, maps1, map1X * map1Y * sizeof(int));
}
void maps_Show() {
printf("\033[H\033[2J");
int isWin = 1;
for (int i = 0; i < map1X; i++) {
for (int j = 0; j < map1Y; j++) {
switch (maps1[i][j])
{
case 0: {
printf(space_color);
break;
}
case 1: {
printf(wall_color);
break;
}
case 2: {
printf(target_color);
break;
}
case 3: {
printf(box_color);
break;
}
case 4: {
printf(self_color);
break;
}
case 5: {
printf(boxTarget_color);
break;
}
case 6: {
printf(selfTarget_color);
break;
}
case 7: {
printf(bg_color);
break;
}
default:
break;
}
}
printf("\n");
}
for (int i = 0; i < map1X; i++) {
for (int j = 0; j < map1Y; j++) {
if (maps1[i][j] == 3) {
isWin = 0;
break;
}
}
if (!isWin) {
break;
}
}
if (isWin) {
printf("\033[H\033[2J");
printf("#####宝宝,你好厉害#####\n");
Sleep(5000);
maps_Init(maps1);
}
}
void moveP()
{
//获取玩家坐标
int pX = 0, pY = 0;
for (pX = 0; pX < map1X; pX++) {
for (pY = 0; pY < map1Y; pY++) {
if (maps1[pX][pY] == 4 || maps1[pX][pY] == 6) {
break;
}
}
if (maps1[pX][pY] == 4 || maps1[pX][pY] == 6) {
break;
}
}
switch (_getch())
{
case 'w':
case 'W':
if (maps1[pX - 1][pY] == 0 || maps1[pX - 1][pY] == 2)
{
maps1[pX - 1][pY] += 4; // 玩家移动到上方
maps1[pX][pY] -= 4; // 玩家消失在原位置
}
else if (maps1[pX - 1][pY] == 3 || maps1[pX - 1][pY] == 3 + 2) // BOX + DEST
{
if (maps1[pX - 2][pY] == 0 || maps1[pX - 2][pY] == 2)
{
maps1[pX - 2][pY] += 3; // BOX移动到上方
maps1[pX - 1][pY] = maps1[pX - 1][pY] - 3 + 4; // BOX + PLAYER
maps1[pX][pY] -= 4; // 玩家消失在原来位置
}
}
break;
case 'a':
case 'A':
if (maps1[pX][pY - 1] == 0 || maps1[pX][pY - 1] == 2)
{
maps1[pX][pY - 1] += 4;
maps1[pX][pY] -= 4;
}
else if (maps1[pX][pY - 1] == 3 || maps1[pX][pY - 1] == 3 + 2)
{
if (maps1[pX][pY - 2] == 0 || maps1[pX][pY - 2] == 2)
{
maps1[pX][pY - 2] += 3;
maps1[pX][pY - 1] = maps1[pX][pY - 1] - 3 + 4;
maps1[pX][pY] -= 4;
}
}
break;
case's':
case'S':
if (maps1[pX + 1][pY] == 0 || maps1[pX + 1][pY] == 2)
{
maps1[pX + 1][pY] += 4;
maps1[pX][pY] -= 4;
}
else if (maps1[pX + 1][pY] == 3 || maps1[pX + 1][pY] == 3 + 2)
{
if (maps1[pX + 2][pY] == 0 || maps1[pX + 2][pY] == 2)
{
maps1[pX + 2][pY] += 3;
maps1[pX + 1][pY] = maps1[pX + 1][pY] - 3 + 4;
maps1[pX][pY] -= 4;
}
}
break;
case'd':
case'D':
if (maps1[pX][pY + 1] == 0 || maps1[pX][pY + 1] == 2)
{
maps1[pX][pY + 1] += 4;
maps1[pX][pY] -= 4;
}
else if (maps1[pX][pY + 1] == 3 || maps1[pX][pY + 1] == 3 + 2)
{
if (maps1[pX][pY + 2] == 0 || maps1[pX][pY + 2] == 2)
{
maps1[pX][pY + 2] += 3;
maps1[pX][pY + 1] = maps1[pX][pY + 1] - 3 + 4;
maps1[pX][pY] -= 4;
}
}
break;
case 'r':
case 'R':
{
maps_Init(maps1);
}
default:
break;
}
}
//TODO关卡选择菜单
void pushBoxStart_Init() {
maps_Init(maps1);
maps_Show();
printf(" **** **** **** **** **** **** **** **** \n");
printf(" * * \n");
printf(" * 这是一个推箱子游戏 * \n");
printf(" * 按wasd移动 * \n");
printf(" * 按r重置地图 * \n");
printf(" * 按q退出游戏 * \n");
printf(" * 黑色是箱子 * \n");
printf(" * 紫色是目的地 * \n");
printf(" * 蓝色是玩家 * \n");
printf(" * 绿色是路 * \n");
printf(" **** **** **** **** **** **** **** **** \n");
while (1) {
moveP();
maps_Show();
}
}
int main() {
printf("\033[?25l");
pushBoxStart_Init();
return 0;
}
引入图形库,加颜色渲染改成图片渲染,加入多个关卡选项打包成.exe文件发给朋友游玩
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。