c语言是许多程序员的入门语言,其重要性不言而喻,因为它奠定了许多编程习惯和逻辑思维的基础。我通过学习c语言,编写了一个推箱子小游戏,提升了我的逻辑能力。现在,我想与大家分享这个推箱子小游戏项目。
GitHub 仓库地址:https://www./link/9a66e987aff9a6d0f673189ca1e72f78
首先,让我们看一下游戏运行的最终效果。
最终的效果图
这是一个在 Windows Dos 界面下运行的小游戏,游戏界面上显示了推箱子的地图。其中,# 表示地图的边界,P 表示推箱子的小人,X 表示箱子,O 表示箱子需要推到的目标位置。
游戏操作使用 W(w)、S(s)、A(a)、D(d) 键,分别对应小人向上、下、左、右移动。
在编写这个小游戏时,我们面临了一些挑战:
如何保存游戏地图?
游戏如何运行?
如何在固定位置上不断更新游戏地图?
小人的移动逻辑如何实现?
游戏如何结束?
如何保存游戏地图?
C语言只有基本的数据类型,而游戏地图是二维的平面结构。我们可以使用二维数组来保存游戏地图,具体代码可在 GitHub 仓库中的 关卡.h 文件中找到。
游戏地图
游戏如何运行?
由于推箱子游戏在结束前需要不断接收用户输入,我们可以设置一个标志来判断游戏是否结束,并将此标志设置为 while 循环的条件。在每次循环中,接收用户输入,根据输入值决定小人的移动方向(上下左右),这里可以使用 switch 语句来判断。每一次循环对应一次用户输入。
如何在固定位置上不断更新游戏地图?
在每次循环中,首先显示当前的地图以便用户进行下一次移动。我们将游戏地图设置为全局变量,这样小人移动后,地图上的字符改变将是永久的,然后打印出局部改变的新地图。程序不断循环,一遍遍打印地图,使得地图上的字符可以不断改变,但地图的位置无法固定。我们可以通过刷新界面来实现这一点。刷新本质上是
除旧迎新,即清除原来的界面,再显示新的界面。C语言中可以使用 system("cls") 函数清除控制台内容,然后再显示新的地图内容。
小人的移动逻辑属于具体的程序实现,我们稍后再讨论,先来说说程序如何结束。
游戏如何结束?
前面提到设置一个标志来判断游戏是否结束,但游戏何时结束呢?推箱子的目标是将每个箱子推到目标位置,这是一种结束情况。由于每次循环都要判断,可以将其写成一个函数。另一种情况是用户不想玩了想退出,这里只考虑了这两种情况,读者可自行考虑其他情况。
到目前为止,我们可以写出程序的大致框架:外部一个大循环,每次循环先刷新界面,接收用户输入,处理用户输入,判断游戏是否结束。
程序大致框架
小人的移动逻辑如何实现?
在上面的程序截图中,可以看到我将小人的上下左右移动分别写到了四个函数中,分别是 MoveToUp()、MoveToDown()、MoveToLeft()、MoveToRight()。以 MoveToUp() 函数为例,我们来分析小人移动的逻辑。
理论上,小人可以上下左右移动,但由于有地图的限制,小人不能穿墙,只能在允许的道路上移动。例如,小人想向上移动,但如果上面一格有限制物(如墙),就不允许移动。
不能向上移动
而如果上面一格没有限制物,小人就可以向上移动。
可以向上移动
因此,我们需要对小人理论上可以移动到的位置(下一位置)进行判断。如果下一位置不是限制物(箱子和箱子要移动到的位置),小人就可以移动。如果有限制物,就不能移动。我们需要记录一个坐标点的值,游戏开始时,小人的初始位置作为当前位置。小人向上移动时,下一位置的横坐标就是小人当前位置的横坐标减一,纵坐标不变。然后根据下一位置的横纵坐标找到具体的字符值,如果是空的或目标位置,小人就可以移动。如果下一位置是箱子,我们还要考虑箱子的下一位置。由于小人和箱子在一条线上移动,小人向上移动时,箱子的下一位置的横坐标就是小人下一位置的横坐标减一,两者的纵坐标相同。同样,我们也要对箱子下一位置的字符值进行判断,如果是空格或箱子可以移动的位置,就可以移动。小人向上移动的代码如下:
小人向上移动
小人向下、向左、向右移动的代码类似,只需修改小人移动的下一坐标。向下移动时,下一位置的横坐标是小人的横坐标加一,纵坐标不变。具体代码请参见 GitHub 仓库中的 控制.cpp 文件。
到这里,整个程序就完成了,可以运行整个程序,效果如下,你能发现哪里有 Bug 吗?
有Bug的效果图
细心的你可能已经发现了,当小人移动到箱子要移动的目标位置,再移出,这个位置就会“消失”。这是因为我们在移动之前没有关注这个位置(上一位置)原本的值。我们可以记录这个“上一位置”的值,但这样考虑的问题就比较多了,尤其是在箱子和小人都在箱子要移动的目标位置时,情况很复杂。实际上,我们的程序大体上是没什么问题的,只是箱子要移动的目标位置会出现“字符消失”。这只是个小 Bug,微软的做法是发布补丁,我们也可以给这个程序打个“补丁”。箱子要移动的位置是不变的,我们可以用一个二维数组来存放这些特殊位置。这些特殊位置的值也是特殊的,要不就是目标位置,要不就是箱子,要不就是小人,而不能是空白字符。我们可以写一个“补丁”函数来修复这个 Bug。在每个方向的移动函数结尾加上这个修复函数。该函数判断特殊位置是否为空白字符,如果是,就将特殊位置的值改为目标位置的字符值,这里是字符 “O”,这样就“修复”了程序的 Bug,“字符消失”的问题也被解决了。
修复函数
我将程序划分成了不同的文件,GitHub仓库也有程序目录的说明文件,读者在阅读代码时,会注意到 extern 关键字的使用,这个关键字是为了拆分的多个文件之间共用某个变量或者函数。通过更换关卡中的游戏地图,可以实现推箱子的多个关卡,读者有兴趣可自己尝试改进,本文也是起到一个抛砖引玉的作用。
最后想说的是,写程序很注重逻辑,无论用什么语言,程序的逻辑都是一样的,无非就是哪种语言更方便,更快捷。写程序真正玩的是逻辑,只有逻辑清晰,代码才能写得好,否则顶多也是代码的搬运工。
# git
# windows
# github
# c语言
# switch
# win
# 微软
# 数据类型
# while
# extern
# 全局变量
# 循环
# https
# bug
# 下一
# 我们可以
# 推箱子
# 就可以
# 上下左右
# 可以使用
# 的是
# 多个
# 上一
# 我将
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
网络优化76771 】
【
技术知识130152 】
【
IDC云计算60162 】
【
营销推广131313 】
【
AI优化88182 】
【
百度推广37138 】
【
网站推荐60173 】
【
精选阅读31334 】
相关推荐:
如何在 Go 中正确反序列化多个同级 XML 元素(而非单个根节点)
Win11怎么设置任务栏图标大小_Windows11注册表TaskbarSi修改
Windows10怎么用“讲述人”读屏辅助 Windows10轻松使用开启讲述人朗读屏幕文字帮助视障用户【教程】
Win11开机Logo怎么换_Win11自定义启动画面工具【高级】
如何在Golang中编写异步函数测试_Golang异步操作测试策略
Win11怎么关闭自动调节亮度 Win11禁用内容自适应亮度【设置】
MySQL 中使用 IF 和 CASE 实现查询字段的条件转换
Windows 11怎么更改锁屏超时时间_Windows 11电源选项中设置屏幕关闭时间
PHP接收参数长度超限怎么办_修改postmaxsize设置教程【解答】
Python对象比较与排序_集合使用说明【指导】
LINUX怎么查看进程_LINUX ps命令查看运行服务
LINUX如何开放防火墙端口_Linux firewalld与iptables开放端口命令【安全配置】
Windows系统文件被保护机制阻止怎么办_权限不足错误处理方案
如何使用Golang实现Web表单数据绑定_自动映射字段到结构体
Win11怎么设置DNS服务器_Windows11修改网络适配器DNS优选
Win11此电脑不在桌面上_Windows 11桌面图标设置找回【步骤】
Win11怎么设置虚拟桌面 Win11新建多桌面切换操作【技巧】
Windows10如何删除恢复分区_Win10 Diskpart命令强制删除分区
Win11怎么清理C盘下载文件夹_Win11清理下载文件夹技巧【教程】
Win11怎么设置ip地址_Windows 11手动配置网络IP教程【详解】
Win11局域网共享怎么设置 Win11文件夹网络共享教程【详解】
Win10如何更改开机密码_Windows10登录选项更改密码
Win11怎么清理C盘系统日志_Win11清理系统日志文件【步骤】
Win11怎么关闭内容自适应亮度_Windows11显示设置CABC关闭
php下载安装包太大怎么下载_分卷压缩下载方法【教程】
Win11怎么关闭应用权限_Windows11相机麦克风隐私管理
Win11怎么关闭自动调节亮度_Windows11禁用内容自适应亮度
Windows10如何更改鼠标图标_Win10鼠标属性指针浏览
c# 在高并发场景下,委托和接口调用的性能对比
Win11怎么设置鼠标宏_Win11鼠标按键自定义编程教程【详解】
MAC怎么用连续互通相机里的“桌上视角”_MAC在视频通话中同时展示人脸和桌面
如何用正则与预处理结合精准拦截拼接式垃圾域名
php下载安装后swoole扩展怎么安装_异步框架支持【汇总】
Windows7如何安装系统镜像_Windows7系统安装教程【步骤】
c++如何判断文件是否存在_c++ filesystem库用法
Windows11怎么自定义任务栏_Windows11任务栏自定义教程【步骤】
Win11如何设置自动关机 Win11定时关机命令使用教程【技巧】
Django 密码修改后会话失效的解决方案
如何在Golang中实现自定义Benchmark_Golang testing.B自定义性能测量示例
使用类变量定义字符串常量时如何实现类型安全的 Literal 注解
Python大文件处理策略_内存优化说明【指导】
Python邮件系统自动化教程_批量发送解析与模板应用
php中$this和::能混用吗_对象与静态作用域冲突解决【方法】
Django密码修改后会话失效的解决方案
Windows10怎么备份注册表_Windows10注册表备份步骤【教程】
php怎么下载安装后无法解析php文件_服务器配置检查【解答】
Win11怎么查看wifi信号强度_检测Windows 11无线网络质量方法【详解】
Windows怎样关闭Edge新标签页广告_Windows关闭Edge新标签页设置【步骤】
如何在 Pandas 中按元素交集合并两列字符串
php能跑在stm32上吗_php在stm32微控制器上的移植方法【介绍】
2025-09-25
致胜网络推广营销网专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。