因为地图是从文件中读取,所以关卡地图发成了资源。

key.cpp

#include <conio.h>
#include "pushBox.h"//键盘操作(改变核心数据)
void key(){unsigned char key = 0;key = _getch();//调用getch方法,获取按下的键盘某个键的键值;此方法为阻塞方法,会卡在这里,直到用户按下了某个按键switch (key){case 'A':case 'a'://a,左{direction=3;manMove();Direction[_key]=direction;_key++;}break;case 'D':case 'd'://d,右{direction=4;manMove();Direction[_key]=direction;_key++;}break;case 'W':case 'w'://w,上{direction=1;manMove();Direction[_key]=direction;_key++;}break;case 'S':case 's'://s,下{direction=2;manMove();Direction[_key]=direction;_key++;}break;case 'N':case 'n'://按下N键,直接跳关到下一关nextLevel();break;case 'B':case 'b'://按下B键,直接跳关到上一关beforeLevel();break;case 'C':case 'c'://按下C键,返回上一步goback();break;break;case 'R':case 'r'://按下R键,重新开始restart();break;case 'G':case 'g'://按下G键,选择关卡xuanguan();break;}
}

main.cpp

#include <conio.h>
#include "paint.h"
#include "key.h"
#include "pushBox.h"int main(){//load_level_1();//加载第一关地图loadMapFromFile(1);//加载第一关地图initPaint();startDurationTimer();//开启游戏主窗口之后,打开定时器while(1){paintAll();key();}return 0;
}

paint.cpp

