先说明下:本文来源:https://blog.youkuaiyun.com/silence1772/article/details/55005008
写在前面,这个项目,希望大家先下载下来,玩一玩。然后2天左右把代码敲一遍。再花一到两天写个博客,写下自己的理解,这样自己就能比较清楚。
github网址: https://github.com/LLM1602/greedy_snake.git
一:游戏演示

二:游戏思路框架介绍
大体分为以下个步骤
(1)开始界面:蛇的移动,以及SNAKE的移动与呈现。
(2)进入界面:菜单的绘制(难度选择)以及地图(也就是围墙)绘制。
(3)游戏界面:包括食物、蛇的动态出现、移动,以及围墙右侧的文字(分数、难度等的成像)的绘制。
三:游戏代码目录以及代码整个层次关系介绍
(1)项目文件目录:
目录分为:.cpp文件和.h文件,是为了方便文件之间的互相调用。
.h文件:主要是类的函数以及成员变量的声明。
.cpp文件:主要是相应类的函数的具体实现。

(2)项目层次关系图
这里说明,方框里直接采用类的名称表示相应关系。这幅图大概说了各个类之间的了个调用关系。

四:各个类的讲解
(1): tools类
a): tools.h
#ifndef TOOLS_H
#define TOOLS_H
void SetWindowSize(int cols, int lines);//设置游戏窗口的大小
void SetCursorPosition(const int x, const int y);//设置光标位置,用来输出文字或者空格(覆盖)
void SetColor(int colorID);//设置文本颜色
void SetBackColor();//设置文本背景颜色
#endif // TOOLS_H
b): tools.cpp
以下几个点需要注意下:
1)SetWindowSize()里的,system(cmd)是个固定用法,这是一个库函数,另外由于一个图形■占两个字符,故宽度乘以2。
2)SetCursorPosition()里的,COORD 是个结构体,含有两个成员变量x,y,刚好用来表示光标的位置。再调用
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), position);库函数,也就把光标移到position的位置
3)同理也是一个库函数,SetConsoleTextAttribute():设置文本颜色。
#include "tools.h"
#include <windows.h>
#include <stdio.h>
void SetWindowSize(int cols, int lines)//设置窗口大小
{
system("title 贪吃蛇");//设置窗口标题,黑款左上角会显示贪吃蛇,固定的“title+....."
char cmd[30];
sprintf(cmd, "mode con cols=%d lines=%d", cols * 2, lines);//一个图形■占两个字符,故宽度乘以2
system(cmd);//system(mode con cols=88 lines=88):设置窗口宽度和高度,固定的库函数以及写法
}
void SetCursorPosition(const int x, const int y)//设置光标位置,相当于是个接口,还要调用windows里 的函数,SetConsoleCursorPosition
{
//懂了
COORD position;//COORD:固定的结构体变量,有两个成员X,Y
position.X = x * 2 ;//一个图形■占两个字符,故宽度乘以2
position.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), position);
//可直接记住即可。
//GetStdHandle(STD_OUTPUT_HANDLE):标准输出程序的句柄
//SetConsoleCursorPosition:在写入输出之前将光标移动到所需位置,即(x,y)的位置m
}
void SetColor(int colorID)//设置文本颜色
{
//懂了
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colorID);
//GetStdHandle(STD_OUTPUT_HANDLE):固定输出句柄
//
}
void SetBackColor()//设置文本背景色
{
//懂了
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
FOREGROUND_BLUE |
BACKGROUND_BLUE |
BACKGROUND_GREEN |
BACKGROUND_RED );
}
(2): point类
a): point.h
#ifndef POINT_H
#define POINT_H
class Point
{
public:
Point(){};
Point(const int x,const int y) :x(x),y(y){};//构造函数
void Print();//打印地图需要用到的正方形方块
void PrintCircular();//打印蛇需要的圆形块
void Clear();//打印空格,用以覆盖蛇的尾部,就是蛇在移动过程中,其实是把尾部的图形用空格覆盖,在头部重新加入一个point的点进去,再绘制这条蛇
void ChangePosition(const int x,const int y);//改变坐标
bool operator == (const Point& point ){ return (point.x == this->x) &&(point.y == this->y) ;};//重载 == 运算符
int GetX(){return this->x;};//得到坐标
int GetY(){return this->y;};
private:
int x,y;
};
#endif // POINT_H
b): point.cpp
注意下:
1)Clear()函数是通过打印空格来覆盖掉原来的方块,
#include "point.h"
#include "tools.h"
#include <iostream>
void Point::Print()//输出方块
{
//懂了
SetCursorPosition(x,y);
std::cout<<"■" ;//Alt+41462,一个方块占2个字节,
}
void Point::PrintCircular()//输出图形
{
//懂啦,打印蛇
SetCursorPosition(x,y);
std::cout<<"●";//●
}
void Point::Clear()//清除输出
{
//懂了,
SetCursorPosition(x,y);//清除(x,y)这个点,不是真正清除,是通过覆盖,用空格来覆盖原来的点
std::cout<<" ";//此处是两个空格,因为都是占了2个字节的
}
void Point::ChangePosition(const int x,const int y)//改变坐标
{
//懂啦
this->x = x;
this->y = y;
}
(3): startinterface类:
a): startinterface.h
需要说明下:
1) speed是动画显示的速度
2)其次看两个双端队列,startsnake(存储开始动画中那个v字形一样的蛇),starttext(SNAKE的那个文字)
3)这里其实是把屏幕左上角当作坐标系的原点,横轴向右是X轴正方向,竖轴向下是y轴正方向。自己可以试着把这些点在纸上描绘以下,就能明白了,尤其是那个v字形的蛇。本人的草稿这在里给大家看看,字丑哈。

