挑战!贪吃蛇小游戏的实现(1)

news2024/11/21 1:38:40

引言

相信大家都玩过贪吃蛇这个游戏!

玩家控制一个不断移动的蛇形角色,在一个封闭空间内移动。随着时间推进,这个蛇形角色会逐渐增长,通常是通过吞食屏幕上出现的物品(如点或者其他标志)来实现。每当贪吃蛇吃掉一个物品时,它就会变得更长一些。

目标是尽可能地让蛇增长而不撞击墙壁、障碍物或自己的身体部分。如果发生了这样的碰撞,则游戏结束。难度主要来源于两方面:一方面是由于贪吃蛇长度不断增加导致操作空间越来越小;另一方面则是速度可能会逐步提升,对玩家反应能力和策略规划提出了更高要求。

那么,我们能否使用C语言在Windows环境的控制台中模拟实现贪吃蛇小游戏呢~

答案是可以!

由于本次实现贪吃蛇会使用一些Win32 API的知识,所以我们先来学习一下Win32 API!

Win32 API

什么是Win32 API

Win32 API(Application Programming Interface)是微软Windows操作系统提供的一套核心接口,用于开发32位和64位的应用程序。这些API为程序员提供了访问Windows系统底层服务的方法,包括窗口管理、文件操作、设备输入输出、内存管理和进程线程控制等。

Win32 API可以分为几个不同的类别:

1. 用户界面(User Interface)API:负责创建和管理窗口、对话框以及其他图形用户界面元素。例如CreateWindow()函数就是用来创建一个窗口。

2. 图形设备接口(Graphics Device Interface, GDI)API:GDI APIs允许应用程序在屏幕上绘制图形,并处理字体和打印机输出。例如LineTo()函数可以画一条直线。

3. 系统服务API:提供对系统级功能如注册表操作、事件日志记录等的访问。例如RegOpenKeyEx()函数可以打开注册表键值。

4. 文件与I/O API:允许读写文件系统中的数据,以及与外部设备进行通信。例如ReadFile() 和 WriteFile() 函数可用于文件读写。

5. 进程与线程管理API:控制进程和线程生命周期,实现多任务并发执行能力。CreateProcess() 可以启动新进程,而CreateThread() 会创建一个新线程。

6. 网络服务API:支持网络通信功能,如TCP/IP连接、数据发送接收等。WSAStartup(), socket(), connect(), send(), recv() 是常见网络编程相关函数。

7. 安全性API:涉及到身份验证、权限检查等安全相关功能。
8. 多媒体API: 提供音频视频播放录制等多媒体处理能力。

1.控制台程序

我们可以使用cmd命令来设置控制台窗口的长度:比如设置控制台窗口大小为30行 100列

mode con cols=100 lines=30

也可以通过命令来设置控制台窗口的名字

title 贪吃蛇

这些能在控制台窗口执行的命令,也可以调用C语言函数system来执行

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

2.控制台屏幕上的坐标COORD

COORD是Windows API中定义的一个结构体,表示一个字符在控制台屏幕上的坐标

typedef struct _COORD{
  SHORT x;
  SHORT Y;
}COORD,*PCOORD;

给坐标赋值(使用时要包含头文件windows.h)

COORD pos = {10,15};

3.GetStdHandle

句柄:这是一个抽象的概念,用于表示对资源或对象的引用,它通常是一个整数值或者指针,通过这个值可以访问到底层系统资源,如文件,窗口和数据库连接等。

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

HANDLE GetStdHandle(DWORD nstdHandle);

下列代码用于获取标准输出的句柄

HANDLE houtput = NULL;
houtput = GetStdHandle(STD_OUTPUT_HANDLE);

4.GetConsoleCursorInfo

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

BOOL WINAPI GetConsoleCursorInfo(

  HANDLE  hConsoleOutput,

  PCONSOLE_CURSOR_INFO  lpConsoleCursorInfo//是指向CONSOLE_CURSOR_INFO结构的指针,该结构接收有关主机游标的信息

);

HANDLE houtput = NULL;
houtput = GetStdHandle(STD_OUTPUT_HANDLE);//获取标准输出的句柄

CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(houtput,&CursorInfo);//获取控制台光标信息


5.CONSOLE_CURSOR_INFO

该结构体包含了有关控制台光标的信息,光标大小和可见性数据

typedef struct _CONSOLE_CURSOR_INFO{
  DWORN dwSize;
  BOOL  bVisible;
}CONSOLE_CURSOR_INFO,*PCONSOLE_CURSOR_INFO;
  • dwSize 由光标填充的字符单元格的百分比。光标的外观会变化,从完全填充单元格到单元底部的水平线条。此值介于1-100之间。
  • bVisible 游标的可见性。如果光标可见,此值为TRUE。
CursorInfo.bVisible =false;//隐藏控制台光标

6.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);//设置控制台光标状态

7.SetConsoleCursorPosition

设置制定控制台屏幕缓冲区中的光标位置,我们将想要设置的坐标信息放在COORD类型的pos中,调用该函数将光标位置设定到指定位置