#include <stdio.h>
#include "EasyXPng.h"
#include "pushBox.h"
#include "paint.h"//1.定义图片对象
IMAGE pic_back;
IMAGE_PNG pic_man;
IMAGE pic_outer_wall;
IMAGE pic_inner_wall;
IMAGE pic_ball;
IMAGE pic_box;
IMAGE pic_box_on_ball;int pikaquCount = 0;//当前该绘制哪一张皮卡丘图片
IMAGE_PNG pikaqu[16];//存放皮卡丘的16张动画图片HANDLE hMutex;//加载所有图片
void loadAllImages(){//2.加载图片文件到图片对象loadimage(&pic_back, "imgs/back.jpg", WINDOW_WIDTH, WINDOW_HEIGHT);loadimage(&pic_outer_wall, "imgs/wall_outside.bmp", GRID_SIZE, GRID_SIZE);loadimage(&pic_inner_wall, "imgs/wall_inside.bmp", GRID_SIZE, GRID_SIZE);loadimage(&pic_ball, "imgs/ball.bmp", GRID_SIZE, GRID_SIZE);loadimage(&pic_box, "imgs/box.bmp", GRID_SIZE, GRID_SIZE);loadimage(&pic_box_on_ball, "imgs/box_pushed.bmp", GRID_SIZE, GRID_SIZE);//加载17张皮卡丘的动画图片loadimage(&pikaqu[0], "imgs/pikaqu/pi01.png", GRID_SIZE, GRID_SIZE);loadimage(&pikaqu[1], "imgs/pikaqu/pi02.png", GRID_SIZE, GRID_SIZE);loadimage(&pikaqu[2], "imgs/pikaqu/pi03.png", GRID_SIZE, GRID_SIZE);loadimage(&pikaqu[3], "imgs/pikaqu/pi04.png", GRID_SIZE, GRID_SIZE);loadimage(&pikaqu[4], "imgs/pikaqu/pi05.png", GRID_SIZE, GRID_SIZE);loadimage(&pikaqu[5], "imgs/pikaqu/pi06.png", GRID_SIZE, GRID_SIZE);loadimage(&pikaqu[6], "imgs/pikaqu/pi07.png", GRID_SIZE, GRID_SIZE);loadimage(&pikaqu[7], "imgs/pikaqu/pi08.png", GRID_SIZE, GRID_SIZE);loadimage(&pikaqu[8], "imgs/pikaqu/pi09.png", GRID_SIZE, GRID_SIZE);loadimage(&pikaqu[9], "imgs/pikaqu/pi10.png", GRID_SIZE, GRID_SIZE);loadimage(&pikaqu[10], "imgs/pikaqu/pi01.png", GRID_SIZE, GRID_SIZE);loadimage(&pikaqu[11], "imgs/pikaqu/pi02.png", GRID_SIZE, GRID_SIZE);loadimage(&pikaqu[12], "imgs/pikaqu/pi03.png", GRID_SIZE, GRID_SIZE);loadimage(&pikaqu[13], "imgs/pikaqu/pi04.png", GRID_SIZE, GRID_SIZE);loadimage(&pikaqu[14], "imgs/pikaqu/pi05.png", GRID_SIZE, GRID_SIZE);loadimage(&pikaqu[15], "imgs/pikaqu/pi06.png", GRID_SIZE, GRID_SIZE);}//加载所有图片资源,并打开主窗口
void initPaint(){hMutex = CreateMutex(NULL,FALSE,NULL);loadAllImages();//打开主窗口,指定窗口宽和高initgraphEx(WINDOW_WIDTH, WINDOW_HEIGHT);
}//根据核心数据,绘制界面所有元素
void paintAll(){WaitForSingleObject(hMutex,INFINITE);//利用双缓冲技术,把图像绘制到双缓冲中,加速图像绘制、显示的过程BeginBatchDrawEx();//开始批量绘图,此刻起,绘制的所有内容,都是绘制在内存中(缓冲区)的,显示器无法看到//3.把加载完毕的图片对象,贴到窗口上putimage(0, 0, &pic_back);//绘制背景//绘制人物所在游戏范围setlinecolor(YELLOW);setlinestyle(PS_SOLID, 3);rectangle(BEGIN_X, BEGIN_Y, BEGIN_X + GRID_N * GRID_SIZE, BEGIN_Y + GRID_N * GRID_SIZE);setlinecolor(RED);setlinestyle(PS_SOLID, 3);rectangle(5, 90,280,500);//根据核心地图数据,遍历它,把每一格元素,根据下标计算出它的像素位置,并绘制到界面上for(int k = 0; k < 3; k++){for(int x = 0; x < GRID_N; x++){for(int y = 0; y < GRID_N; y++){switch(map[k][x][y]){case OUTERE_WALL:putimage(BEGIN_X + x * GRID_SIZE, BEGIN_Y + y * GRID_SIZE, &pic_outer_wall);break;case INNER_WALL:putimage(BEGIN_X + x * GRID_SIZE, BEGIN_Y + y * GRID_SIZE, &pic_inner_wall);break;case BALL:putimage(BEGIN_X + x * GRID_SIZE, BEGIN_Y + y * GRID_SIZE, &pic_ball);break;case BOX:if(map[1][x][y] == BALL){putimage(BEGIN_X + x * GRID_SIZE, BEGIN_Y + y * GRID_SIZE, &pic_box_on_ball);}else{putimage(BEGIN_X + x * GRID_SIZE, BEGIN_Y + y * GRID_SIZE, &pic_box);}break;}}}}//putimage(BEGIN_X + manX * GRID_SIZE, BEGIN_Y + manY * GRID_SIZE, &pic_man);//绘制人物图片//绘制当前某一帧的人物图像(根据定时器的推动,自行计算出,该绘制哪一副皮卡丘图片)putimage(BEGIN_X + manX * GRID_SIZE, BEGIN_Y + manY * GRID_SIZE, &pikaqu[pikaquCount]);//绘制游戏选项setbkmode(TRANSPARENT);//设定文字绘制的背景为透明settextstyle(20, 0, "宋体");//设置文字大小和字体settextcolor(YELLOW);//设置文字颜色char buffer[1024];sprintf(buffer, "当前关卡:第%d关", level);char steps[1024];sprintf(steps,"步数:%d步",step);outtextxy(10, 100, buffer);//在界面上显示当前关卡数outtextxy(10, 200, "上一关:B");outtextxy(10, 250, "下一关:N");outtextxy(10, 300,steps);outtextxy(10, 350, "返回上一步:C");outtextxy(10, 400, "重新开始:R");outtextxy(10, 450, "选关:G:输入关卡+回车");//绘制当前关卡经过的时长sprintf(buffer, "经过时长:%d秒", duration / 10);outtextxy(10, 150, buffer);EndBatchDrawEx();//结束批量绘图ReleaseMutex(hMutex);
}

pushBox.cpp

#include <stdio.h>
#include "EasyXPng.h"
#include "paint.h"
#include "pushBox.h"//定义人的坐标(格子数)
int manX = 0;
int manY = 0;//定义地图,存放界面中所有格子元素
//第0层存放内墙
//第1层存放小球
//第2层存放:外墙、箱子、人
int map[3][GRID_N][GRID_N] = {0};//当前第几关
int level = 1;
int step=0;
int _key=1;
int direction=0;
int Direction[1024]={0};//当前关卡已度过的时长,单位为0.1秒
int duration = 0;//此方法为定时器自动调用的回调方法,此方法会被每隔0.1秒钟调用一次,我们在此,对当前关卡时长总数进行加1
VOID CALLBACK currentTimer(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime)
{duration++;//当前关卡时长总数进行加1//同时,让皮卡丘动画的当前图像下标,加1,推动动画pikaquCount++;if(pikaquCount >= 16){pikaquCount = 0;}paintAll();//重新绘制界面所有内容
}//调用此方法,开启一个间隔时间为0.1秒(100毫秒)的定时器
void startDurationTimer()
{KillTimer(GetHWnd(), 1);//杀掉ID为1的定时器SetTimer(GetHWnd(), 1, 150, currentTimer);//开启一个ID为1的定时器,时间间隔为0.1秒
}//调用此方法,给定关卡数字,内部会从关卡文件夹中加载对应的地图文件(比如:100.txt)
void loadMapFromFile(int _level){FILE * fp;//文件指针,指向一个已经打开的文件char buffer[1024];//定义字符串缓存,用于存放拼接好的字符串内容sprintf(buffer, "levels/%d.txt", _level);//根据格式化,把当前关卡数值,拼接到文件路径字符串中fp = fopen(buffer, "r");//打开指定的地图文件int element;//临时存放从文件中读取出来的一块元素的值//比如:1为外墙、2为内墙、3为小球、4为箱子(下面没有小球)、5为人、6为在小球上的箱子for(int y  = 0; y < GRID_N; y++){for(int x = 0; x < GRID_N; x++){fscanf(fp, "%d", &element);//从fp指向的已打开文件中,读取一个数字,存放到element变量中(代表某种游戏元素)switch(element){case OUTERE_WALL:map[2][x][y] = OUTERE_WALL;break;case INNER_WALL:map[0][x][y] = INNER_WALL;break;case BALL:map[1][x][y] = BALL;map[0][x][y] = INNER_WALL;break;case BOX:map[2][x][y] = BOX;map[0][x][y] = INNER_WALL;break;case MAN:manX = x;manY = y;map[0][x][y] = INNER_WALL;break;case BOX_ON_BALL:map[2][x][y] = BOX;map[1][x][y] = BALL;map[0][x][y] = INNER_WALL;break;}}}fclose(fp);//文件打开用完后,记得关闭
}
void xuanguan()
{scanf("%d",&level);level--;nextLevel();
}//此方法,负责判断输赢:1:胜利;0:未胜利
int isWin(){for(int x  = 0; x < GRID_N; x++){for(int y = 0; y < GRID_N; y++){if(map[2][x][y] == BOX && map[1][x][y] != BALL){return 0;}}}_key=1;step=0;return  1;
}//清空地图
void clearMap(){for(int k = 0; k < 3; k++){for(int x = 0; x < GRID_N; x++){for(int y = 0; y < GRID_N; y++){map[k][x][y] = EMPTY;}}}_key=1;Direction[0]=0;step=0;
}//此方法,负责加载下一关地图(根据当前第几关)
void nextLevel(){if(level == 100){level = 1;}else{step=0;_key=1;level++;}clearMap();//在加载新地图前,清空当前地图数据loadMapFromFile(level);//根据当前关卡,加载对应地图文件
}//此方法,负责加载上一关地图(根据当前第几关)
void beforeLevel(){if(level > 1){step=0;_key=1;level--;}else{return;}clearMap();//在加载新地图前,清空当前地图数据loadMapFromFile(level);//根据当前关卡,加载对应地图文件
}
void restart(){//重玩函数clearMap();
loadMapFromFile(level);
}//调用此方法,检查是否产生输赢,若胜利则加载下一关地图!
int checkAndPass(){if(isWin() == 1){nextLevel();return 1;}return 0;
}
void goback(){if(_key>0){_key--;direction=Direction[_key];switch(direction){case 0:break;case 10:{map[2][manX][manY] = BOX;map[2][manX][manY - 1] = EMPTY;manY++;step--;}break;case 20:{map[2][manX][manY] = BOX;map[2][manX][manY + 1] = EMPTY;manY--;step--;}break;case 30:{map[2][manX][manY] = BOX;map[2][manX-1][manY] = EMPTY;manX++;step--;}break;case 40:{map[2][manX][manY] = BOX;map[2][manX+1][manY] = EMPTY;manX--;step--;}break;case 1:{manY++;step--;}break;case 2:{manY--;step--;}break;case 3:{manX++;step--;}break;case 4:{manX--;step--;}break;}}elsestep=0;}//外部调用此方法,由核心业务模块,自行完成人物移动
//direction,方向:1:上、2:下、3:左、4:右
void manMove(){switch(direction){case 1://上if(map[2][manX][manY - 1] == OUTERE_WALL){direction=0;break;}if(map[2][manX][manY - 1] == BOX){//上方是箱子,但还需判断箱子是否能被推动if(map[2][manX][manY - 2] == EMPTY){//箱子上方没有东西,可以推动map[2][manX][manY - 2] = BOX;map[2][manX][manY - 1] = EMPTY;   direction=10;if(checkAndPass() == 1){    direction=0;break;}    }else{direction=0;//箱子上方有东西,不能推动,且人也不能移动break;}}if(manY > 0){manY--;step++;}break;case 2://下if(map[2][manX][manY + 1] == OUTERE_WALL){direction=0;break;}if(map[2][manX][manY + 1] == BOX){//下方是箱子,但还需判断箱子是否能被推动if(map[2][manX][manY + 2] == EMPTY){//箱子下方没有东西,可以推动map[2][manX][manY + 2] = BOX;map[2][manX][manY + 1] = EMPTY;if(checkAndPass() == 1){direction=0;break;}else   direction=20;}else{direction=0;//箱子下方有东西,不能推动,且人也不能移动break;}}if(manY < GRID_N - 1){manY++;step++;}break;case 3://左if(map[2][manX  - 1][manY] == OUTERE_WALL){direction=0;break;//终止移动}if(map[2][manX  - 1][manY] == BOX){//左侧是箱子,但还需判断箱子是否能被推动if(map[2][manX - 2][manY] == EMPTY){//箱子左侧没有东西,可以推动map[2][manX - 2][manY] = BOX;map[2][manX  - 1][manY] = EMPTY;if(checkAndPass() == 1){direction=0;break;}else direction=30;}else{direction=0;//箱子左侧有东西,不能推动,且人也不能移动break;}}if(manX > 0){manX--;step++;}break;case 4://右if(map[2][manX + 1][manY] == OUTERE_WALL){direction=0;break;}if(map[2][manX  + 1][manY] == BOX){//右侧是箱子,但还需判断箱子是否能被推动if(map[2][manX + 2][manY] == EMPTY){//箱子右侧没有东西,可以推动map[2][manX + 2][manY] = BOX;map[2][manX + 1][manY] = EMPTY;if(checkAndPass() == 1){_key=1;direction=0;break;}else direction=40;}else{direction=0;//箱子左侧有东西,不能推动,且人也不能移动break;}}if(manX < GRID_N - 1){manX++;step++;}break;}
}

key.h

#ifndef KEY_H
#define KEY_Hvoid key();#endif

paint.h

#ifndef PAINT_H
#define PAINT_H#define WINDOW_WIDTH 1024 //窗口宽度,像素数
#define WINDOW_HEIGHT 768 //窗口高度,像素数
#define GRID_SIZE 40 //格子大小,像素数
#define BEGIN_X 300 //棋盘左侧偏移量,像素数
#define BEGIN_Y 50 //棋盘上方偏移量,像素数extern int pikaquCount;//当前该绘制哪一张皮卡丘图片void paintAll();
void initPaint();#endif

pushBox.h

#ifndef PUSHBOX_H
#define PUSHBOX_H#define GRID_N 16 //游戏场景范围的格子数//定义游戏界面中格子中的元素类型
#define EMPTY 0 //空
#define OUTERE_WALL 1 //外墙
#define INNER_WALL 2 //内墙
#define BALL 3 //小球
#define BOX 4 //箱子
#define MAN 5 //人
#define BOX_ON_BALL 6 //箱子在小球上面,箱子要变色//声明变量和方法
extern int manX;
extern int manY;
extern int map[3][GRID_N][GRID_N];
extern int level;
extern int step;
extern int direction;
extern int Direction[1024];
extern int _key;
extern int duration;void goback();
void restart();
void xuanguan();void loadMapFromFile(int _level);//调用此方法,给定关卡数字,内部会从关卡文件夹中加载对应的地图文件(比如:100.txt)//加载下一关地图(根据当前第几关)
void nextLevel();
//加载上一关地图(根据当前第几关)
void beforeLevel();//外部调用此方法,完成人物移动
void manMove();//调用此方法,开启一个间隔时间为1秒的定时器
void startDurationTimer();#endif

推箱子小游戏自制100关,有兴趣可以试一试。(头文件和源文件分开)游戏截图已发。相关推荐

  1. [原创]jQuery推箱子小游戏(100关且可扩展可选关),休闲,对战,娱乐,小游戏,下载即用,兼容iPad移动端,代码注释全(附源码)

    Sokoban 介绍 [原创]jQuery推箱子小游戏(100关且可扩展可选关),休闲,对战,娱乐,小游戏,下载即用,兼容iPad移动端,代码注释全(附源码) 游戏说明 经典的推箱子是一个来自日本的古 ...

  2. HTML5推箱子小游戏 源码 共100关哦!

    推箱子 源码链接地址:https://github.com/shunyue1320/sokoban.git 推箱子小游戏展示效果图: 源码链接地址:https://github.com/shunyue ...

  3. python推箱子小游戏_小伙利用Python自制一个推箱子小游戏!

    原标题:小伙利用Python自制一个推箱子小游戏! 导语 月初更波python制作小游戏系列吧用python写了个推箱子小游戏,在这里分享给大家,让我们愉快地开始吧 小伙利用Python自制一个推箱子 ...

  4. win32GDI函数编程实现推箱子小游戏

    利用GDI绘图函数实现推箱子小游戏,代码源于上一篇博客 C语言控制台推箱子. 实现方法很简单,把字符用绘图函数绘出的图形替换即可. 从字符控制台到win32界面编程,更加形象化. 代码量大增,主程序就 ...

  5. C++ 简化 推箱子 小游戏 完整代码 参考网络资料 命令行运行 仅供初学者参考交流

    C++ 简化 推箱子 小游戏 完整代码 参考网络资料 命令行运行 仅供初学者参考交流 说明:学做了4关推箱子, 仅供初学者参考可用g++ 编译,可以将内容复制到TXT文件,将后缀改为".cp ...

  6. python推箱子小游戏

    推箱子小游戏 本次小游戏学习视频:https://www.bilibili.com/video/BV1gz411B71H 相关素材:点击这里 import turtle import levelms ...

  7. 用C语言实现推箱子小游戏基础程序plus

    目录 设计一个简单的推箱子游戏 功能设计要求: 代码实现 数据定义头文件data_def.h 窗口设置头文件WindowsSet.h WindowsSet.cpp 上移函数 矩阵旋转函数 游戏帧 菜单 ...

  8. 基于html5实现的推箱子小游戏

    一.游戏功能分析 1)功能需求分析 功能需求分析如图1-1所示. 小人推箱子:当箱子周围存在通道时,通过小人的左右移动实现推箱子功能. 炸毁墙面:小人当前所在位置的四周有墙面时,按下空格可以炸毁墙面 ...

  9. python写推箱子_python写的推箱子小游戏

    原标题:python写的推箱子小游戏 导语 Python 功能强大,可以写爬虫.服务器.数据分析.AI--当然,也可以写游戏. 用python写了个推箱子小游戏,在这里分享给大家,让我们愉快地开始吧~ ...

最新文章

  1. 深入解析和反思携程宕机事件
  2. 发送电子邮件模块smtplib
  3. python编码规范手册-python之(8)Python编码规范整理
  4. 安装visual studio 2013--【转】
  5. C++Opengl三维列表堆罗汉源码
  6. 哈·曼丁的故事(三)
  7. 单点登录(SSO)—简介 1
  8. 重装谷歌浏览器chrome:未知错误导致安装失败
  9. 计算机网络 —— 组网
  10. linux简单的操作命令
  11. 633.平方数之和(力扣leetcode) 博主可答疑该问题
  12. 从用户端到后台系统,严选分销教会我这些事
  13. pyqt html编辑器,PyQt笔记——代码编辑器Scintilla的使用方法
  14. Iredmail搭建
  15. Java程序线上运行CPU占用100%的处理方法
  16. Spring Boot整合Redis-lesson8
  17. Remote end closed connection without response
  18. The project seems to require yarn but it‘s not installed.
  19. 学习人工智能宝藏网站(Papers with Code)
  20. 曝光程序员的桌面!有点心酸 |每日趣闻

热门文章

  1. JMeter之non-GUI 模式执行
  2. GeForce GTX 2050/2080/3090/A6000自动安装nvidia显卡驱动
  3. 关于hard parses以及latches争用
  4. Wi n d o w s函数l s t r c m p和l s t r c m p i是作为对Wi n d o w s函数 C o m p a r e S t r i n g的调用来实现
  5. ARCGIS Geostatistic Analysis 工具条的使用
  6. 【券后价12.90元】【包邮】铁观音茶叶浓香型安溪2019新茶乌龙茶散装袋装小包装礼盒装250克...
  7. An Introduction to K-theory
  8. NI-DAQmx安装问题,DAQ助手在Labview中不显示,新建时显示缺少编辑所需要的组件
  9. tlac100怎么添加ap_TL-AC100安装说明书
  10. 3Blue1Brown系列:贝叶斯定理(Bayes Theorem)