吕橙
摘要:运用EasyX和C语言在Visual Studio 2019 平台上设计开发了一款贪吃蛇游戏。通过游戏的开发,达到学习C语言和熟悉软件开发流程的目的。
关键词:EasyX;Visual Studio 2019;贪吃蛇游戏
中图分类号:TP311.52 文献标识码:A
文章编号:1009-3044(2021)03-0118-04
Abstract: Using EasyX and C language, a snake game is designed and developed on the platform of visual studio 2019. Through the development of the game, to achieve the purpose of learning C language and familiar with the software development process.
Key words: EasyX; Visual Studio 2019; Snake Game
1 背景
经典的贪吃蛇游戏是一款休闲益智类游戏,有PC和手机等多平台版本。该游戏通过控制蛇头方向吃食物,从而使得蛇变得越来越长,游戏通过键盘操作,简单方便,老少皆宜。
文献[1]利用C#开发环境,开发实现了贪吃蛇游戏。文献[2]基于 HTML5 技术,采用 JavaScript 语言编程实现了简单的贪吃蛇游戏。文献[3]利用Protues 设计软件并仿真电路,制作了相应的PCB板,从硬件和软件两方面模拟了贪吃蛇游戏。文献[4]采用VS2010介绍了C++版的双人贪吃蛇游戏设计思想,文献[5]采用OpenGL实现了多人在线贪吃蛇游戏,可供多人多终端同步游戏。
贪吃蛇游戏常用于学生课设、实验等实践环节,本文用EasyX和Visual Studio 2019软件实现贪吃蛇游戏。
2 贪吃蛇游戏功能分析
2.1 游戏规则分析
一条蛇出现在封闭空间中,通过键盘控制,蛇可以向上下左右四个方向移动。随机产生食物,如果蛇头撞到食物,食物消失,蛇身体长增加一节,得分加100,刷新食物。游戏可以设置蛇移动的速度。如果蛇在前進过程中撞到墙或自己身体,则游戏结束。
2.2 游戏功能分析
游戏功能设计为3个模块:
1)初始化模块,主要包括初始化地图、难度设置、初始化蛇的属性、初始化食物等;
2)游戏控制模块,主要包括产生食物、移动蛇、按键控制、死亡判断;
3)统计模块,主要包括实时显示玩家积分,玩家积分每超过500,自动升级到下一个难度级别,随机出现的食物增加1个。
贪吃蛇游戏功能如图1所示。
3 贪吃蛇游戏详细设计
3.1 初始化模块
功能主要包括初始化地图、难度设置、初始化蛇、初始化食物等。其中,难度设置,难度I每次产生一个食物,难度Ⅱ每次产生两个食物,难度Ⅲ每次产生三个食物,依次类推,最多每次产生食物不超过10个。
坐标点、蛇、食物的结构体如下:
// 坐标属性
struct point
{
int x;
int y;
};
// 蛇的属性
struct Snake
{
vector
point next; // 为下一节预留的位置
vector
int num; // 长度
int position; // 方向
}snake;
// 食物的属性
struct Food
{
point fdxy[10]; // 坐标
int grade; // 分数
int num = 1; // 食物总数
COLORREF color[10]; // 食物颜色
}food;
enum position { up, down, left, right }; // 枚举蛇的方向
3.2 游戏控制模块
游戏执行过程中,通过按键控制蛇的走向,移动蛇,不停地产生食物,吃掉食物后,玩家积分增加,如果超过一定积分,难度升级,每次同时产生多个食物,判断是否撞墙或撞到自己,如果撞到了游戏结束。
游戏流程如图2所示。
3.3 统计模块
游戏过程中,蛇每吃掉一个食物,累积积分100,积分每超过500自动升级到下一个难度级别,系统实时显示玩家积分。
4 贪吃蛇游戏代码实现
4.1 游戏中的坐标系
以左上角(0,0)为游戏界面的原点,沿水平方向向右是x轴,逐渐增加,沿垂直方向向下是y轴,逐渐增加。游戏界面设计原理如图3所示。
4.2 初始化模块代码实现
初始化模块,主要是初始化游戏界面,初始化蛇,初始化食物。主要代码如下:
初始化游戏设置函数:设置游戏界面尺寸,设置背景颜色,初始化随机数种子,设置文字前景色和背景色。
initgraph(800, 600);
setbkcolor(RGB(95, 183, 72));
srand((unsigned)time(NULL));
settextcolor(BLUE);
setbkmode(TRANSPARENT); // 设置文字输出模式为透明
degree_dif= 1; // 设置游戏难度
初始化蛇函数:初始化蛇头位置,蛇身颜色,蛇身字节数量。
// 初始化蛇
void initSnake()
{
point xy;
xy.x = 20;
xy.y = 0;
snake.xy.push_back(xy);
snake.color.push_back(RGB(rand() % 256, rand() % 256, rand() % 256)); // 设置一个随机颜色
xy.x = 10;
xy.y = 0;
snake.xy.push_back(xy);
snake.color.push_back(RGB(rand() % 256, rand() % 256, rand() % 256)); // 设置一个随机颜色
xy.x = 0;
xy.y = 0;
snake.xy.push_back(xy);
snake.color.push_back(RGB(rand() % 256, rand() % 256, rand() % 256)); // 设置一个随机颜色
snake.num = 3;
snake.position = right;
}
初始化食物函數:初始化食物位置,食物随机产生到蛇身处理判断。
// 初始化食物
void initFood(int num /* 食物编号 */)
{
int i;
food.fdxy[num].x = rand() % 80 * 10;
food.fdxy[num].y = rand() % 60 * 10;
for (i = 0; i < snake.num; i++)
if (food.fdxy[num].x == snake.xy[i].x && food.fdxy[num].y == snake.xy[i].y) // 避免食物生成在蛇身上
{
food.fdxy[num].x = rand() % 80 * 10;
food.fdxy[num].y = rand() % 60 * 10;
}
}
4.3 游戏控制模块代码实现
该模块需要进行按键控制,移动蛇,产生食物,死亡判断等操作。主要代码如下:
按键控制函数:根据用户按键,进行判断,“w”“s”“a”“d”分别表示“上”“下”“左”“右”四个方向。
// 按键控制
void keyDown()
{
char userKey = _getch();
if (userKey == -32) // 表明这是方向键
userKey = -_getch(); // 获取具体方向,并避免与其他字母的 ASCII 冲突
switch (userKey)
{
case 'w':
case 'W':
if (snake.position != down)
snake.position = up;
break;
case 's':
case 'S':
if (snake.position != up)
snake.position = down;
break;
case 'a':
case 'A':
if (snake.position != right)
snake.position = left;
break;
case 'd':
case 'D':
if (snake.position != left)
snake.position = right;
break;
}
}
产生食物函数:吃掉一个食物,积分增加100,积分每得500分,增加一个食物,游戏难度加一。
void createFood()
{
int i;
for (i = 0; i <= food.num - 1; i++)
if (snake.xy[0].x == food.fdxy[i].x && snake.xy[0].y == food.fdxy[i].y)
{
snake.num++;
snake.xy.push_back(snake.next); // 新增一个节到预留位置
snake.color.push_back(food.color[i]); // 将新增节的颜色设置为当前吃掉食物的颜色
food.grade += 100;
initFood(i);
if (food.num < 10 && food.grade % 500 == 0 && food.grade != 0)
{
food.num++; // 每得 500 分,增加一个食物,但食物总数不超过 10 个
degree_dif++;
initFood(food.num - 1); // 初始化新增加的食物
}
break;
}
}
移动蛇函数:蛇头带领蛇身移动,不能反向移动,蛇头可以“上”“下”“左”“右”方向变化。
// 移动蛇
void moveSnake()
{
int i;
// 将预留节设置为未移动前的尾节
snake.next = snake.xy[snake.num - 1];
// 将除蛇头以外的节移动到它的前面一節
for (i = snake.num - 1; i >= 1; i--)
snake.xy[i] = snake.xy[i - 1];
// 根据当前移动方向移动蛇头
switch (snake.position)
{
case right:
snake.xy[0].x += 10;
break;
case left:
snake.xy[0].x -= 10;
break;
case up:
snake.xy[0].y -= 10;
break;
case down:
snake.xy[0].y += 10;
}
}
死亡判断函数:蛇撞到自己或撞到墙,游戏结束。
// 游戏结束
bool snakeStatus()
{
// 撞墙,将墙向外扩展一圈(否则蛇无法到达地图边缘)
if (snake.xy[0].y <= -10 && snake.position == up) return true;
if (snake.xy[0].y + 10 >= 610 && snake.position == down) return true;
if (snake.xy[0].x <= -10 && snake.position == left) return true;
if (snake.xy[0].x + 10 >= 810 && snake.position == right) return true;
// 撞自己
for (int i = 1; i < snake.num; i++)
{
if (snake.xy[0].x <= snake.xy[i].x + 10 && snake.xy[0].x >= snake.xy[i].x && snake.xy[0].y == snake.xy[i].y && snake.position == left)
return true;
if (snake.xy[0].x + 10 >= snake.xy[i].x && snake.xy[0].x + 10 <= snake.xy[i].x + 10 && snake.xy[0].y == snake.xy[i].y && snake.position == right)
return true;
if (snake.xy[0].y <= snake.xy[i].y + 10 && snake.xy[0].y >= snake.xy[i].y && snake.xy[0].x == snake.xy[i].x && snake.position == up)
return true;
if (snake.xy[0].y + 10 >= snake.xy[i].y && snake.xy[0].y + 10 <= snake.xy[i].y + 10 && snake.xy[0].x == snake.xy[i].x && snake.position == down)
return true;
}
return false;
}
4.4 统计功能代码实现
该模块的代码主要是实时统计并显示玩家积分,积分累加每超过500,自动升级进入到下一个难度级别。
5 系统测试与结果
游戏实现了贪吃蛇游戏基本功能,可以通过操纵“w”“s”“a”“d”实现蛇头的上下左右转动,运行界面如图4所示。
游戏功能还可以进一步完善。比如:
1)通过标准键盘的方向键(left、right、down、up)控制贪吃蛇的移动。
2)游戏界面设置暂停和启动功能键。
6 结束语
本文以贪吃蛇游戏为原型,利用EasyX完成了游戏的基本运行,包括游戏的初始化设置、游戏控制模块和统计模块,游戏操作简单,运行准确,反应速度快,基本上满足了学生课设要求,提高学生的兴趣,带给学生具有挑战度的游戏类编程体验。
参考文献:
[1] 商利华.C#版贪吃蛇游戏的设计与实现[J].电脑与电信,2015(11):65-67.
[2] 施瑶.基于HTML5的贪吃蛇游戏设计与实现[J].福建电脑,2018,34(7):118-119.
[3] 汪源,李宛聪,黄文敏,等.一种基于LabVIEW的贪吃蛇游戏的设计[J].信息与电脑(理论版),2018(9):102-103,106.
[4] 李嘉诚.基于VS2010的双人贪吃蛇设计与实现[J].数字技术与应用,2015(4):164.
[5] 沈旭,孟巍,彭正超.多人在线版贪吃蛇3D游戏App设计与开发[J].计算技术与自动化,2019,38(4):126-132.
【通联编辑:谢媛媛】