首页 > 其他分享 >C语言实现推箱子小游戏

C语言实现推箱子小游戏

时间:2022-11-17 20:41:27浏览次数:35  
标签:case 箱子 level C语言 break PLAYER map 小游戏 BOX


C语言实现推箱子小游戏
包括黑窗图形界面
参考视频 https://www.bilibili.com/video/BV1By4y1a79o?t=4428
BUG:当人进入到目的地的时候会无法移动。

#include<stdio.h>
#include<stdlib.h>
//这个库函数不是C 语言标准的,在VS上可以直接用,在Linux上就不行。
#include<conio.h>
//使用布尔类型
#include<stdbool.h>
//使用图形界面-图形界面头文件(需要安装)
#include<graphics.h>
//推箱子
//知识点:数组 、函数、
//开发环境 vs2019
//准备地图数据 用二维数组来存储
//表示——空地 0 墙 1 目的地 2 箱子 3 玩家 4
//这两个是动态变化的 箱子+目的地 5 玩家+目的地 6
//难点在于判断移动导致的变化

#define SPACE 0
#define WALL 1
#define DEST 2
#define BOX 3
#define PLAYER 4
#define ROW 10
#define COL 10
//当前所在关卡
int level = 0;


//变成3纬数组 可以存多个地图
int map[3][ROW][COL] =
{
//设计地图样式
//map1
{
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,1,1,1,0,0,0,0},
{0,0,0,1,2,1,0,0,0,0},
{0,0,0,1,3,1,1,1,1,0},
{0,1,1,1,0,3,0,2,1,0},
{0,1,2,3,4,0,1,1,1,0},
{0,1,1,1,1,3,1,0,0,0},
{0,0,0,0,1,2,1,0,0,0},
{0,0,0,0,1,1,1,0,0,0},
{0,0,0,0,0,0,0,0,0,0}
},
//map2
{
{0,0,0,0,0,0,0,0,0,0},
{0,0,1,1,0,0,1,1,0,0},
{0,1,0,2,1,1,2,0,1,0},
{1,0,0,0,0,0,0,0,0,1},
{1,0,0,3,0,3,0,0,0,1},
{1,0,0,0,4,0,0,0,0,1},
{0,1,0,3,0,3,0,0,1,0},
{0,0,1,2,0,0,2,1,0,0},
{0,0,0,1,0,0,1,0,0,0},
{0,0,0,0,1,1,0,0,0,0}
},
//map3
{
{0,0,0,0,0,0,0,0,0,0},
{0,1,1,1,1,1,1,1,1,0},
{0,1,2,0,0,0,0,2,1,0},
{0,1,0,0,0,0,0,0,1,0},
{0,1,0,3,0,3,0,0,1,0},
{0,1,0,0,4,0,0,0,1,0},
{0,1,0,3,0,3,0,0,1,0},
{0,1,2,0,0,0,0,2,1,0},
{0,1,1,1,1,1,1,1,1,0},
{0,0,0,0,0,0,0,0,0,0}
}
};
//定义一个图片的数组int image
IMAGE img[6];
//加载图片
void loadImg()
{
for (int i = 0; i < 6; i++)
{
char temFileName[50] = { 0 };
sprintf_s(temFileName,"./images/%d.bmp", i);
loadimage(img + i, temFileName, 63, 63); //项目属性-高级-字符集-使用多字符字符集
}
}
void DrawMap()
{
for (int i = 0; i < 10; i++)
{
for (int k = 0; k < 10; k++)
{
switch (map[level][i][k])
{
case SPACE:
putimage(k * 63, i * 63, img + 0);
break;
case WALL:
putimage(k * 63, i * 63, img + 1);
break;
case DEST:
putimage(k * 63, i * 63, img + 2);
break;
case BOX:
putimage(k * 63, i * 63, img + 3);
break;
case PLAYER:
putimage(k * 63, i * 63, img + 4);
break;
case BOX + DEST:
putimage(k * 63, i * 63, img + 5);
break;
case PLAYER + DEST:
putimage(k * 63, i * 63, img + 5);
break;
default:
printf("%d ", map[level][i][k]);
break;
}
}
printf("\n");
}
}
void show()
{
for (int i = 0; i < 10; i++)
{
for (int k = 0; k < 10; k++)
{
switch (map[level][i][k])
{
case SPACE:
printf(" ");
break;
case WALL:
printf("▓");
break;
case DEST:
printf("☆");
break;
case BOX:
printf("★");
break;
case PLAYER:
printf("♂");
break;
case BOX + DEST:
printf("◇");
break;
case PLAYER + DEST:
printf("♀");
break;
default:
printf("%d ", map[level][i][k]);
break;
}
}
printf("\n");
}
}
void pushBox()
{
//找到玩家所在的下标
//地图里面哪些数据有可能是玩家
//PLAYER PLAYER+DEST
int i = 0;
int k = 0;
for ( i = 0; i < 10; i++)
{
for ( k = 0; k<10; k++)
{
if (map[level][i][k] == PLAYER)
{
goto end;
break;
}
}
}
end:;//goto到这里
//获取键盘按键 - _getch()-一触即发不需要按回车 getchar()-输入之后需要按回车
char key = _getch();
//printf("%d %c\n", key, key);
switch (key)
{
case 'w':
case 'W':
case 72://向上移动
//什么情况下 玩家才能移动 才能推箱子?
//玩家的前面是空地(目的地)、玩家的前面是箱子(箱子的前面是什么) 可以动
//如果玩家的前面是空地
if (map[level][i- 1][k] == SPACE || map[level][i - 1][k] == DEST)
{
map[level][i - 1][k] += PLAYER;
map[level][i][k] -= PLAYER;
}
else if(map[level][i-1][k] == BOX)//玩家的前面是箱子
{
if (map[level][i - 2][k] == SPACE || map[level][i - 2][k] == DEST)//箱子的前面是空地或者是目的地
{
map[level][i - 2][k] += BOX;
map[level][i - 1][k] += (PLAYER - BOX);
map[level][i][k] -= PLAYER;
}
}
break;
case 's':
case 'S':
case 80://向下移动
if (map[level][i + 1][k] == SPACE || map[level][i + 1][k] == DEST)
{
map[level][i + 1][k] += PLAYER;
map[level][i][k] -= PLAYER;
}
else if (map[level][i + 1][k] == BOX)//玩家的前面是箱子
{
if (map[level][i + 2][k] == SPACE || map[level][i + 2][k] == DEST)//箱子的前面是空地或者是目的地
{
map[level][i + 2][k] += BOX;
map[level][i + 1][k] += (PLAYER - BOX);
map[level][i][k] -= PLAYER;
}
}
break;
case 'a':
case 'A':
case 75://向左移动
if (map[level][i][k - 1] == SPACE || map[level][i][k - 1] == DEST)
{
map[level][i][k - 1] += PLAYER;
map[level][i][k] -= PLAYER;
}
else if (map[level][i][k - 1] == BOX)//玩家的前面是箱子
{
if (map[level][i][k - 2] == SPACE || map[level][i][k - 2] == DEST)//箱子的前面是空地或者是目的地
{
map[level][i][k - 2] += BOX;
map[level][i][k - 1] += (PLAYER - BOX);
map[level][i][k] -= PLAYER;
}
}
break;
case 'd':
case 'D':
case 77://向右移动
if (map[level][i][k + 1] == SPACE || map[level][i][k + 1] == DEST)
{
map[level][i][k + 1] += PLAYER;
map[level][i][k] -= PLAYER;
}
else if (map[level][i][k + 1] == BOX)//玩家的前面是箱子
{
if (map[level][i][k + 2] == SPACE || map[level][i][k + 2] == DEST)//箱子的前面是空地或者是目的地
{
map[level][i][k + 2] += BOX;
map[level][i][k + 1] += (PLAYER - BOX);
map[level][i][k] -= PLAYER;
}
}
break;
default:
break;
}
}
//什么情况下才过关呢,当前关卡没有箱子了 就通关了
bool Judge()
{
for (int i = 0; i < ROW; i++)
{
for (int k = 0; k < COL; k++)
{
if(map[level][i][k] == BOX)
{
return false;
}
}
}
return true;
}
int main(void)
{
//设置黑窗口的大小
system("mode con cols=30 lines=20");//设置cols和lines数值的时候不能有空格,否则会报错。
//创建图形界面窗口
//参数 窗口的宽度 高度 SHOWCONSOLE表示同时显示控制台和控制台
initgraph(ROW*63,COL*63,SHOWCONSOLE);
//Easyx只能用于C++,所以源文件后缀改为.cpp
loadImg();
while (1)
{
system("cls");
show();
DrawMap();
//判断是否过关
if (Judge())
{
//切换关卡
level++;//最大只有三关,超过了就数组越界了
if (level > 2)
{
exit(0);
}
printf("按任意键进入下一关......\n");
}
pushBox();
}

//getchar();——防止闪退的,加了while 1就不需要了
return 0;
}


