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) 根据游戏规则,更新每一个角色的数据,形成新的画面。

目录
相关文章
|
1月前
|
C语言
扫雷游戏(用C语言实现)
扫雷游戏(用C语言实现)
100 0
|
14天前
|
C语言 Windows
C语言课设项目之2048游戏源码
C语言课设项目之2048游戏源码,可作为课程设计项目参考,代码有详细的注释,另外编译可运行文件也已经打包,windows电脑双击即可运行效果
26 1
|
1月前
|
编译器 C语言
猜数字游戏实现#C语言
猜数字游戏实现#C语言
83 1
|
1月前
|
存储 C语言
揭秘C语言:泊舟的猜数字游戏
揭秘C语言:泊舟的猜数字游戏
|
1月前
|
存储 定位技术 API
C语言项目实战:贪吃蛇
C语言项目实战:贪吃蛇
|
1月前
|
C语言
初学者指南:使用C语言实现简易版扫雷游戏
初学者指南:使用C语言实现简易版扫雷游戏
37 0
|
1月前
|
C语言
C语言扫雷游戏(详解)
C语言扫雷游戏(详解)
40 0
【C语言】函数递归实现——扫雷小游戏(详细步骤)
【C语言】函数递归实现——扫雷小游戏(详细步骤)
【C语言】函数递归实现——扫雷小游戏(详细步骤)
|
1月前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
35 3
|
13天前
|
C语言
c语言调用的函数的声明
被调用的函数的声明: 一个函数调用另一个函数需具备的条件: 首先被调用的函数必须是已经存在的函数,即头文件中存在或已经定义过; 如果使用库函数,一般应该在本文件开头用#include命令将调用有关库函数时在所需要用到的信息“包含”到本文件中。.h文件是头文件所用的后缀。 如果使用用户自己定义的函数,而且该函数与使用它的函数在同一个文件中,一般还应该在主调函数中对被调用的函数做声明。 如果被调用的函数定义出现在主调函数之前可以不必声明。 如果已在所有函数定义之前,在函数的外部已做了函数声明,则在各个主调函数中不必多所调用的函数在做声明
28 6