C语言实战 | “贪吃蛇”游戏重构

简介: 在程序设计中,模块化思维至关重要,尤其对于复杂项目,它帮助分解任务,便于团队协作。以“贪吃蛇”游戏为例,游戏涉及两个角色:蛇和食物。使用数组存储蛇的位置,变量存储食物位置。游戏流程分为初始化、显示和更新数据。初始化时,食物位置随机,蛇的位置根据数组设定。显示数据则根据这些信息在屏幕上呈现角色。更新数据时,处理蛇的移动和增长以及食物的生成和消失。类似地,通过模块化方法可开发“打砖块”游戏,涉及球、球拍和砖墙,每个角色都有相应数据结构和更新逻辑。通过这种方式,游戏开发就像搭建积木,遵循框架逐步实现。

程序设计的过程中,面对复杂项目,利用模块化思维分解任务,是关键的一步。读者一定要掌握模块化思维设计思维,为将来团队合作、协同完成大型应用软件做好准备。

01、“贪吃蛇”游戏

有了游戏框架之后,按照游戏框架完成“贪吃蛇”游戏。

“贪吃蛇”游戏角色有两个:“贪吃蛇”和“蛋”。也就是每幅图像都需要包含这两个角色。完成游戏的第一步,找到合适的数据结构存储游戏角色,显示在屏幕上。“贪吃蛇”的信息由一个较大的数组保存。

选择好合适的数据结构,则可以完成游戏元素的显示。

保存“蛋”位置的变量为:


int foodRow,foodCol;

保存“贪吃蛇”的数据变量为:


