C++ EasyX 实现贪吃蛇游戏完整代码与逻辑解析

Ryan
Ryan
发布时间:2026-10-16| 9人浏览过
原创

本文介绍了如何利用C++标准库配合EasyX图形库开发一款经典的贪吃蛇控制台游戏。文章从需求分析出发,详细阐述了蛇的身体结构、食物生成机制、移动算法以及边界与自身碰撞的检测逻辑。通过分段解析关键代码并展示完整的可运行源文件,帮助读者理解面向对象思想在游戏逻辑中的应用,最终实现支持键盘控制、速度调节及分数统计的完整游戏体验。

系统设计与需求分析

开发一个标准的贪吃蛇游戏,需要将整体功能拆分为四个核心模块:用户界面、游戏地图、蛇实体与食物实体。

  • 界面管理:提供开始、结束按钮及难度(速度)选择,提升交互体验。
  • 地图坐标:作为全局定位基准,通常设定为固定宽高的矩形区域(如640x480像素)。
  • 蛇属性:核心数据包括当前坐标数组、移动方向、身体长度及移动速度。行为逻辑涵盖自动移动、进食增长及死亡判定。
  • 食物生成:在地图范围内随机分布,并与蛇头坐标进行碰撞判断。

数据结构定义与初始化

使用 struct 分别定义蛇和食物的状态。其中,蛇通过二维坐标数组记录每一节身体的位置,食物则记录其当前位置及玩家得分。

// 蛇的结构体定义
typedef struct Snake {
 int speed; // 速度等级
 pair<int, int> coor[MAXSIZE]; // 身体各节点坐标
 int dir; // 方向标识:1上, 2右, 3下, 4左
 int length; // 当前长度
};

// 食物结构体定义
typedef struct food {
 pair<int, int> place[MAXSIZE]; // 预设食物池或动态更新
 int score; // 累计分数
};

初始化流程:

  1. 食物初始化:重置分数,利用 srand(time(NULL)) 生成随机种子,计算食物在屏幕范围内的初始坐标。
  2. 蛇初始化:设定初始长度为3,头部朝向右侧,初始坐标位于地图左侧中部区域。
void Initfood(food& F)
{
 F.score = 0;
 srand(time(NULL));
 // 预生成多个食物坐标备用
 for (int i = 0; i < 100; i++)
 {
  F.place[i].first = rand() % (640 - R) + R;
  F.place[i].second = rand() % (480 - R) + R;
 }
}

