【C语言项目】贪吃蛇(上)

news2024/11/18 7:52:09

在这里插入图片描述

个人主页 ~

gitee仓库~


欢迎大家来到C语言系列的最后一个篇章–贪吃蛇游戏的实现,当我们实现了贪吃蛇之后,我们的C语言就算是登堂入室了,基本会使用了,当然,想要更加熟练地使用还需要多多练习

贪吃蛇

  • 一、目标
  • 二、需要的知识
    • 1、Win32 API概念
    • 2、控制台程序
      • (1)mode命令
      • (2)COORD坐标
      • (3)隐藏光标的操作
        • ①GetStdHandle
        • ②GetConsoleCursorlnfo
        • ③CONSOLE_CURSOR_INFO
        • ④SetConsoleCursorInfo
        • ⑤SetConsoleCursorPosition
        • 封装一个函数命名为SetPos,专门用来设置光标位置
      • (4)GetAsyncKeyState
  • 三、游戏设计与分析
    • 1、地图
      • (1)本地化
      • (2)类项
      • (3)setlocale
      • (4)宽字符的打印
      • (5)地图坐标
    • 2、蛇身和食物
    • 3、数据结构设计
    • 4、设计游戏流程

一、目标

使用C语言在Windows环境的控制台中模拟实现贪吃蛇游戏
功能:
①贪吃蛇地图
②蛇的移动
③蛇吃食物
④蛇撞墙或者撞到自己死亡
⑤计算得分
⑥暂停游戏
⑦加速蛇身
⑧计算得分

二、需要的知识

函数、枚举、结构体、动态内存管理、预处理指令、链表、Win32 API
其中只有Win32 API我们在之前的博文中没有提到过,这里我们一起着重学习一下

1、Win32 API概念

Application Programming Interface(应用程序编程接口),简称API函数。
Windows是一个多作业系统,它除了协调应用程序的执行、分配内存、管理资源之外,也是一个很大的服务中心,调用这个服务中心的各种服务,其中每一种服务就是一个函数,可以帮应用程序达到开启视窗、描绘图形、使用周边设备等目的,这些函数服务的对象就是应用程序Application
Win32 API就是Windows32位平台的应用程序编程接口

2、控制台程序

在控制台能够执行的命令在编译器中也可以使用system函数来执行

(1)mode命令

mode con cols=100 lines=30;
#include <stdio.h>
int main()
{
    //设置控制台的大小为三十行一百列
    system("mode con cols=100 lines=30");
    //设置cmd窗⼝名称
    system("title 贪吃蛇"); 
    return 0;
}

(2)COORD坐标

COORD是Windows API中的一个结构体,表示一个字符在控制台屏幕上的坐标,左上角的坐标为(0,0)
在这里插入图片描述
COORD中有两个short值,一个为x,一个为y

typedef struct _COORD
{
    SHORT X;
    SHORT Y;
}COORD,*PCOORD;
COORD p = {10,20};//给坐标赋值

(3)隐藏光标的操作

在游戏的过程中,我们需要打印蛇身,墙壁,食物等,当我们在进行游戏时,是看不到光标闪烁的,但光标是存在的,所以我们要将它们隐藏

①GetStdHandle

GetStdHandle也是一个Windows API函数,它用于从一个特定的设备(标准输入、标准输出、标准错误)中获得一个句柄,使用这个句柄可以操作设备

HANDLE GetStdHandle(DWORD nStdHandle);
②GetConsoleCursorlnfo

检索有关指定控制台屏幕缓冲区的光标大小和可见性的信息

BOOL WINAPI GetConsoleCursorInfo
(
    HANDLE hConsoleoutput,
    PCONSOLE_CURSOR_INFO lpConsoleCursorInfo
);
//PCONSOLE_CURSOR_INFO是指向CONSOLE_CURSOR_INFO结构的指针

使用:

HANDLE houtput = NULL;
//获取标准输出的句柄(⽤来标识不同设备的数值)
houtput = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(houtput, &CursorInfo);//获取控制台光标信息
③CONSOLE_CURSOR_INFO

包含有关控制台光标的信息,是个结构体

typedef struct _CONSOLE_CURSOR_INFO 
{
    DWORD dwSize;//光标填充单元格的百分比,此值介于1-100,光标外观会发生变化
    BOOL bVisible;//游标的可见性,如果游标可见,其为TRUE,不可见为FALSE
} CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO;
④SetConsoleCursorInfo

