游戏设计:推箱子【easyx图形界面/c语言】

在之前写程序设计的大作业时,在哔哩哔哩上跟着一个视频的学习的成果【第一个练习的】

今天整理文件的时候看到的,就发出来一下【CSDN和B站都有详细教程】

不是大项目,只有两个界面

这个代码只有两百行不到,但通过这个把基本的运行逻辑什么的掌握了,然后写自己的完整的游戏设计


经典的推箱子玩法,玩家需要控制一个小人,将箱子推到指定的目标位置,直到通关

#include<graphics.h>
#include<conio.h>
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 650  //屏幕宽高#define RATIO 50 //道具比例#define START_X 100
#define START_Y 100#define  LINE 9
#define COLUMN 12//控制键上下左右,退出键
#define KEY_UP 'w'
#define KEY_DOWN 's'
#define KEY_LEFT 'a'
#define KEY_RIGHT 'd'
#define KEY_QUIT 'q'//#define KEY_UNDO 'u' // 撤回键
//#define KEY_RESTART 'r' // 重玩键#define isvalid(pos) (pos.x>=0 && pos.x<LINE && pos.y>=0 && pos.y<COLUMN)
//确保下标不会越界,移动的前提enum _PROPS
{WALL,//墙0FLOOR,//地板1BOX_DES,//箱子目的地2MAN,//小人3BOX,//箱子4HIT,//箱子的正确位置5GameOver,//通关界面6ALL    //7数组个数
};
// 显高级枚举法,暂时不想改typedef enum _PROPS PROPS;//定义别名//游戏控制方向,枚举变量
enum _DIRECTION 
{UP,DOWN,LEFT,RIGHT,
};
typedef enum _DIRECTION DIRECTION;//用类型定义作简化//0:墙 ,1:地板,2:目的地,3:小人,4:箱子,5:正确位置的箱子
int map[9][12] =
{{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,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},
};IMAGE images[ALL];struct _POS 
{int x;//小人所在的二维数组的行int y;//小人所在的二维数组的列
};
typedef struct _POS POS;//POS小人的坐标的数据类型POS man;     //小人的实时位置,包含小人的坐标//
void ChangeMap(POS* pos, PROPS prop)
{map[pos->x][pos->y] = prop;//位置  数组要改putimage(START_X + pos->y * RATIO, START_Y + pos->x * RATIO, &images[prop]);//视图}
/********************
实现上下左右控制
输入:输出
********************/void GameControl(DIRECTION direct) //void没有返回值,方向类型定义变量
{POS next_pos = man;//小人下一个的位置,变量初始化POS	next_next_pos = man;//小人下下个的位置switch (direct) //switch判断方向{case UP:next_pos.x = man.x - 1;next_next_pos.x = man.x - 2;break;case DOWN:next_pos.x = man.x + 1;next_next_pos.x = man.x + 2;//上下行变,列不变break;case LEFT:next_pos.y = man.y - 1;next_next_pos.y = man.y - 2;break;case RIGHT:next_pos.y = man.y + 1;next_next_pos.y = man.y + 2;//左右列变break;}/**********在一个狭小的仓库中,要求把木箱放到指定的位置稍不小心就会出现箱子无法移动或者通道被堵住的情况***********///逻辑判断,小人怎么走//如果小人前进一步是地板,则前进// 人到next_pos位置,原来的位置变成地板if (isvalid(next_pos) && map[next_pos.x][next_pos.y] == FLOOR) {ChangeMap(&next_pos, MAN);//ChangeMap(&man, FLOOR);//人原来的位置man = next_pos;//小人的实时位置}//如果人前进一步是   箱子  ,并且箱子前面next_next_pos是地板或者箱子目的地,则推着箱子走// if (isvalid(next_pos) && map[next_pos.x][next_pos.y] == BOX){//箱子前面是地板if (isvalid(next_next_pos) && map[next_next_pos.x][next_next_pos.y] == FLOOR){ChangeMap(&next_next_pos,BOX);ChangeMap(&next_pos, MAN);ChangeMap(&man, FLOOR);man = next_pos;}//箱子前面是目的地else if (isvalid(next_next_pos) && map[next_next_pos.x][next_next_pos.y] == BOX_DES){ChangeMap(&next_next_pos, HIT);//箱在目的地ChangeMap(&next_pos, MAN);ChangeMap(&man, FLOOR);man = next_pos;}}}
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 GameOverScene(IMAGE* bg)
{putimage(0, 0, bg);settextcolor(RED);RECT rec = { 0,0,SCREEN_WIDTH,SCREEN_HEIGHT };//跟屏幕同宽高settextstyle(80, 0, "楷体");drawtext("恭喜您成功通关", & rec, DT_CENTER | DT_VCENTER | DT_SINGLELINE);}int main(void)
{//定义一个表示图片的变量IMAGE bg_img;initgraph(SCREEN_WIDTH, SCREEN_HEIGHT);//屏幕宽高//定义一个表示图片的变量IMAGE gameoverscene;//设置成功背景loadimage(&gameoverscene, "GameOverScene.png", SCREEN_WIDTH, SCREEN_HEIGHT, true);//true表示图片自适应//设置背景loadimage(&bg_img, "beijing.png", SCREEN_WIDTH, SCREEN_HEIGHT, true);//true表示图片自适应putimage(0, 0, &bg_img);//物件图片loadimage(&images[0], "wall.png", RATIO, RATIO, true);//墙 loadimage(&images[1], "floor.png", RATIO, RATIO, true);//地板loadimage(&images[2], "des.png", RATIO, RATIO, true);//目的地loadimage(&images[3], "man.png", RATIO, RATIO, true);//小人loadimage(&images[4], "box.png", RATIO, RATIO, true);//箱子loadimage(&images[5], "box.png", RATIO, RATIO, true);//正确位置的箱子for (int i = 0;i < 9;i++){for (int j = 0;j < 12;j++){if (map[i][j] == MAN){man.x = i;man.y = j;//x行,y列}//小人的位置putimage(START_X + j * RATIO, START_Y + i * RATIO, &images[map[i][j]]);}}bool quit = false;//游戏结束条件//热键控制do{if (_kbhit())      //_kbnit(),_grtch()关于按键的函数{//判断是否有按键,如果有按键按char ch = _getch();if (ch == KEY_UP)//w{GameControl(UP);//游戏控制}else if (ch == KEY_DOWN)//s{GameControl(DOWN);}else if (ch == KEY_LEFT)//a{GameControl(LEFT);}else if (ch == KEY_RIGHT)//d{GameControl(RIGHT);}else if (ch == KEY_QUIT) //q{quit = true;}else if (ch == KEY_QUIT) //q{quit = true;}if (IsGameover())//判断游戏是否结束,所有的2全没了{GameOverScene(& gameoverscene);}}Sleep(100);//100ms,0.1s//在没有按键的情况下让CPU休息一下,降低CPU率} while (quit == false);system("pause");return 0;}

是一个简单的推箱子游戏的实现,使用了 graphics.h 库来进行图形显示。

功能简单明了。

1. 游戏地图的初始化

游戏地图是一个二维数组,包含墙壁、地板、箱子、目的地等不同的元素。通过 map 数组表示,不同的整数值代表不同的元素。

int map[9][12] = {{0,0,0,0,0,0,0,0,0,0,0,0},  // 0代表墙{0,1,0,1,1,1,1,1,1,1,0,0},  // 1代表地板{0,1,4,1,0,2,1,0,2,1,0,0},  // 4代表箱子,2代表目的地// ...
};
  • 0 表示墙壁
  • 1 表示地板
  • 2 表示箱子目的地
  • 3 表示小人
  • 4 表示箱子
  • 5 表示正确放置的箱子

2. 结构体与枚举类型

  • PROPS 枚举定义了不同的游戏元素类型(如墙、地板、箱子等)。

  • DIRECTION 枚举定义了小人的移动方向(上、下、左、右)。

  • POS 结构体用来表示位置,包含 xy 两个成员,分别表示二维数组的行列。

3. 游戏控制和移动逻辑

GameControl 函数是控制小人移动的核心。根据输入的方向(上下左右),更新小人的位置,并处理箱子的推送逻辑。具体逻辑如下:

  • 如果小人前进的方向是地板,则小人可以移动。

  • 如果小人前进的方向是箱子,且箱子后方是地板或目的地,箱子可以被推移。

4. 游戏结束判断

IsGameover 函数用来判断游戏是否结束,判断标准是所有目的地(BOX_DES)上是否都有箱子。

5. 图形显示

使用 putimage 函数显示图像,加载各类图像(如墙壁、地板、箱子等),并通过 ChangeMap 函数来更新游戏地图的显示。

6. 用户输入与游戏循环

游戏通过 _kbhit()_getch() 检测用户的按键输入。如果按下控制键(如 w, a, s, d),则调用 GameControl 函数进行相应的移动操作。如果按下退出键(q),则退出游戏。


把这些东西理解后就可以自己扩写改造了,

我最后的大作业就是基于最简单的推箱子游戏进行改动,增加其他的功能进行功能扩展

这里的图片来源于网络,可能按照自己的想法更改

完整文件我上传到这了,下载可以直接运行

游戏设计:推箱子【easyx图形界面/c语言】资源-CSDN文库

自己看用上面代码然后自己整加图片素材也可以正常运行

图像加载

游戏中的每个对象(如墙、地板、小人、箱子等)都通过图像来表示。我们使用loadimage函数将图像加载到内存,并通过图形界面显示出来。

loadimage(&images[0], "wall.png", RATIO, RATIO, true); // 加载墙壁图像
loadimage(&images[1], "floor.png", RATIO, RATIO, true); // 加载地板图像
loadimage(&images[2], "des.png", RATIO, RATIO, true);   // 加载目标图像
loadimage(&images[3], "man.png", RATIO, RATIO, true);    // 加载小人图像
loadimage(&images[4], "box.png", RATIO, RATIO, true);    // 加载箱子图像

“”里就是图片对应的图片路径

loadimage(&images[4], "box.png", RATIO, RATIO, true);

"box.png" 是图像文件的路径,它是一个名为 box.png 的图像文件。

图像文件可以是多种格式,比如 .png, .jpg 等,这里使用的是 .png 格式。box.png 应该是存放在程序的工作目录下,或者是通过相对/绝对路径进行访问。

这里是直接存储在代码所在的文件夹

如果想现有运行效果,针对导入图片的一些代码加入自己的图片路径即可
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/11323.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

C++数学

前言 C算法与数据结构 打开打包代码的方法兼述单元测试 数论&#xff1a;质数、最大公约数、菲蜀定理 组合数学汇总 计算几何 博弈论 曼哈顿距离与切比雪夫距离 红线是哈曼顿距离&#xff0c;绿线是切比雪夫距离。 二维曼哈顿距离转切比雪夫距离 曼哈顿距离&#xff1a;|…

如何安装VMWare Workstation 16虚拟机

1、到VMware官网下载安装包。 2、下一步。 3、勾选同意协议&#xff0c;下一步。 4、更换安装路径&#xff0c;下一步。 5、取消全部勾选&#xff0c;下一步。 6、下一步。 7、安装。 8、等待安装完成。 9、安装完成&#xff0c;启动软件。 10、输入许可证ZF3R0…

光流分析技术

光流分析技术是一种重要的计算机视觉和图像处理技术&#xff0c;它通过分析连续帧图像中像素点的运动轨迹和速度&#xff0c;来捕捉图像中物体的运动和相邻帧之间的位移信息。以下是对光流分析技术的详细介绍&#xff1a; 一、光流的基本概念 光流&#xff08;Optical Flow&am…

Bearer 和 Digest 两个区别

Bearer 和 Digest 是两种常见的身份验证机制,主要用于在网络通信中验证用户的身份,以下是它们之间的区别: 认证原理 Bearer:也称为承载令牌认证,其核心是使用一个令牌(Token)来代表用户的身份信息。用户在进行身份验证后,服务器会颁发一个令牌给客户端,客户端在后续…

H264三种RTP打包方式

1. 单一NALU模式 单一NALU模式 适用于小于MTU&#xff08;最大传输单元&#xff09;的NALU。这种模式下&#xff0c;一个RTP包包含一个完整的NALU。RTP头部之后紧跟着NALU头和NALU数据。 封装格式&#xff1a; RTP头 | NALU头 | NALU数据这种方式简单直接&#xff0c;但仅适…

亚马逊评论爬虫+数据分析

爬取评论 做分析首先得有数据&#xff0c;数据是核心&#xff0c;而且要准确&#xff01; 1、爬虫必要步骤&#xff0c;选好框架 2、开发所需数据 3、最后测试流程 这里我所选框架是seleniumrequest&#xff0c;很多人觉得selenium慢&#xff0c;确实不快&#xff0c;仅针对此…

批量缓存模版

批量缓存模版 缓存通常有两种使用方式&#xff0c;一种是Cache-Aside&#xff0c;一种是cache-through。也就是旁路缓存和缓存即数据源。 一般一种用于读&#xff0c;另一种用于读写。参考后台服务架构高性能设计之道。 最典型的Cache-Aside的样例&#xff1a; //读操作 da…

09 Oracle数据拯救:Flashback Technologies精细级数据恢复指南

文章目录 09 Oracle数据拯救&#xff1a;Flashback Technologies精细级数据恢复指南一、Flashback Technologies概览二、Flashback Query&#xff1a;查询过去的数据三、Flashback Table&#xff1a;恢复整个表四、Flashback Database&#xff1a;恢复整个数据库五、总结与最佳…

BIST(Built-in Self-Test,内建自测试)学习笔记

参考资料: 内建自测试&#xff08;Built-in Self-Test&#xff0c;简称BIST&#xff09;详解_built in self test-CSDN博客 芯片测试术语 &#xff0c;片内测试(BIST)&#xff0c;ATE测试-CSDN博客 可能是DFT最全面的介绍--BIST - 知乎 (zhihu.com) 汽车功能安全--TC3xx LB…

three.js 杂记

在Three.js中&#xff0c;Object3D是所有3D对象的基类&#xff0c;而Group是Object3D的一个子类。Group的目的是为了简化处理多个对象的集合。当你将对象添加到Group中时&#xff0c;它们会以一个单元格的形式被处理&#xff0c;参与Group的某些操作&#xff0c;例如位置更新、…

go函数传值是值传递?还是引用传递?slice案例加图解

先说下结论 Go语言中所有的传参都是值传递&#xff08;传值&#xff09;&#xff0c;都是一个副本&#xff0c;一个拷贝。 值语义类型&#xff1a;参数传递的时候&#xff0c;就是值拷贝&#xff0c;这样就在函数中就无法修改原内容数据。 基本类型&#xff1a;byte、int、bool…

穿越时空的全球时钟:一个实时多时区显示的网页应用

引言 在当今这个全球化时代&#xff0c;人们经常需要与世界各地的朋友、同事或客户进行沟通。然而&#xff0c;由于时差的存在&#xff0c;找到一个合适的沟通时间往往成为一大挑战。为了解决这一问题&#xff0c;我们开发了一个名为“全球时钟”的网页应用&#xff0c;它能够…

本地部署免费开源助手Ollama

Ollama 安装 安装ollama 官方网站&#xff1a;https://ollama.com/download 2. 安装成功 3. 运行模型 模型&#xff1a;https://ollama.com/library 运行&#xff1a; ollama run llama3.2:3b Mac 、Linux 版本安装类似。 Open-WebUI界面安装 openwebui官网&#xff1a;http…

three.js杂记

空间 - 位置变换&#xff1a; // 假设有一个Three.js的对象: object3D // 存储矩阵位置 const matrix object3D.matrix.clone(); const matrixArray matrix.toArray(); // 转换为数组 // 之后&#xff0c;当你需要恢复位置时 object3D.matrix.fromArray(matrixArray); …

通过DNS服务器架构解释DNS请求过程

在前面的章节,这里,基于PCAP数据包和RFC文档详细介绍了DNS请求和响应的每个字段的含义。但是在现实的网络世界中,DNS请求和响应的数据包是怎么流动的,会经过哪些设备。本文将着重说明一下目前网络空间中DNS请求和响应的流动过程。 当前网络空间中比较常见DNS请求的流程如下…

HBase使用create创建表时报错ERROR: KeeperErrorCode = NoNode for /hbase/master

场景模拟 1. 正常情况 模拟ERROR: KeeperErrorCode NoNode for /hbase/master错误场景。 正常情况下创建hbase表如下图所示。 2. 删除hbase集群的zk节点 进入zookeeper客户端。 zkCli.sh删除hbase的zk节点。 deleteall /hbase退出zookeeper客户端。 quit3. 重启hbase集…

软件分享丨火绒应用商店

【资源分享】 资源名&#xff1a;火绒应用商店 官方网址&#xff1a;点击跳转 火绒应用商店是由火绒安全推出的一款独立软件。它提供了海量的应用程序&#xff0c;涵盖办公、社交、游戏、视频、工具等多种领域和类别&#xff0c;方便用户轻松找到所需的应用并进行一键下载安装…

在线考试系统demo页面

<!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>在线考试系统</title><link rel"styl…

从0到1基于LangChain制作一个AI猫娘

前言&#xff1a; 看到B站上的AIVtuber的项目落地了&#xff0c;就心血来潮想制作一个AI的猫娘供自己使用&#xff0c;顺便出一个简单的教程&#xff0c;跳过理论&#xff0c;直接实践&#xff0c;作者也还在学习摸索中&#xff0c;所以有错误可以直接在评论区指正。&#xff0…

前端---高效工具(一) : NVM的使用

一、NVM用途 方便快捷 管理和切换各个 node版本。现在前端项目Vue2与Vue3很多项目要求的node版本不一致导致的。 二、安装 如果有安装nodejs&#xff0c;按一下步骤清理环境 1.卸载应用程序的 nodejs 2.删除环境变量中nodejs的配置 3.删除C:\Users\Administrator 中最下面…