void hatch(Snake &S)
{
 S.length = 3;
 S.dir = 2; // 默认向右
 S.speed = 0;
 // 设置初始三节身体坐标
 for (int i = 0; i < 3; i++)
 {
  S.coor[i].first = 40 - i * 10;
  S.coor[i].second = 30;
 }

核心运动与绘制逻辑

游戏的视觉效果由绘制函数负责,而逻辑变化由移动函数驱动。两者结合形成平滑的游戏循环。

第1步:实现蛇身与食物绘制

遍历蛇的坐标数组,绘制头部与身体。头部使用绿色实心矩形区分,身体使用白色空心矩形。随后绘制当前目标食物。

// 绘制蛇的主体部分
for (int i = 0; i < S.length; i++)
{
 int x = S.coor[i].first;
 int y = S.coor[i].second;
 if (i == 0) // 蛇头
 {
  setfillcolor(GREEN);
  solidrectangle(x - R, y - R, x + R, y + R);
 }
 else // 蛇身
 {
  setcolor(WHITE);
  rectangle(x - R, y - R, x + R, y + R);
 }
}

第2步:处理蛇的运动轨迹

蛇的移动本质是坐标数据的偏移。新头的坐标由当前方向决定,而其余身体节点的坐标依次继承前一个节点的位置(即 coor[i] = coor[i-1]),从而实现尾部跟随效果。

void movesnake(Snake& S)
{
 // 从倒数第二节开始,坐标向前一位继承
 for (int i = S.length - 1; i > 0; i--)
 {
  S.coor[i].first = S.coor[i - 1].first;
  S.coor[i].second = S.coor[i - 1].second;
 }
 
 // 根据方向更新蛇头坐标
 switch (S.dir)
 {
 case 1: S.coor[0].second -= 10; break; // 上
 case 2: S.coor[0].first += 10; break;  // 右
 case 3: S.coor[0].second += 10; break; // 下
 case 4: S.coor[0].first -= 10; break;  // 左
 }
}

第3步:键盘输入控制

使用 _getch() 同步获取按键状态。为防止蛇直接反向移动导致身体重叠(如向右移动时不能直接按左键),在改变方向时需增加校验逻辑。支持方向键及WASD键位。

void control_dir(int& DIR)
{
 char ch = _getch();
 switch (ch)
 {
 case 72: case 'W': case 'w': // 向上
  if (DIR != 3) DIR = 1; break;
 case 77: case 'D': case 'd': // 向右
  if (DIR != 4) DIR = 2; break;
 case 80: case 'S': case 's': // 向下
  if (DIR != 1) DIR = 3; break;
 case 75: case 'A': case 'a': // 向左
  if (DIR != 2) DIR = 4; break;
 }
}

胜负判定与游戏循环

碰撞检测机制

游戏结束条件主要包含两类:碰壁与自噬。

  • 碰壁:蛇头横纵坐标超出地图范围(小于0或大于最大宽高)。
  • 自噬:蛇头坐标与身上任意一节(从头节之后的第一节算起)重合。
int isdead(Snake S)
{
 // 1. 检测是否撞墙
 if (S.coor[0].first > 640-R || S.coor[0].first < R || 
     S.coor[0].second > 480-R || S.coor[0].second <= R)
  return 1;
 
 // 2. 检测是否咬到自己 (忽略蛇头索引0,从索引4开始检测,因为短于4节的蛇不可能咬到自己)
 for (int i = 4; i < S.length; i++)
 {
  if (abs(S.coor[0].first - S.coor[i].first) <= 2*R && 
      abs(S.coor[0].second - S.coor[i].second) <= 2*R)
   return 1;
 }
 return 0;
}

进食逻辑

当蛇头中心坐标落入食物所在矩形区域内时判定为吃到。触发后增加分数、延长蛇身长度,并消耗下一个预生成的食物坐标。

void Eating(Snake& S, food& F)
{
 // 简单的矩形碰撞检测
 if (S.coor[0].first >= F.place[F.score].first - R && 
     S.coor[0].first <= F.place[F.score].first + R &&
     S.coor[0].second >= F.place[F.score].second - R && 
     S.coor[0].second <= F.place[F.score].second + R)
 {
  F.score++; // 加分
  S.length++; // 变长
 }
}

完整代码整合

将上述所有模块整合进主循环,利用 BeginBatchDraw() 开启双缓冲绘图以减少闪烁,并通过 Sleep() 控制刷新率来实现不同等级的游戏速度。以下是合并后的完整可执行源码:

#include <iostream>
#include <graphics.h>
#include <conio.h>
#include <time.h>
using namespace std;

#define MAXSIZE 100
#define R 5

typedef struct Snake {
 int speed;
 pair<int, int> coor[MAXSIZE];
 int dir;
 int length;
};

typedef struct food {
 pair<int, int> place[MAXSIZE];
 int score;
};

// ... (此处省略前述已列出的子函数定义:Initfood, hatch, control_speed, control_dir, movesnake, isdead, Eating) ...

void drawsnake(Snake& S, food F)
{
 char out[16] = {};
 BeginBatchDraw();
 while (1)
 {
  cleardevice();
  // 绘制蛇
  for (int i = 0; i < S.length; i++)
  {
   int x = S.coor[i].first;
   int y = S.coor[i].second;
   if (i == 0)
   {
    setfillcolor(GREEN);
    solidrectangle(x - R, y - R, x + R, y + R);
   }else
   {
    setcolor(WHITE);
    rectangle(x - R, y - R, x + R, y + R);
   }
  }
  // 绘制食物
  int m = F.place[F.score].first;
  int n = F.place[F.score].second;
  setfillcolor(WHITE);
  solidrectangle(m-R, n-R, m+R, n+R);

  // 显示得分
  sprintf_s(out, "%d", F.score * S.speed);
  setbkmode(0);
  outtextxy(570, 20, "得分");
  outtextxy(620, 20, out);

  FlushBatchDraw();
  // 控制游戏帧率/速度
  Sleep(200-S.speed*30);

  // 检查按键输入
  while(_kbhit())
  {
   control_dir(S.dir);
  }

  movesnake(S);
  Eating(S, F);
  if (isdead(S))
   break;
 }
 cleardevice();
 sprintf_s(out, "%d", F.score * S.speed);
 outtextxy(280, 180, "游戏结束");
 outtextxy(280, 200, "按Enter键返回主页");
 FlushBatchDraw();
 getchar();
 EndBatchDraw();
}

void menu()
{
 initgraph(640, 480);
 int flag = 1;
 while (flag)
 {
  cleardevice();
  outtextxy(280, 180, "贪吃蛇游戏");
  outtextxy(280, 200, "按1开始游戏");
  outtextxy(280, 220, "按2结束游戏");
  char ch = _getch();
  switch (ch)
  {
  case '1':
  {
   food F;
   Initfood(F);
   Snake S;
   hatch(S);
   control_speed(S.speed); // 提示用户选择速度
   drawsnake(S, F);
   break;
  }  
  case '2':
   flag = 0;
   break;
  default : break;
  }
 }
 closegraph();
}

int main(void)
{
 menu();
 return 0;
}

以上就是利用 C/C++ 和 EasyX 实现贪吃蛇游戏的全部内容。通过拆解数据结构、渲染逻辑与碰撞检测,您可以清晰了解基于网格移动的经典游戏是如何构建的。更多关于 C++ 图形化编程的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。