int snakeRows[100,snakeCols[100;

完成了最重要的第一步,接下来就按照框架流程来进行,每一个角色都包含着相同流程:初始化数据→显示数据→更新数据,如图6.6所示。

image.png


■ 图6.6“贪吃蛇”游戏框架图

(1) 初始化数据。

“食物”的位置是随机的,代码如下:

image.png


image.png


(2) 显示数据。

初始化数据之后,根据数据显示“蛋”和“贪吃蛇”的代码如下:

image.png


(3) 更新数据。

完成了“初始化数据”和“显示数据”两部分,剩下就是“更新数据”部分。

数据会发生变化的情况包括如下两种情况。

第一种:“贪吃蛇”的运动导致“贪吃蛇”位置信息发生变化;

第二种:“贪吃蛇”吃到“食物”时,“贪吃蛇”的长度会发生变化,会产生新的“食物”,“食物”的位置信息会发生变化。

“贪吃蛇”运动数据更新的代码如下:

image.png


image.png


image.png


当“贪吃蛇”吃到“食物”时,“贪吃蛇”和“食物”数据都要发生变化。是否吃到“食物”,这个模块的判决条件非常简单,就是“蛇头”运动到“食物”的位置,对应的代码如下:

image.png


image.png


image.png


完整的代码如下:

image.png


image.png


运行代码,游戏能实现“贪吃蛇”的基本功能,此时还差最后一步——“贪吃蛇”撞到墙壁或者自己时游戏结束,感兴趣的读者可以自己尝试完成该功能。

完成较为完整的游戏之后,发现程序设计其实就像搭积木一样,按照框架,将不同组件安装起来。

# 02、“打砖块”游戏

为了进一步感受“框架”的作用,不妨再完成一个经典的游戏:“打砖块”游戏。“这款游戏由苹果公司的创始人乔布斯和沃兹尼亚设计。从这款游戏中可以体验到乔布斯的“至繁归于至简”的设计思想。它的玩法非常简单:通过方向键控制底部的球拍左右运动,让小球通过不断反弹消除砖块,同时要保持小球不掉落。消掉的砖块越多,分数也就越高,如图6.7所示。

image.png


■ 图6.7“打砖块”游戏示意图

根据“贪吃蛇”游戏的经验,游戏中总共有3个角色:球、球拍和砖墙。每一个角色都需要找到合适的数据结构保存信息。球拍与“贪吃蛇”非常相似,可以使用一维数组去保存球拍组成的每个小方块的位置信息,然后根据位置信息显示出来。球与“食物”非常相似,使用单个变量就能保存位置信息,而顶部的砖墙则使用二维数组保存。找到合适的数据类型存储数据之后,按照游戏的框架,对每一个游戏元素进行初始化数据→显示数据→更新数据,直到完成游戏,如图6.8所示。

image.png


■ 图6.8“打砖块”游戏框架图

(1) 初始化数据。

根据图6.7所示,确定游戏角色的初始位置,初始化数据的代码如下:

image.png


(2) 显示数据。

完成了数据的初始化,接着就是将数据显示在屏幕上,代码如下:

image.png


(3) 更新数据。

接下来完成的是球拍在按键的控制下,朝着某个方向运动。球拍的运动与“俄罗斯方块”运动相似,都是整体运动,代码如下:
image.png
球拍在按键的控制下沿着某个方向运动。不过,当球拍运动到边界时,球拍还会继续运动,引发错误,所以需要一个判断球拍是否到达了边界的函数:

如果向左运动,则球拍的最左端运动到第0列,不能继续向左运动。

如果向右运动,则球拍的最右端运动到第7列,不能继续向右运动。

根据上面的分析,代码如下:

image.png


球拍完成之后,接下来完成小球的运动,球运动时遇到障碍就反弹,如图6.9所示。

image.png


■ 图6.9球反弹示意图

在第2章的案例中已经实现了球的反弹运动,定义两个变量表示小球运动方向:

int v;
int h;

变量v存储水平运动方向的值,值为-1时,表示向左运动;值为1时,表示向右运动。 变量h存储垂直运动方向的值,值为-1时,表示向上运动;值为1时,表示向下运动。 当球运行到左右两边的边界时,球水平方向会反弹,对应的代码为:

v =-v;

当球运行到上下界面,或者遇到了球拍时会发生垂直反弹,对应的代码为:

h =-h;

根据上述情况,球运动的代码如下:

image.png


完成了球拍和球的部分,还差最后一部分:砖块伴随着球不断运动,被击中界面不断动态变化,如图6.10所示。

image.png


■ 图6.10球运动方向示意图

接下来需要完成当运动的球击中砖块之后产生的影响。当球击中砖块时,砖块消失。所以,也就是球运动过的位置,如果对应的位置有砖块,则将对应位置的数组元素赋值为0,代码如下:
更新数据的代码为:

image.png

image.png


游戏完整的代码如下:

image.png

image.png

image.png

image.png

image.png

image.png

image.png


通过已经完成的“贪吃蛇”和“打砖块”游戏,可以体会到按照游戏框架逐步完成小游戏,就像通过流水线生成产品一样。

如果完成一个新的小游戏,则设计步骤如下。

(1) 根据游戏规则,统计游戏画面中会出现的游戏角色。然后根据游戏角色的特征选择合适的数据类型保存数据,通常有变量、一维数组、二维数组。

(2) 根据这些角色在屏幕上最初的位置,对每一个角色的数据进行初始化。

(3) 根据数据,将每一个角色显示在屏幕上。

(4) 根据游戏规则,更新每一个角色的数据,形成新的画面。

目录
相关文章
|
4天前
|
C语言
C语言实战项目——学生试卷分数统计
C语言实战项目——学生试卷分数统计
|
4天前
|
C语言
【海贼王编程冒险 - C语言海上篇】怎样用C语言实现简单的扫雷游戏?
【海贼王编程冒险 - C语言海上篇】怎样用C语言实现简单的扫雷游戏?
5 1
|
4天前
|
C语言
【海贼王编程冒险 - C语言海上篇】C语言如何实现简单的三子棋游戏?
【海贼王编程冒险 - C语言海上篇】C语言如何实现简单的三子棋游戏?
7 1
|
2天前
|
C语言
C语言实现猜数字游戏:代码详解与函数解析
C语言实现猜数字游戏:代码详解与函数解析
5 0
|
2天前
|
存储 C语言
C语言实战 | “俄罗斯方块”游戏重构
摘要(Markdown格式): 在之前的游戏中,全局变量的过度使用导致存储浪费和低代码通用性。以“贪吃蛇”为例,显示功能依赖全局变量,限制了函数的复用。通过参数传递代替全局变量,如在“俄罗斯方块”等游戏中控制物体运动的函数,可提升代码重用性和模块化。重构过程中,即使小到变量命名和代码精简的改进,也能逐步带来程序质量的显著提升。
5 0
|
4天前
|
C语言
【C语言基础篇】字符串处理函数(四)strcmp的介绍及模拟实现
【C语言基础篇】字符串处理函数(四)strcmp的介绍及模拟实现
|
15小时前
|
Java C语言 C++
定义C语言的int main()函数
定义C语言的int main()函数
|
4天前
|
C语言
C语言prinf函数
C语言prinf函数
10 4
|
2天前
|
存储 移动开发 C语言
技术心得记录:嵌入式开发中常用到的C语言库函数
技术心得记录:嵌入式开发中常用到的C语言库函数
|
4天前
|
编译器 程序员 Serverless
函数(C语言)
函数(C语言)