1.实现的基本功能
1.1贪吃蛇的地图绘制
1.2蛇吃食物的功能(上下左右方向键控制蛇的动作)
1.3蛇撞墙死亡
1.4蛇撞自身死亡
1.5计算得分
1.6蛇身加速减速
1.7暂停游戏
2
2.1坐标
在贪吃蛇移动过程中吃的食物可以认为是一个坐标,控制台屏幕上的坐标COORD,COORD是windows API中定义的一个结构体,表示一个字符在控制台屏幕缓冲区的一个坐标,坐标系(0,0)的原点位于缓冲区的顶部左侧单元格
2.2GetStdHandle
GetStdHandle是一个Windows API函数,它是从一个特定的标准设备(标准输入、标准输出、或标准错误)中取得一个句柄(用来标识不同设备的数值),使用这个句柄可以操作设备
2.3GetConsoleCursorInfo
检索有关指定控制台屏幕缓冲区的光标⼤⼩和可⻅性的信息
2.4CONSOLE_CURSOR_INFO
这个结构体,包含有关控制台光标的信息
typedef struct _CONSOLE_CURSOR_INFO {
DWORD dwSize;
BOOL bVisible;
} CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO;
• dwSize,由光标填充的字符单元格的百分⽐。 此值介于1到100之间。 光标外观会变化,范围从完 全填充单元格到单元底部的⽔平线条。
• bVisible,游标的可⻅性。 如果光标可⻅,则此成员为 TRUE
2.5SetConsoleCursorInfo
设置指定控制台屏幕缓冲区的光标的⼤⼩和可⻅性
例如
2.6SetConsoleCursorPosition
设置指定控制台屏幕缓冲区中的光标位置,我们将想要设置的坐标信息放在COORD类型的pos中,调 ⽤SetConsoleCursorPosition函数将光标位置设置到指定的位置。
2.7GetAsyncKeyState
将键盘上每个键的虚拟键值传递给函数,函数通过返回值来分辨按键的状态。 GetAsyncKeyState 的返回值是short类型,在上⼀次调⽤ GetAsyncKeyState 函数后,如果 返回的16位的short数据中,最⾼位是1,说明按键的状态是按下,如果最⾼是0,说明按键的状态是抬 起;如果最低位被置为1则说明,该按键被按过,否则为0。 如果我们要判断⼀个键是否被按过,可以检测GetAsyncKeyState返回值的最低值是否为1.
3
其中注意:我们打印墙体使用宽字符:□,打印蛇使⽤宽字符●,打印⻝物使用额宽字符# 普通的字符是占⼀个字节的,这类宽字符是占⽤2个字节,汉字本质上也是宽字符
来为了使C语⾔适应国际化,C语⾔的标准中不断加⼊了国际化的支持。比如:加⼊和宽字符的类型 wchar_t 和宽字符的输入和输出函数,加⼊和头文件,其中提供了允许程序员针对特定 地区(通常是国家或者说某种特定语⾔的地理区域)调整程序行为的函数
3.1
<locale.h>本地化 提供的函数⽤于控制C标准库中对于不同的地区会产⽣不⼀样⾏为的部分。
在标准可以中,依赖地区的部分有以下⼏项:
• 数字量的格式
• 货币量的格式
• 字符集
• ⽇期和时间的表⽰形式
3.2 setlocale函数
char* setlocale (int category, const char* locale);
setlocale 函数⽤于修改当前地区,可以针对⼀个类项修改,也可以针对所有类项。 setlocale 的第⼀个参数可以是前⾯说明的类项中的⼀个,那么每次只会影响⼀个类项,如果第⼀个参 数是LC_ALL,就会影响所有的类项。 C标准给第⼆个参数仅定义了2种可能取值:"c"和“”
在任意程序执⾏开始,都会隐藏式执⾏调⽤:
setlocale(LC_ALL, "C");
当地区设置为“c"时,库函数按正常⽅式执行,小数点是⼀个点。 当程序运⾏起来后想改变地区,就只能显⽰调⽤setlocale函数。用" "作为第2个参数,调⽤setlocale 函数就可以切换到本地模式,这种模式下程序会适应本地环境。比如:切换到我们的本地模式后就⽀ 持宽字符(汉字)的输出等
setlocale(LC_ALL, " ");
3.3宽字符的打印
宽字符的字面量必须加上前缀L,否则C语言会把字面量当作窄字符类型处理,前缀L在单引号前面,表示宽字符,宽字符的打印使用wprintf,对应的占位符为%lc,在双引号前面,表示宽3字符串,对应wprintf()的占位符为%ls;
4.游戏的实现
4.1数据结构的设计
在游戏运⾏的过程中,蛇每次吃⼀个⻝物,蛇的⾝体就会变长⼀节,如果我们使用链表存储蛇的信 息,那么蛇的每⼀节其实就是链表的每个节点。每个节点只要记录好蛇身节点在地图上的坐标就⾏, 所以蛇节点结构如下:
为了管理整条贪吃蛇,我们封装一个snake的结构来维护整条贪吃蛇
蛇的方向有上下左右,使用枚举一一列举
同理蛇的状态
4.2游戏流程设计
4.3游戏由开始 运行 结束三个环节组成
游戏开始
游戏开始要设置控制台的大小,隐藏光标,打印欢迎界面,打印地图,初始化蛇,创建第一个食物
设置控制台的大小
打印欢迎界面
创建地图
初始化蛇身
创建第一个食物
随机生成食物,通过rand函数随机生成食物
游戏运行
游戏运⾏期间,右侧打印帮助信息,提示玩家 根据游戏状态检查游戏是否继续,如果是状态是OK,游戏继续,否则游戏结束。 如果游戏继续,就是检测按键情况,确定蛇下⼀步的方向,或者是否加速减速,是否暂停或者退出游 戏。 确定了蛇的⽅向和速度,蛇就可以移动了。
检测按键状态,我们封装了一个宏
打印提示信息
蛇身移动
先创建下⼀个节点,根据移动⽅向和蛇头的坐标,蛇移动到下⼀个位置的坐标。 确定了下⼀个位置后,看下⼀个位置是否是⻝物(NextIsFood),是⻝物就做吃⻝物处理 (EatFood),如果不是⻝物则做前进⼀步的处理(NoFood)。 蛇⾝移动后,判断此次移动是否会造成撞墙(KillByWall)或者撞上自己去蛇身(KillBySelf),从而影 响游戏的状态。
如果下一个节点是食物
吃到食物,我们只需要打印当前这个食物的节点为蛇的身体,而后面的内容无需覆盖直接放着就行了
如果没吃到食物,与吃掉食物方法不同的是我们需要释放最后一个节点,并将倒数第二个节点的下一个节点的下一个指针置为空
判断蛇的坐标和墙的坐标是否冲突
如果冲突则撞墙
判断蛇的坐标是否和身体冲突
游戏结束
源码
test.c
snake.c
snake.h