代码:
#ifndef STRATINTERFACE_H
#define STARTINTERFACE_H
#include <deque>
#include <vector>
#include "point.h"
class StartInterface
{
public:
StartInterface() : speed(500) {
startsnake.emplace_back(Point(0,14));//Éß,蛇刚开始的像v字形一样
startsnake.emplace_back(Point(1,14));
startsnake.emplace_back(Point(2,15));
startsnake.emplace_back(Point(3,16));
startsnake.emplace_back(Point(4,17));
startsnake.emplace_back(Point(5,18));
startsnake.emplace_back(Point(6,17));
startsnake.emplace_back(Point(7,16));
startsnake.emplace_back(Point(8,15));
startsnake.emplace_back(Point(9,14));
textsnake.emplace_back(Point(-26, 14));//S,刚开始SNAKE的点在X轴的负半轴
textsnake.emplace_back(Point(-25, 14));
textsnake.emplace_back(Point(-27, 15));
textsnake.emplace_back(Point(-26, 16));
textsnake.emplace_back(Point(-25, 17));
textsnake.emplace_back(Point(-27, 18));
textsnake.emplace_back(Point(-26, 18));
textsnake.emplace_back(Point(-23, 14));//N
textsnake.emplace_back(Point(-23, 15));
textsnake.emplace_back(Point(-23, 16));
textsnake.emplace_back(Point(-23, 17));
textsnake.emplace_back(Point(-23, 18));
textsnake.emplace_back(Point(-22, 15));
textsnake.emplace_back(Point(-21, 16));
textsnake.emplace_back(Point(-20, 17));
textsnake.emplace_back(Point(-19, 14));
textsnake.emplace_back(Point(-19, 15));
textsnake.emplace_back(Point(-19, 16));
textsnake.emplace_back(Point(-19, 17));
textsnake.emplace_back(Point(-19, 18));
textsnake.emplace_back(Point(-17, 18));//A
textsnake.emplace_back(Point(-16, 17));
textsnake.emplace_back(Point(-15, 16));
textsnake.emplace_back(Point(-14, 15));
textsnake.emplace_back(Point(-14, 16));
textsnake.emplace_back(Point(-13, 14));
textsnake.emplace_back(Point(-13, 16));
textsnake.emplace_back(Point(-12, 15));
textsnake.emplace_back(Point(-12, 16));
textsnake.emplace_back(Point(-11, 16));
textsnake.emplace_back(Point(-10, 17));
textsnake.emplace_back(Point(-9, 18));
textsnake.emplace_back(Point(-7, 14));//K
textsnake.emplace_back(Point(-7, 15));
textsnake.emplace_back(Point(-7, 16));
textsnake.emplace_back(Point(-7, 17));
textsnake.emplace_back(Point(-7, 18));
textsnake.emplace_back(Point(-6, 16));
textsnake.emplace_back(Point(-5, 15));
textsnake.emplace_back(Point(-5, 17));
textsnake.emplace_back(Point(-4, 14));
textsnake.emplace_back(Point(-4, 18));
textsnake.emplace_back(Point(-2, 14));//E
textsnake.emplace_back(Point(-2, 15));
textsnake.emplace_back(Point(-2, 16));
textsnake.emplace_back(Point(-2, 17));
textsnake.emplace_back(Point(-2, 18));
textsnake.emplace_back(Point(-1, 14));
textsnake.emplace_back(Point(-1, 16));
textsnake.emplace_back(Point(-1, 18));
textsnake.emplace_back(Point(0, 14));
textsnake.emplace_back(Point(0, 16));
textsnake.emplace_back(Point(0, 18));
}
void PrintFirst();//蛇(v字形)出现再界面上
void PrintSecond();//蛇从左移动到右,
void PrintThird();//蛇逐渐消失
void PrintText();//SNAKE文字的移动
void ClearText();//SNAKE文字的消失
void Action();
private:
std::deque<Point> startsnake;//开始动画中的蛇
std::vector<Point> textsnake;//开始动画中的文字
int speed;//动画的速度
};
#endif // STRATINTERFACE_H

本文详细解析了贪吃蛇游戏的实现过程,包括游戏界面、蛇的移动逻辑、食物生成与碰撞检测等核心内容,适合游戏开发初学者学习。
最低0.47元/天 解锁文章
842