标签:case,箱子,level,C语言,break,PLAYER,map,小游戏,BOX
From: https://blog.51cto.com/u_15333750/5866120

相关文章

  • C语言自定义数据类型
    结构体参考视频:https://www.bilibili.com/video/BV1oi4y1g7CF?p=58大纲:结构体的声明结构体的自引用结构体内存对齐结构体传参结构体实现位段(位段的填充&可移植性)charshor......
  • C语言实现飞翔的小鸟小游戏
    参考视频https://www.bilibili.com/video/BV1Xo4y1R7hs缺陷:撞柱子功能暂未实现//飞翔的小鸟#include<stdio.h>//C语言标准头文件#include<graphics.h>//图形库头文件#includ......
  • C语言实现数字字母雨小程序
    //字母数字雨#include<stdio.h>//随机数头文件#include<stdlib.h>//包含easyX图形库可以使用绘图函数以及鼠标操作#include<graphics.h>#include<conio.h>#defineSTR_SIZ......
  • C语言类型转换
    类型转换类型转换:在C语言中,当一个运算符的几个操作数类型不同时,编译器会在进行运算之前将他们共同转化为某种一样的数据类型,一般来说编译器会先将占用内存较小的数据转化为......
  • C语言简单的猜数字游戏
    #include<stdio.h>#include<stdlib.h>#include<time.h>intmain(void){intnum=0;srand((unsigned)time(NULL));inti=rand();while(scanf("%d",&num)!=EO......
  • C语言动态内存开辟
    1.动态内存管理1.为什么存在动态内存管理当前我们知道的内存的使用方式主要是两种。1.创建一个变量inta=10;//局部变量-在栈区中开辟空间intg_a=10;//全局变量-静......
  • C语言编写Web服务器
    相关视频——C/C++技术教学:web网络服务器开发!纯C语言手写web服务器,仅需80行代码,制作出你的专属服务器_哔哩哔哩(゜-゜)つロ干杯~-bilibili我的小站——半生瓜的blog,同......
  • C语言实现图书管理系统
    相关视频——C语言课程设计实战:图书管理系统!计算机专业同学的一大难题,今天用代码实战演示,手把手带你完成!_哔哩哔哩(゜-゜)つロ干杯~-bilibili我的小站——半生瓜のblog1.......
  • C语言的灵魂——指针
    相关视频——强烈推荐【强烈推荐】4小时彻底掌握C指针-顶尖程序员图文讲解-UP主亲自翻译校对(已完结)_哔哩哔哩(゜-゜)つロ干杯~-bilibili我的小站——半生瓜のblog......
  • 【c&c++】C语言中#ifdef,#ifndef和#endif的作用
    现在规定一下头文件书写规范,根据陈皓编写的跟我一起些makefile,一定要记住:头文件中应该只是声明,而定义应该放在C/C++文件中。否则如果出现有定义,比如头文件中有inta=2;如......