BOOL WINAPI SetConsoleCursorPosition(
  HANDLE  hconsoleoutput,
  COORD pos

);
COORD pos = {10,5};
HANDLE houtput = NULL;
houtput = GetStdHandle(STD_OUTPUT_HANDLE);//获取标准输出的句柄
SetConsoleCursorPosition(houtput,pos);//设置标准输出上光标位置为pos

由此,我们可以封装一个设置光标位置的函数SetPos

void SetPos(short x,short y)
{
  COORD pos ={x,y};
  HANDLE houtput = NULL;
  houtput = GetStdHandle(STD_OUTPUT_HANDLE);//获取标准输出的句柄
  SetConsoleCursorPosition(houtput,pos);//设置光标位置
}

8.GetAsyncKeyState

该函数用于获取按键情况,GetAsyncKeyState的函数原型如下

SHORT GetAsyncKeyState(

  int vKey;

);

将按键上的每个键的虚拟键值传递给函数,函数通过返回值来分辨按键状态。

GetAsyncKeyState的返回值为short类型,在上一次调用该函数后,如果返回的16位short数据中,最高位是1,说明按键的状态是按下,如果最高位是0,说明按键的状态是抬起;如果最低位被设置成1说明该按键被按过,否则为0

所以要判断一个按键是否被按过,我们可以检测该函数返回值的最低位是否为1

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

好啦!关于WIN32 API及相关函数的介绍就到这里啦,在下一篇博客中,我将详细实现贪吃蛇小游戏!防止迷路ovo请点赞收藏加关注哦~

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

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

相关文章

XML:可扩展标记语言

XML&#xff1a;可扩展标记语言 主要内容 XML介绍DTDXSDDOM解析SAX解析 学习目标 知识点要求XML介绍掌握DTD掌握XSD掌握DOM解析掌握SAX解析掌握 一、XML介绍 1. 简介 XML&#xff08;Extensible Markup Language&#xff09;可扩展标记语言。严格区分大小写。 2. XML和…

肿瘤微环境各种浸润细胞及maker(学习)

目录 Tumor Infiltrating Leukocytes&#xff08;肿瘤浸润性白细胞&#xff09; TISCH2数据库收录的TIL 免疫细胞的分类 28种不同免疫细胞类型 Tumor Infiltrating Leukocytes&#xff08;肿瘤浸润性白细胞&#xff09; Gene expression markers of Tumor Infiltrating Le…

关于Linux和消息队列常见的十道面试题

实际工作中如何排查CPU飙升问题&#xff1f; 在实际工作中&#xff0c;我们可以通过以下步骤来排查CPU飙升的问题&#xff1a; 使用系统监控工具&#xff1a;首先&#xff0c;我们可以使用系统监控工具&#xff0c;如top命令&#xff0c;来查看所有进程占系统CPU的排序。这样可…

vue element 组件 form深层 :prop 验证失效问题解决

此图源自官网 借鉴。 当我们简单单层验证的时候发现是没有问题的&#xff0c;但是有的时候可能会涉及到深层prop&#xff0c;发现在去绑定的时候就不生效了。例如我们在form单里面循环验证&#xff0c;在去循环数据验证。 就如下图的写法了 :prop"pumplist. i .device…

LeetCode、216. 组合总和 III【中等,组合型枚举】

文章目录 前言LeetCode、216. 组合总和 III【中等&#xff0c;组合型枚举】题目类型与分类思路 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注于Java后端技术领域。 涵盖…

一篇文章认识Vue3

Vue 3 介绍 Vue3 于 2022 年 2 月 7 日星期一成为新的默认版本&#xff01;Vue3 性能更高&#xff0c;体积更小Vue3 在经过一年的迭代后&#xff0c;越来越好用。 官方文档&#xff1a; vue3官方文档&#xff1a;vuejs.org/vue3中文文档&#xff1a;v3.cn.vuejs.org/vue3预发…

挂耳式耳机什么牌子的好?年度最值得入手的挂耳式耳机推荐

近年来耳机市场发展迅猛&#xff0c;蓝牙耳机品类日益增多。而挂耳式耳机尤其火爆&#xff0c;得益于其出色的佩戴体验&#xff0c;赢得了众多消费者的青睐。市场上挂耳式耳机的品牌种类繁多&#xff0c;让许多消费者在选择时感到困惑&#xff0c;挂耳机耳机什么牌子的好&#…

【React】redux状态管理、react-redux状态管理高级封装模块化

【React】react组件传参、redux状态管理 一、redux全局状态管理1、redux概述2、redux的组成1.1 State-状态1.2 Action-事件1.3 Reducer1.4 Store 3、redux入门案例1.1 前期准备1.2 构建store1.2.1 在src下新建store文件夹1.2.2 在store文件夹下新建index.ts文件1.2.3 在index.t…

用的到的linux-删除文件-Day3

