c语言是许多程序员的入门语言,其重要性不言而喻,因为它奠定了许多编程习惯和逻辑思维的基础。我通过学习c语言,编写了一个推箱子小游戏,提升了我的逻辑能力。现在,我想与大家分享这个推箱子小游戏项目。
GitHub 仓库地址:https://www.php.cn/link/9a66e987aff9a6d0f673189ca1e72f78
首先,让我们看一下游戏运行的最终效果。
最终的效果图
这是一个在 Windows Dos 界面下运行的小游戏,游戏界面上显示了推箱子的地图。其中,# 表示地图的边界,P 表示推箱子的小人,X 表示箱子,O 表示箱子需要推到的目标位置。
立即学习“C语言免费学习笔记(深入)”;
游戏操作使用 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 关键字的使用,这个关键字是为了拆分的多个文件之间共用某个变量或者函数。通过更换关卡中的游戏地图,可以实现推箱子的多个关卡,读者有兴趣可自己尝试改进,本文也是起到一个抛砖引玉的作用。
最后想说的是,写程序很注重逻辑,无论用什么语言,程序的逻辑都是一样的,无非就是哪种语言更方便,更快捷。写程序真正玩的是逻辑,只有逻辑清晰,代码才能写得好,否则顶多也是代码的搬运工。
以上就是人人都可以用C语言写推箱子小游戏的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号