贪吃蛇游戏框架
├── 基础框架
│ ├── 头文件引入
│ ├── 常量和宏定义
│ └── 窗口初始化
│
├── 数据结构系统
│ ├── Pos结构体(位置和颜色)
│ ├── Snake结构体(蛇的属性)
│ ├── Food结构体(食物属性)
│ └── DIR枚举(方向控制)
│
├── 初始化系统
│ ├── 随机种子设置
│ ├── 蛇属性初始化
│ ├── 蛇身位置初始化
│ └── 食物生成
│
├── 绘制系统
│ ├── 清屏操作
│ ├── 蛇身绘制
│ ├── 食物绘制
│ └── 分数显示
│
├── 控制系统
│ ├── 键盘输入检测
│ ├── 方向键处理
│ └── 防反向移动逻辑
│
├── 移动系统
│ ├── 蛇身跟随算法
│ └── 蛇头方向移动
│
├── 食物系统
│ ├── 食物生成算法
│ ├── 碰撞检测
│ ├── 分数增加
│ └── 蛇身增长
│
└── 游戏循环
├── 绘制→移动→输入→检测
└── 速度控制
游戏实现步骤分析
1. 基础框架搭建
cpp
// 1. 包含必要的头文件
#include <graphics.h> // EasyX图形库
#include <conio.h> // 控制台输入输出
#include <iostream> // 标准输入输出
using namespace std;
// 2. 定义游戏窗口大小和常量
const int WIDTH = 640;
const int HEIGHT = 480;
#define MAX_SNAKE 500
2. 数据结构设计
cpp
// 3. 定义位置结构体
struct Pos {
int x;
int y;
DWORD color;
};
// 4. 定义蛇结构体
struct Snake {
int num; // 蛇节数
int dir; // 方向
int score; // 分数
int size; // 尺寸
int speed; // 速度
Pos coor[MAX_SNAKE]; // 坐标数组
};
// 5. 定义食物结构体
struct Food {
int x;
int y;
DWORD color;
bool flag; // 是否存在
};
// 6. 定义方向枚举
enum DIR { UP, DOWN, LEFT, RIGHT };
3. 游戏初始化
cpp
void GameInit() {
// 初始化随机种子
srand(GetTickCount());
// 设置蛇的初始属性
snake.num = 3;
snake.dir = RIGHT;
snake.score = 0;
snake.size = 10;
snake.speed = 10;
// 初始化蛇身位置和颜色
snake.coor[0].x = 20;
snake.coor[0].y = 0;
snake.coor[0].color = RGB(rand() % 256, rand() % 256, rand() % 256);// 随机生产颜色
snake.coor[1].x = 10;
snake.coor[1].y = 0;
snake.coor[1].color = RGB(rand() % 256, rand() % 256, rand() % 256);
snake.coor[2].x = 0;
snake.coor[2].y = 0;
snake.coor[2].color = RGB(rand() % 256, rand() % 256, rand() % 256);
// 初始化食物
createFood();
}
4. 游戏绘制系统
cpp
void GameDraw() {
cleardevice(); // 清屏
// 绘制蛇身
for (int i = 0; i < snake.num; i++) {
setfillcolor(snake.coor[i].color);
fillrectangle(snake.coor[i].x, snake.coor[i].y,snake.coor[i].x + snake.size, snake.coor[i].y + snake.size);
}
// 绘制食物
if (food.flag) {
setfillcolor(food.color);
solidellipse(food.x, food.y, food.x + 10, food.y + 10);
}
// 绘制分数
char temp[20] = "";
sprintf(temp, "分数: %d", snake.score);
outtextxy(10, 10, temp);
}
5. 输入控制系统
cpp
void GameController() {
if (_kbhit()) {
char key = _getch();
switch (key) {
case 72: if (snake.dir != DOWN) snake.dir = UP; break;
case 80: if (snake.dir != UP) snake.dir = DOWN; break;
case 75: if (snake.dir != RIGHT) snake.dir = LEFT; break;
case 77: if (snake.dir != LEFT) snake.dir = RIGHT; break;
}
}
}
6. 移动逻辑实现
cpp
void GameMove() {
// 蛇身跟随移动
for (int i = snake.num - 1; i > 0; i--) {
snake.coor[i].x = snake.coor[i - 1].x;
snake.coor[i].y = snake.coor[i - 1].y;
}
// 蛇头移动
switch (snake.dir) {
case UP: snake.coor[0].y -= snake.speed; break;
case DOWN: snake.coor[0].y += snake.speed; break;
case LEFT: snake.coor[0].x -= snake.speed; break;
case RIGHT: snake.coor[0].x += snake.speed; break;
}
}
7. 食物系统
cpp
void createFood() {
food.x = rand() % (WIDTH / 10) * 10;
food.y = rand() % (HEIGHT / 10) * 10;
food.color = RGB(rand() % 256, rand() % 256, rand() % 256);
food.flag = true;
}
void EatFood() {
if (food.flag && snake.coor[0].x == food.x && snake.coor[0].y == food.y) {
food.flag = false;
snake.num++;
snake.score += 10;
snake.coor[snake.num - 1].color = RGB(rand() % 256, rand() % 256, rand() % 256);
createFood();
}
}
8. 游戏主循环
cpp
int main() {
initgraph(WIDTH, HEIGHT);
setbkcolor(RGB(207, 214, 229));
GameInit();
while (true) {
GameDraw(); // 绘制
GameMove(); // 移动
if(_kbhit()) { // 输入检测
GameController();
}
EatFood(); // 食物检测
Sleep(100); // 控制速度
}
return 0;
}
9. 完整代码
cpp
// 导入图形界面库 EasyX
#include <graphics.h>
//控制键盘的头文件
#include<conio.h>
#include<iostream>
using namespace std;
// 定义游戏区域大小
const int WIDTH = 640;
const int HEIGHT = 480;
#define MAX_SNAKE 500 // 常量
struct Pos{
int x;
int y;
DWORD color;//DWORD 是 Windows API 中定义的数据类型
};
struct Snake{
int num; // 蛇身体的节数
int dir; // 蛇的方向
int score; // 分数
int size; // 蛇的宽和高
int speed; // 蛇的速度
// 记录蛇的坐标数组
struct Pos coor[MAX_SNAKE];
};
struct Snake snake;//结构体变量
struct Food{
int x;
int y;
DWORD color;
bool flag; // 是否被吃掉
} food;
enum DIR
{
UP,
DOWN,
LEFT,
RIGHT
};
// 初始化一下数据
void GameInit() {
//蛇的身体的颜色随机变化
srand(GetTickCount());
snake.num = 3;
snake.dir = RIGHT;
snake.score = 0;
snake.size = 10;
snake.speed = 10;
// 初始化蛇身位置和颜色
for (int i = 0; i < snake.num; i++) {
snake.coor[i].x = 20 - i * 10;
snake.coor[i].y = 0;
snake.coor[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);
}
// 初始化食物 颜色随机变化
createFood();
}
// 画蛇 画食物 画分数
void GameDraw() {
cleardevice();
for (int i = 0; i < snake.num; i++)
{
// 填充一下颜色
setfillcolor(snake.coor[i].color);
// 画矩形(修正后的)
fillrectangle(snake.coor[i].x, snake.coor[i].y,snake.coor[i].x + snake.size, snake.coor[i].y + snake.size);
}
// 绘制食物
if (food.flag)
{
setfillcolor(food.color);
solidellipse(food.x, food.y, food.x + 10, food.y + 10);
}
// 绘制分数
char temp[20] = "";
sprintf(temp, "分数: %d", snake.score);
outtextxy(10, 10, temp);
}
//控制蛇的方向
void GameController() {
// 获取键盘
char key = _getch();
// 控制蛇不能往回走
switch (key) {
case 72: if (snake.dir != DOWN) snake.dir = UP; break;
case 80: if (snake.dir != UP) snake.dir = DOWN; break;
case 75: if (snake.dir != RIGHT) snake.dir = LEFT; break;
case 77: if (snake.dir != LEFT) snake.dir = RIGHT; break;
}
//cout << (int)key << endl;
}
// 让蛇动起来
void GameMove() {
// 循环部分 - 控制蛇身移动
for (int i = snake.num - 1; i > 0; i--)
{
snake.coor[i].x = snake.coor[i - 1].x;
snake.coor[i].y = snake.coor[i - 1].y;
}
// switch部分 - 控制蛇头移动 [蛇头控制方向,蛇身跟随前一个位置]
switch (snake.dir) {
case UP:
snake.coor[0].y -= snake.speed;
break;
case DOWN:
snake.coor[0].y += snake.speed;
break;
case LEFT:
snake.coor[0].x -= snake.speed;
break;
case RIGHT:
snake.coor[0].x += snake.speed;
break;
}
}
// 创建新食物的函数
void createFood() {
food.x = rand() % (WIDTH / 10) * 10;
food.y = rand() % (HEIGHT / 10) * 10;
food.color = RGB(rand() % 256, rand() % 256, rand() % 256);
food.flag = true;
}
void EatFood() {
// 碰撞检测
if (food.flag && snake.coor[0].x == food.x && snake.coor[0].y == food.y)
{
// 吃到了
food.flag = false;
snake.num++;
snake.score += 10;
snake.coor[snake.num - 1].color = RGB(rand() % 256, rand() % 256, rand() % 256);
// 吃完了 在重新创建一个新的食物
createFood();
}
}
int main() {
// 初始化图形窗口
initgraph(WIDTH, HEIGHT);
// 设置背景色为浅蓝灰色
setbkcolor(RGB(207, 214, 229));
//清屏再重新绘制所有内容
cleardevice();
// 初始化蛇的数据
GameInit();
// 游戏主循环
while (true) {
GameDraw();
GameMove();
// 如果按了键盘就会执行
if(_kbhit()){
GameController();
}
EatFood();
Sleep(100);
}
return 0;
}
10. 改进建议
- 添加碰撞检测 - 检测撞墙和自身碰撞
- 改进输入处理 - 使用Windows API处理方向键
- 添加游戏状态 - 游戏开始、暂停、结束状态优化
- 食物生成 - 避免食物生成在蛇身上添
- 加音效 - 吃食物和游戏结束的音效