设置指定控制台屏幕缓冲区的光标大小和可见性

BOOL WINAPI SetConsoleCursorInfo
(
    HANDLE hConsoleoutput,
    const CONSOLE_CURSOR_INFO *lpConsoleCursorInfo
);

使用:

HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
//影藏光标操作
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(houtput, &CursorInfo);//获取控制台光标信息
CursorInfo.bVisible = false; //隐藏控制台光标
SetConsoleCursorInfo(hOutput, &CursorInfo);//设置控制台光标状态
⑤SetConsoleCursorPosition

设置指定控制台屏幕缓冲区中的光标位置

BOOL WINAPI SetConsoleCursorPosition
(
    HANDLE hConsoleoutput,
    COORD pos
);

我们将想要设置的坐标信息放在pos当中,调用该函数将光标位置设置到指定的位置
使用:

COORD pos = {10, 5};
HANDLE houtput = NULL;
//获取标准输出的句柄(⽤来标识不同设备的数值)
houtput = GetStdHandle(STD_OUTPUT_HANDLE);
//设置标准输出上光标的位置为pos
SetConsoleCursorPosition(hOutput, pos);

封装一个函数命名为SetPos,专门用来设置光标位置
void SetPos(short x, short y)
{
    COORD pos = { x, y };
    HANDLE houtput = NULL;
    //获取标准输出的句柄(⽤来标识不同设备的数值)
    houtput = GetStdHandle(STD_OUTPUT_HANDLE);
    //设置标准输出上光标的位置为pos
    SetConsoleCursorPosition(houtput, pos);
}

(4)GetAsyncKeyState

原型:

SHORT GetAsyncKeyState
(
    int vKey
);

这个函数可以通过检测游戏进行时的按键来传递相应的返回值,可以实时监测此时按键的状态,调用后,如果该键按下返回的short值的最高位为1,否则为0,所以我们定义一个宏,来判断该键是否被按下

#define KEY_PRESS(VK) ( (GetAsyncKeyState(VK) & 0x1) ? 1 : 0 )

括号里是虚拟键代码,填入相应的虚拟键代码可以检测键是否被按下

三、游戏设计与分析

1、地图

在这里插入图片描述

在游戏中墙体、蛇体以及食物的打印用的是宽字符,占用两个字符,因为一个字符的话游戏会相当不美观,因为x轴的1和y轴的1的长度不同,y轴的1的长度约等于x轴的1的两倍

x=y=1时:
在这里插入图片描述

x=2,y=1时:
在这里插入图片描述
我们可以明显看出格子的区别
在宽字符打印之前我们要进行本地化

(1)本地化

包含头文件<local.h>

(2)类项

①LC_COLLATE:影响字符串比较函数strcoll和strxfrm
②LC_CTYPE:影响字符处理函数的行为
③LC_MONETARY:影响货币格式
④LC_NUMERIC:影响printf的数字格式
⑤LC_TIME:影响时间格式strftime和wcsftime
⑥LC_ALL:以上所有类别全部修改

(3)setlocale

char* setlocale (int category, const char* locale);

该函数用来修改当前地区
第一个
第二个参数仅定义了两种可能的取值:
“C”正常模式
“ ”本地模式
切换到本地模式就可以支持宽字符的打印

setlocale(LC_ALL, "C");//正常模式
setlocale(LC_ALL, " ");//本地模式

(4)宽字符的打印

可以把宽字符看做是长的字符

#include <stdio.h>
#include <locale.h>
int main()
{
setlocale(LC_ALL, "");
wchar_t c = L's';
wchar_t s = L"little_monster";
wprintf(L"%lc",c);
wprintf(L"%ls",s);
}

(5)地图坐标

这里我们实现的地图是27*58的,围绕边缘打印一周墙体

2、蛇身和食物

开始时,假设蛇长度为5,蛇身的每个节点用◆符号,在一个固定的连续5个坐标放蛇身
蛇的每个节点的x坐标都是2的倍数(宽字符),否则会出现一半节点在里边一半节点在墙里
食物节点的x坐标也是2的倍数,并且坐标不能与蛇身重合

3、数据结构设计

游戏运行过程中,蛇每吃掉一个食物蛇体就增加一个节点,每个节点就存储当前的坐标以及下一个节点的坐标

