C++编写贪吃蛇小游戏快速入门
刚学完C++。一时兴起,就花几天时间手动做了个贪吃蛇,后来觉得不过瘾,于是又加入了AI功能。希望大家Enjoy It.
效果图示
AI模式演示
整体规划+原理
大体上可以分为图上所示的几个类。不过……怎么看都有点强行面向对象的味道在里面。。[哭笑][哭笑][哭笑]。不管了……代码写得可能有点凌乱,下面我会为大家一一讲解。
整个程序设计的原理就是:主函数死循环,不断刷新打印贪吃蛇和食物。这样每循环一次,就类似电影里面的一帧,最终显示的效果就是蛇会动起来。
01 初始化工作-游戏设置
游戏设置和相关初始化放在了一个类里面,并进行了静态声明。主要设置了游戏窗口的长和款。并在GameInit()函数里面设置了窗口大小,隐藏光标,初始化随机数种子等。代码如下:
//游戏设置相关模块,把函数都放到一个类里面了。函数定义为static静态成员,不生成实体也可以直接调用
class GameSetting
{
public:
//游戏窗口的长宽
static const int window_height = 40;
static const int window_width = 80;
public:
static void GameInit()
{
//设置游戏窗口大小
char buffer[32];
sprintf_s(buffer, "mode con cols=%d lines=%d",window_width, window_height);
system(buffer);
//隐藏光标
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(handle, &CursorInfo);//获取控制台光标信息
CursorInfo.bVisible = false; //隐藏控制台光标
SetConsoleCursorInfo(handle, &CursorInfo);//设置控制台光标状态
//初始化随机数种子
srand((unsigned int)time(0));
}
};
用到了几个相关的Windows API,本文不做过多介绍,大家百度即可。
02 打印信息类
该类主要是用来打印一些游戏相关信息的。该类大体如下:
下面挑几个重点的来讲:
2.1 画地图边界
这个函数主要是根据上面所给的游戏窗口长宽来打印地图边界的。其中还划分了几个区域,主要用来放不同的信息的。
//画地图边界
static void DrawMap()
{
system("cls");
int i, j;
for (i = 0; i < GameSetting::window_width; i++)
cout << "#";
cout << endl;
for (i = 0; i < GameSetting::window_height-2; i++)
{
for (j = 0; j < GameSetting::window_width; j++)
{
if (i == 13 && j >= GameSetting::window_width - 29)
{
cout << "#";
continue;
}
if (j == 0 || j == GameSetting::window_width - 29 || j == GameSetting::window_width-1)
{
cout << "#";
}
else
cout << " ";
}
cout << endl;
}
for (i = 0; i < GameSetting::window_width; i++)
cout << "#";
}
划分区域如下图,#就是边框了:
2.2 画出分数和模式
该函数主要是在右上角画出成绩和游戏模式的,在绘制之前会进行刷新处理。先清除,再重新打印。用到了一个gotoxy()函数。这个函数主要是移动光标到(x, y)坐标处的。关于(x, y)的位置,根据实际情况调整即可。
//画分数
static void DrawScore(int score)
{
gotoxy(GameSetting::window_width - 22+14, 6);
cout << " ";
gotoxy(GameSetting::window_width - 22+14, 4);
cout << " ";
gotoxy(GameSetting::window_width - 22, 6);
cout << "当前玩家分数: " << score << endl;
gotoxy(GameSetting::window_width - 22, 4);
cout << "当前游戏速度: " << 10 - speed / 25 << endl;
}
03 食物类
食物类定义了食物的坐标,随机生成规则,和画出食物等一系列操作。其中食物坐标我们用了一个结构体:
typedef struct
{
int x;
int y;
}COORDINATE;
该结构体两个成员,分别保存坐标的(x, y)。蛇身的坐标也会用到这个结构体。
有关食物类的大体如下:
下面我们还是挑几个重点来讲。
3.1 随机生成食物
随机生成食物,原则上不允许食物出现在蛇身的位置上,如果有。我们重新生成。注意地图的范围,就是区域左边一块。实际情况根据自身的地图范围来调整食物坐标的范围,注意不要越界。用rand()函数获得随机坐标。代码如下:
void RandomXY(vector<COORDINATE> & coord)
{
m_coordinate.x = rand() % (GameSetting::window_width - 30) + 1;
m_coordinate.y = rand() % (GameSetting::window_height - 2) + 1;
unsigned int i;
//原则上不允许食物出现在蛇的位置上,如果有,重新生成
for (i = 0; i < coord.size(); i++)
{
//食物出现在蛇身的位置上。重新生成
if (coord[i].x == m_coordinate.x && coord[i].y == m_coordinate.y)
{
m_coordinate.x = rand() % (GameSetting::window_width - 30) + 1;
m_coordinate.y = rand() % (GameSetting::window_height - 2) + 1;
i = 0;
}
}
}
然后,在构造函数里面传入蛇身的坐标。即可生成食物。
3.2 画出食物
画出食物比较简单了,gotoxy到随机生成的坐标之后,cout就行。我们在这还设置了一个食物颜色为红色。代码如下:
void DrawFood()
{
setColor(12,