前言&#xff1a; 上一节&#xff0c;我们讲到了怎么去移动文件&#xff0c;其中使用到两大类的脚本命令即cp和mv。各两种命令都可以完成移动&#xff0c;但是cp是复制粘贴的方式&#xff0c;可以选择原封不动的复制粘贴过来&#xff0c;即不修改文件及文件夹的创建时间等&…

SSH免密切换服务器案例-ssh协议(公钥和私钥)

公钥和私钥理解 公钥提供加密&#xff0c;私钥解密&#xff0c;公钥可以共享&#xff0c;私钥不可以。举例公钥相当于锁头&#xff0c;可以给别人用&#xff0c;钥匙相当于私钥&#xff0c;只能开自己发出去的锁头&#xff0c;也就是私钥和公钥成对&#xff0c;私钥只能解密对…

如何做报表? 如何建立指标体系

如何制作报表呢&#xff1f; 通过下面5步来制作报表。 如何建立指标体系? 很多数据分析招聘的要求里会写“构建指标体系”&#xff0c;所以建立指标体系是数据分析人员的一项基本技能。下面从4个问题出发&#xff0c;系统介绍指标体系&#xff1a; &#xff08;1&#xf…

编译器的实用调试技巧

目录 一. 什么是bug 二.调试的基本步骤 三.Debug和Release 四.常用快捷键 注意&#xff1a;如果你的快捷键被系统占用&#xff0c;那么可以尝试用&#xff1a;FN快捷键 F10和F11的区别 &#xff1a; F5和F9配合使用 五.如果要观察某个成员 六.断点的使用 F5和F9配合…

【Gephi项目实战-带数据集】利用gephi绘制微博肖战超话120位用户关系图,并计算整体网络指标与节点指标

数据集在评论区&#xff0c;B站演示视频在评论区&#xff01; 简介 最近2天需要用到gephi做社会网络分析&#xff0c;于是从0开始接触gephi并摸索出了gephi的基本使用指南。下面将结合真实的节点文件与边文件&#xff0c;利用gephi绘制社会网络并计算相关测量指标。整个过程会…

BC1.2 SDP/CDP/DCP介绍

参考&#xff1a;文章链接 Microchip Lightning Support 问题 Q1.) 在Microchip产品的数据表中提到了电池充电技术&#xff0c;但以下术语是什么意思: BC1.2? SDP? CDP? DCP? “SE1”? Q2.) 如何配置Microchip Hub以启用这些功能&#xff1f; Q3.) 如何在我的硬件上物…

Profinet转CANopen主站网关与堡盟编码器通讯案例

Profinet转CANopen主站网关(XD-COPNm20)为CPU与堡盟编码器的通讯提供了CANopen协议向Profinet协议转换互通的桥梁。CANopen是一种基于CAN总线的通讯协议&#xff0c;它被广泛应用于工业自动化领域&#xff0c;而Profinet是一种以太网协议&#xff0c;其优点是高速传输和广泛的可…

python-题库篇-数学

文章目录 求最大公约数和最小公倍数斐波那契数列求和运算求前n阶乘的和求年龄 求最大公约数和最小公倍数 两个数的最大公约数是两个数的公共因子中最大的那个数&#xff1b;两个数的最小公倍数 则是能够同时被两个数整除的最小的那个数。 输入&#xff1a;&#xff08;120 和…

Vue-easy-tree封装及使用

1.使用及安装 下载依赖 npm install wchbrad/vue-easy-tree引入俩种方案 1.在main.js中引入 import VueEasyTree from "wchbrad/vue-easy-tree"; import "wchbrad/vue-easy-tree/src/assets/index.scss" Vue.use(VueEasyTree)2.当前页面引入 import VueEa…

红队渗透靶机:LORD OF THE ROOT: 1.0.1

目录 信息收集 1、arp 2、nmap 3、knock 4、nikto 目录探测 1、gobuster 2、dirsearch WEB sqlmap 爆库 爆表 爆列 爆字段 hydra爆破 ssh登录 提权 信息收集 内核提权 信息收集 1、arp ┌──(root㉿ru)-[~/kali] └─# arp-scan -l Interface: eth0, ty…

Redis(三)主从架构、Redis哨兵架构、Redis集群方案对比、Redis高可用集群搭建、Redis高可用集群之水平扩展

转自 极客时间 Redis主从架构 redis主从架构搭建&#xff0c;配置从节点步骤&#xff1a; 1、复制一份redis.conf文件2、将相关配置修改为如下值&#xff1a; port 6380 pidfile /var/run/redis_6380.pid # 把pid进程号写入pidfile配置的文件 logfile "6380.log" …

使用代理IP有风险吗?如何安全使用代理IP?

代理IP用途无处不在。它们允许您隐藏真实IP地址&#xff0c;从而实现匿名性和隐私保护。这对于保护个人信息、绕过地理受限的内容或访问特定网站都至关重要。 然而&#xff0c;正如任何技术工具一样&#xff0c;代理IP地址也伴随着潜在的风险和威胁。不法分子可能会滥用代理IP…