typedef struct SnakeNode
{
    int x;
    int y;
    struct SnakeNode* next;
}SnakeNode, * pSnakeNode;

现在我们有了节点的定义,我们再来用一个结构体维护整条贪吃蛇以及食物

typedef struct Snake
{
    pSnakeNode _pSnake;//维护整条蛇的指针
    pSnakeNode _pFood;//维护⻝物的指针
    enum DIRECTION _Dir;//蛇头的⽅向,默认是向右
    enum GAME_STATUS _Status;//游戏状态
    int _Socre;//游戏当前获得分数
    int _foodWeight;//默认每个⻝物10分
    int _SleepTime;//每⾛⼀步休眠时间
}Snake, * pSnake;

蛇的方向我们用枚举,因为蛇的行进方向只能有一个,使用枚举可以减小内存的占用

enum DIRECTION
{
 UP = 1,
 DOWN,
 LEFT,
 RIGHT
};

游戏状态我们也用枚举,理由同上,状态只能有一个

enum GAME_STATUS
{
 OK,//正常运⾏
 KILL_BY_WALL,//撞墙
 KILL_BY_SELF,//咬到⾃⼰
 END_NOMAL//正常结束
};

4、设计游戏流程

在这里插入图片描述
当我们把整个框架定好,下一步就可以来实现游戏了


下一篇再见~

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1657887.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java培训班还值得去培训吗?

请大家关注我的公众号&#xff1a;老胡聊Java 1 应届生或者在校生&#xff0c;如果感觉有必要&#xff0c;可以去提升下技术&#xff0c;因为应届生或在校生找工作时&#xff0c;未必要提升真实项目经验&#xff0c;所以用应届生身份学到的spring boot等java技术背面试题&#…

80端口被占用,解决办法

1.首先打开控制面板&#xff08;可以在左下角搜索&#xff09; 2. 点击程序 3.点击启用或关闭Windows功能 4. 关闭Internet Information Services 下图是关闭后的样子 5.点击确定&#xff0c;然后重启 这样就解决了80端口被占用的问题。

如何理解vlanif接口无法up的原因?直连不通(PVID问题)?如何排查?

目录 案列一&#xff1a;如何理解vlanif接口无法up的原因&#xff1f; 案例二&#xff1a;vlan接口正常up&#xff0c;同网段&#xff0c;无法ping通&#xff1f;&#xff08;PVID&#xff09; 原因一&#xff1a;pvid&#xff08;native vlan&#xff09;两端不一致——帧的…

操作系统——进程控制

创建进程 fork fork是一个系统调用函数&#xff0c;用来创建子进程&#xff0c;通过多个执行流完成任务。子进程和父进程共用一份代码&#xff0c;子进程数据使用写时拷贝&#xff0c;即子进程数据在创建的时候和父进程相同&#xff0c;但是当要修改数据的时候&#xff0c;子进…

软件项目管理期末复习题8-16章

第八章软件项目质量计划 一、填空题 1、&#xff08;审计&#xff09;是对过程或产品的一次独立质量评估。 2、质量成本包括预防成本和&#xff08;缺陷成本&#xff09;。 3、&#xff08;软件质量&#xff09;是软件满足明确说明或者隐含的需求的程度。 5、McCall质量模…

【C++】STL — vector的接口讲解 +详细模拟实现

前言: 本章我们将学习STL中另一个重要的类模板vector… vector是表示可变大小数组的序列容器。就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。但是又不像数组&#xff0c;它的大小是可以动态改变的本质讲&#xff0c;vector使用动态分配数组来存储它的元素v…

电脑缺失opencl.dll怎么办,轻松解决opencl.dll的多种方法分享

当我们在操作电脑过程中遇到系统提示“由于找不到opencl.dll&#xff0c;无法继续执行代码”&#xff0c;这个错误会导致软件应用无法正常运行。OpenCL.dll作为一个与Open Computing Language&#xff08;开放计算语言&#xff09;相关的动态链接库文件&#xff0c;它在执行需要…

基士得耶CP 6303c速印机不制版故障检修

故障&#xff1a;基士得耶CP 6303c经常提示版纸卡纸&#xff0c;重设版纸 版纸还没下滚筒&#xff0c;卡在版纸仓里面,手动滚动裁纸刀可以解决&#xff0c;但第二天又是这个毛病&#xff1b; 版纸定位传感器的灵敏度调节一下,然后给机器全面做个清洁大保养&#xff0c;尤其是传…

