谈到贪吃蛇游戏,我们都不陌生,贪吃蛇游戏最早是由瑞典程序员伊维·达赫尔(Yevgeny Dvorzhak)在1979年开发的,它在1980年开始流行。今天我将使用Win11 VS2022社区版带领大家一步一步实现贪吃蛇,希望这能多多少少对大家有些帮助。
一、贪吃蛇游戏的预期实现结果
我们可以参考下面这个视频:
贪吃蛇实现效果
二、贪吃蛇实现的大致思路及Snake.h
结合平时玩贪吃蛇的经验,我们可以按照如下思路来实现贪吃蛇代码:
其中游戏开始部分是创建初始环境,欢迎信息和地图、蛇、食物信息。
游戏进行部分是核心,处理蛇的移动。
游戏结束部分是完成游戏的善后。
我们按照上述思路先写一份头文件,把思路先理一理:
//"Snake.h"
#pragma once
# include<stdio.h>
# include<stdlib.h>//动态内存开辟、时间函数
# include<stdbool.h>//布尔类型
# include<time.h>//时间函数
# include<windows.h>//需要用到Win32的方法
# include<locale.h>//设置本地环境,方便打印宽字符'□'等
# define KEY_STATE(VK) ((GetAsyncKeyState(VK) & 0x1) ? 1 : 0)//定义按键宏,获取按键信息
# define WALL L'□'
# define BODY L'●'
# define FOOD L'★'
# define POS_X 24//定义初始x坐标
# define POS_Y 5//定义初始y坐标
//定义蛇节点
typedef struct SnakeNode
{
//坐标信息
int x;
int y;
struct SnakeNode* next;//方便链接下一个蛇节点
}SnakeNode, * pSnakeNode;
//定义方向状态
enum DIRECTION
{
UP,//向上
DOWN,//向下
LEFT,//向左
RIGHT//向右
};
//定义游戏状态
enum GAMESTATE
{
OK,//正常进行
BREAK_NORMAL,//正常退出
KILL_BY_WALL,//撞墙而死
KILL_BY_SELF//撞到自身而死
};
//定义整个蛇整体变量
typedef struct Snake
{
pSnakeNode _pSnake;//存放小蛇的头指针
pSnakeNode _pFood;//存放食物的地址
int _Count;//记录游戏总得分
int _FoodWeight;//记录当前食物的得分(由于蛇速度影响)
int _SleepTime;//存放蛇每走一个格子需要停顿的时间,停顿时间越短,蛇移动越快
enum DIRECTION _Dir;//存放蛇的运动方向
enum GAMESTATE _Game_State;//存放蛇的游戏状态
}Snake,*pSnake;
//设置坐标
void SetPos(int x, int y);
//隐藏光标
void ConsoleCursorHide();
//设置窗口大小以及标题
//游戏开始
void GameStart(pSnake ps);
//打印欢迎界面
void WelcomeToGame();
//打印地图
void CreateMap();
//初始化小蛇
void InitSnake(pSnake ps);
//创建食物
void CreateFood(pSnake ps);
//游戏运行
void GameRun(pSnake ps);
//打印提示信息
void PrintHelpInfo();
//暂停
void Pause();//空格为暂停
//蛇的移动
void MoveSnake(pSnake ps);//更新蛇头等
//判断下一个是不是食物
bool IsNextFood(pSnake ps, pSnakeNode pNext);//比较下一个位置和食物的位置
//吃掉食物
void EatFood(pSnake ps, pSnakeNode pNext);//覆盖、更新食物
//不吃食物
void NoFood(pSnake ps, pSnakeNode pNext);
//撞墙
void KillByWall(pSnake ps);
//自杀
void KillBySelf(pSnake ps);
//游戏结束
void GameEnd(pSnake ps);//销毁动态蛇节点内存
咱们为什么要定义比较复杂的结构体变量和枚举变量,这是为了减少因为使用太多的函数而增加实现难度,我们在下面就会感受到这样定义的好处。
三、基本知识
在打印欢迎页面之前,我们需要了解一个知识,就是我们使用VS2022运行的时候调用的命令提示框(黑框框)是有坐标的概念的,如图:
默认左上角的坐标是(0,0),而且x,y坐标的含义和数学的不太一样,具体如下:
在输出的时候,输出的英文字符占据1个x长度1个y长度,代表占据一个字节,而输出汉字占据两2个x单位1个y单位,代表占据两个字节。换算关系:2个x长度等于1个y长度。即随着数值的增大,坐标往y轴移动的速度是坐标往x轴移动的速度的2倍。
当谈到设置坐标以确保相关文字能在指定的位置输出,我们需要掌握一部分的Win32API知识,注意,这一部分涉及的函数仅仅在Windows操作系统下生效,在其他的如Linux、mac等不支持。
那么,WindowsAPI是干什么的呢?
# include<stdlib.h>
int main()
{
system("mode con cols=100 lines=30");
system("title 贪吃蛇");
return 0;
}
即可以将窗口设置成往x轴方向100个x单位,y轴方向30个y单位,标题变为“贪吃蛇”,如下图:
变化前:
变化后:
为了确保我们能够成功更改标题,我们需要做如下设置:
Win11:
打开cmd,点击这个小三角:
点击设置:
点击该处,选择“Windows控制台主机”
保存并关闭
就设置成功了。
Win10:
打开cmd,鼠标划到“命令提示符”页面上端白色部分,右键后,点击“属性”
点击终端->默认终端改为Windows控制台主机,点击确定,再关掉cmd,就设置好了。
为了实现能够更改光标位置,在特定位置打印文字,我们需要在include<