健康体检系统源码,体检中心、医院体检科管理系统,C/S架构,成熟稳定运行。支持预约管理、检查项目管理、结果录入、报告生成、数据分析

一套C/S架构的智慧健康体检管理系统源码&#xff0c;三级综合医院应用案例 体检系统是一种用于管理和记录个人或群体健康信息的软件系统。它通常包括预约管理、检查项目管理、结果录入、报告生成、数据分析等功能&#xff0c;旨在提高体检流程的效率和准确性&#xff0c;为医院…

高扬程水泵:专业设备,高效输送水源/恒峰智慧科技

在广袤无垠的森林中&#xff0c;每一棵树木都承载着生命的希望与自然的恩赐。然而&#xff0c;当森林遭遇火灾的威胁时&#xff0c;这些生机勃勃的生命便岌岌可危。此时&#xff0c;森林消防高扬程水泵便成为了守护森林安全的重要武器&#xff0c;以其专业性与高效性&#xff0…

第1章 信息系统综合知识 1.2 信息化

第1章 信息系统综合知识 1.2 信息化 1.2.1 信息的含义 信息化是推动经济社会发展转型的一个历史性过程。在这个过程中&#xff0c;综合利用各种信息技术&#xff0c;改造、支撑人类的各项 政治、经济、社会活动&#xff0c;并把贯穿于这些活动中的各种数据有效、可靠地进行管…

【2024版】最新6款漏洞扫描工具来了!(附下载)看完这一篇就够了

目录 一、Nessus 二、AWVS 三、ZAP 四、w3af 五、北极熊 六、御剑 七、网络安全学习路线 &#xff08;2024最新整理&#xff09; 八、学习资料的推荐 1.视频教程 2.SRC技术文档&PDF书籍 3.大厂面试题 特别声明&#xff1a; 渗透测试收集信息完成后&#xf…

修改表空间的状态

Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 表空间有4种状态:联机、脱机、只读和读写。修改其中某一种状态的语句如下所示 设置表空间 tspace 为联机状态。 SQL>ALTER TABLESPACE space ONLINE: 设置表空间 tspa…

房地产新楼盘营销短信群发

房地产新楼盘营销短信群发 1. 房地产市场竞争激烈&#xff0c;开发商为了能够快速推广新楼盘并吸引更多潜在买家的关注&#xff0c;采用房地产新楼盘营销群发已成为一种常见的营销手段。通过向大量的用户推广&#xff0c;开发商能够提高楼盘的知名度和曝光度&#xff0c;从而增…

(七)JSP教程——session对象

浏览器和Web服务器之间的交互通过HTTP协议来完成&#xff0c;HTTP协议是一种无状态的协议&#xff0c;服务器端无法保留浏览器每次与服务器的连接信息&#xff0c;无法判断每次连接的是否为同一客户端。为了让服务器端记住客户端的连接信息&#xff0c;可以使用session对象来记…

ARM(2)ARMv8基础知识

目录 一、异常 1.1异常等级的定义 1.2异常的种类 1.2.1同步异常和异步异常 1.3改变异常等级 1.4异常后的处理 1.4.1异常处理相关寄存器 1.4.2系统调用 1.4.3对EL2/EL3的系统调用 1.4.4异常返回 1.4.5异常处理流程 二、安全状态 三、执行状态 本文介绍以下内容&…

Oracle 修改数据库的字符集

Oracle 修改数据库的字符集 alter system enable restricted session; alter database "cata" character set ZHS16CGB231280; alter database "cata" national character set ZHS16CGB231280; alter system enable restricted session; alter database…

docker-compose安装 人大金仓数据库

下载官网安装包 将安装包重命名为: kingbase.tar 再导入镜像仓库 docker load -i kingbase.tar目录创建data文件夹创建docker-compose文件 version: 3 services: kingbase: image: kingbase:v1 container_name: kingbaseports: - "54321:54321" volumes: -…

AlphaFold3: Google DeepMind的的新突破

AlphaFold 3的论文今天在Nature期刊发表啦!这可是AI在生物领域最厉害的突破的最新版本。AlphaFold-3的新招就是用扩散模型去"画出"分子的结构。它一开始先从一团模模糊糊的原子云下手,然后慢慢透过去噪把分子变得越来越清楚。 Alphafold3 我们活在一个从Llama和Sora那…