c语言贪食蛇游戏

演示视频

目录

一.概述 

二.游戏开始前

修改控制台程序标题和大小

 Win32 API

 GetStdHandle函数

GetConsoleCursorInfo函数和SetConsoleCursorInfo函数

SetConsoleCursorPosition函数 

游戏开篇界面处理

创建地图

蛇身节点以及食物节点初始化

蛇身的初始化 

整体蛇节点初始化的代码

食物节点初始化

食物节点初始化完整代码 

三.游戏运行阶段 

游戏按键的设置

虚拟按键代码

snakemove移动函数

撞墙机制

咬到自己机制 

游戏运行阶段的全部代码如下,从下往上看

五.贪食蛇完整代码

测试.c文件代码

贪食蛇的声明.h文件

贪食蛇的实现.h代码


一.概述 

贪食蛇游戏设计,分为游戏开始前和游戏运行以及游戏结束三个阶段,我这个是利用win32 API直接在命令框设计的游戏,游戏运行阶段主要是解决游戏界面,提示信息等方面。游戏运行阶段会去解决初始化蛇身和食物,以及根据按键情况去移动蛇的方面。游戏结束阶段会告知游戏结束的原因和释放链表节点(蛇身以及食物都是通过链表来表示,其实也可以通过动态顺序表来做),游戏结束一般来说会是撞墙结束,咬到自己结束,以及正常退出三种情况。

二.游戏开始前

正常的控制台程序结束标题位置一般都是默认给出了,如果要修改标题要怎么修改呢,控制台程序命令框的大小能不能修改呢。同时光标一闪一闪很影响观感,也应该隐藏起来。

修改控制台程序标题和大小

对于windows命令框可以直接通过  title 新名称来修改命令框标题

 而命令框的大小可以通过mode con cols=要修改的大小 lines=有修改的大小,来进行修改大小,cols是行大小,lines是列大小

而对于编译器来说可不可以使用同样的语句来修改控制台程序界面的大小呢

 还没使用就已经报错了,如果你想使用和windows系统一样的语句进行修改,那么需要加上windows.h头文件,并且使用system才能使用系统语句

代码和运行结果如下,使用getchar()是使程序一直停留在运行阶段,方便测试,如果不这样的话运行结束会直接还原

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<windows.h>
void text()
{system("title 贪食蛇");system("mode con cols=100 lines=30");getchar();
}
int main()
{text();
}

 2.光标的隐藏以及改变输入位

 Win32 API

控制程序光标的各种操作是通过win32 API来进行操作的,Windows这个多作业系统除了协调应⽤程序的执行、分配内存、管理资源之外,它同时也是⼀个很大的服务中心,调⽤这个服务中心的各种服务(每⼀种服务就是⼀个函数),可以帮应用程序达到开启视窗、描绘图形、使用周边设备等目的,由于这些函数服务的对象是应⽤程序(Application),所以便称之为Application Programming Interface,简称API函数。WIN32 API也就是Microsoft Windows 32位平台的应⽤程序编程接⼝。

不过话说回来,如果你要画图又没怎么接触这些图形库,还是先用Easyx吧,这个更容易初学者上手一点,Win32要处理很多细节

Win32 API是windows系统提供的,所以直接使用windows.h头文件就可以使用了

 GetStdHandle函数

 GetStdHandle是用来获取句柄的函数,属于windows API函数,GetStdHandle是⼀个Windows API函数。它⽤于从⼀个特定的标准设备(标准输⼊、标准输出或标准错误)中取得⼀个句柄(⽤来标识不同设备的数值),使⽤这个句柄可以操作设备。句柄说直白点其实就是一个“授权的凭证”,你要通过这个“授权许可凭证”才能进行一系列操作,可以操纵鼠标的光标,还可以用来控制窗口的位置、大小和状态。

语法如下

HANDLE  GetStdHandle(DWORD nStdHandle
);

函数参数如下 

在Windows编程中,标准输入、标准输出和标准错误的句柄值分别为-10、-11和-12。这些特殊的负数值是为了与普通句柄值区分开来。通常情况下,普通句柄值是正整数,而这些特殊句柄值是为了表示标准输入输出而特意赋予的负数值。其实你不填参数值,它也默认是-10,-11,-12

比如获取标准输出的句柄可以表示为HANDLE WINAPI GetStdHandle( STD_OUTPUT_HANDLE)

HANDLE是一种数据类型,是专门接收句柄用的。

GetConsoleCursorInfo函数和SetConsoleCursorInfo函数

GetConsoleCursorInfo函数是用来查看检索光标大小和可见性信息的函数,SetConsoleCursorInfo是将修改后的结果设置回去的函数。

具体用法是首先获取句柄,然后通过GetConsoleCursorInfo函数来获取光标信息,再然后进行修改,然后通过SetConsoleCursorInfo把修改后的结果设置回去

HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);//获取句柄CONSOLE_CURSOR_INFO Info;GetConsoleCursorInfo(houtput, &Info);//获取光标控制台信息Info.bVisible = false;//隐藏控制台光标SetConsoleCursorInfo(houtput, &Info);//把修改后的结果设置回去

  CONSOLE_CURSOR_INFO这是个结构体,是专门用来存放光标信息的结构体,这个结构体成员是是光标可见性和光标大小

bVisible 是光标可见性,false是隐藏,true是正常显示。有些c编译器不支持布尔值 ,用0表示false,1表示true也可以实现操作

dwSize是光标大小,现在的光标大小一般默认是百分之25,介于1到100之间

SetConsoleCursorPosition函数 

这个函数是用来设置光标位置的,一般光标是默认放在左上角进行输出的,而想到屏幕中间输出文字可以通过这个函数来实现。

COORD是存放光标位置的结构体,成员是横坐标x,纵坐标y

COORD定义

用法如下

void setpos(int x, int y)
{COORD pos = { x,y };HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);SetConsoleCursorPosition(houtput, pos);
}

因为要用到很多次,所以单独设置一个函数

游戏开篇界面处理

然后就可以开始准备游戏界面的处理了

首先打印开篇界面

 此时开篇界面的代码

void setpos(int x, int y)
{COORD pos = { x,y };HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);SetConsoleCursorPosition(houtput, pos);
}

那么如何控制请按任意键继续呢,这些字不是直接打印出来的,windows提供了系统函数pause进行暂停,请按任意键继续是这个函数调用了自动产生的

void welcome()
{setpos(40, 10);printf("欢迎来到贪食蛇小游戏\n");setpos(43, 15);system("pause");getchar();
}

然后开始处理第二个界面 

但是在打印之前要先清理上一个界面的数据,通过windows自带的cls就可以清屏了

void welcomemap()
{setpos(40, 10);printf("欢迎来到贪食蛇游戏\n");setpos(41, 15);system("pause");system("cls");//清屏setpos(38, 10);printf("用 ↑ ↓ → ←键操作蛇\n");setpos(38, 13);printf("f3表示加速,f4表示减速,加速能得到更多的分数");setpos(38, 18);system("pause");system("cls");
}//欢迎界面

处理完就这个样子了

 

创建地图

地图的打印我采用的是宽字符“□”,单字符(一个字节的空间)通常是指一个字母、数字或标点符号,但是复杂的特殊符号方框五角星之类的用的是宽字符(两个字节的空间),c语言是美国人发明的,默认ASCII编码形式,所以要打印宽字符需要setlocale函数来进行本地化,具体用法如下

setlocale(LC_ALL, "");

 头文件是<locale.h>,LC_ALL是针对所有项进行修改,具体有
• 数字量的格式 LC_NUMERIC
• 货币量的格式    LC_MONETARY      • 字符集  LC_CTYPE
• ⽇期和时间的表⽰形式 LC_TIME      •所有格式LC_ALL

""双引号表示的是默认本地化,vs编译器双引号里面不加空格,否则会本地化失败,也不会报错,反正就一直打印不出来宽字符。也可以写的具体点setlocale(LC_ALL, "zh_CN");或者指定编码格式setlocale(LC_ALL, "zh_CN.UTF-8");
setlocale(LC_ALL, NULL);是不进行任何操作,仅仅用来查看当前locale设置成了什么

设置完之后就可以着手打印地图了,需要注意的是宽字符只是横坐标x占两个字节,但是纵坐标依旧是一个字节,大致如下

所以一个方格横坐标相当于纵坐标的两倍,如果我想把墙体设置为正方形的话,横坐标是0到54,坐标最后到了56除二为28个格子,而纵坐标是1到27共27个格子,因为横坐标已经打印了0,所以纵坐标从1开始,加上0坐标的各种也28个格子

#define wall L'□'

 

宽字符打印格式是wprintf,我已经提前 把要作为墙体的宽字符方框□要宏定义了,方便修改#define wall L'□'

因为宽字符是占两个字节,所以它每次打印的横坐标x都必须是2的倍数(0也是2的倍数),所以每次i都要+2而不是往常的i++,而第一个横着的墙体纵坐标y是不变的,一直是0,只需要改变x就行

接下来打印最左边竖着的墙,x轴是不变的,y轴每次都要变,所以只需要改变y值就行了,y轴还是一个字节每次加1就行,第0行横坐标的时候已经打印了,所以从1开始打印

然后是最下面横着的墙打印,y轴是一直保持27不变的,竖着的墙坐标到27就停止了,所以跟它连接的横着的墙y轴从27开始。x轴因为要和竖着的行衔接,所以第0行其实已经被打印过了,所以从2开始,每次增加2(宽字符x轴占两个字节)

再然后最右边竖着的墙 ,x轴不变,打印最上面墙的时候条件是i<56,这里没有等号,所以到不了56,而每次i都加2,所以最右边竖着的墙从54开始往下打印就行。也就是x一直保持54,而y轴变化

,由于第一行和最后一行都已经打印过了,所以条件为int i = 1; i < 27; i++

再然后打印右侧的提示信息,这个自己设置好光标直接打印就行,最右的墙最后坐标是56,所以x轴坐标设置要大于56

蛇身节点以及食物节点初始化

我采用的是单链表作为蛇身节点和食物节点用的,所以我采用了结构体snakenode首先对蛇身节点和食物节点都进行初始化,其次贪食蛇整体不只有蛇身节点这一个属性,还有方向 游戏状态,食物分数,总分等多个属性,所以又用另外一个结构体snakegame来表示游戏的各种属性

snakenode节点只有两个成员横坐标x,纵坐标y

 snakegame是维护整条贪食蛇的

因为游戏状态和方向比较多,所以用枚举方式一一表示了

蛇身的初始化 

蛇身的初始化采用的是不带头结点的单链表的头插法,在调用初始化函数snakeInit之前就已经把头结点置为空了,然后循环建立节点cur,如果蛇链表的头结点为空,那么就让第一个cur作为头结点

if (ps->psnake == NULL)
{cur->next = ps->psnake;//最后一个节点置空ps->psnake = cur;
}

因为头插法第一个插入的节点是链表的最后一个,是需要置空的,而ps->psnake之前初始化的时已经置为空了,所以cur->next=ps->psnake; 

如果头节点不为空,那么就将新建节点的next指向头结点,然后将ps->snake头节点指向新建立的节点,这样新建立的节点成了新的头节点

else
{cur->next = ps->psnake;ps->psnake = cur;
}

蛇身节点我是准备设置五个节点,因为每个宽字符占两个字节,所以i+=2,把cur的x坐标和y坐标设置,y的坐标设置为5不动,只改变x的坐标。cur的坐标设置完了之后用setpos函数在同样的坐标上打印身体宽字符图案

for循环的条件如下

for (int i = 0; i <10; i+=2)

cur坐标和打印身体如下

cur->x = 24 + i;
cur->y = 5;//设置cur的x和y坐标
setpos(cur->x, cur->y);//在cur坐标上打印蛇的身体
wprintf(L"%lc", BODY);

再然后顺便初始化一下贪食蛇的其他数据

ps->Dir = right;//方向
ps->foodweight = 10;//一个食物的分数
ps->score = 0;//总分
ps->sleeptime = 200;//休眠时间
ps->statues = ok;//游戏状态

整体蛇节点初始化的代码
void snakeInit(Snake* ps)
{for (int i = 0; i <10; i+=2){snakenode* cur = (snakenode*)malloc(sizeof(snakenode));if (ps->psnake == NULL){cur->next = ps->psnake;ps->psnake = cur;}else{cur->next = ps->psnake;ps->psnake = cur;}cur->x = 24 + i;cur->y = 5;//设置cur的x和y坐标setpos(cur->x, cur->y);//在cur坐标上打印蛇的身体wprintf(L"%lc", BODY);}ps->Dir = right;//方向ps->foodweight = 10;//一个食物的分数ps->score = 0;//总分ps->sleeptime = 200;//休眠时间ps->statues = ok;//游戏状态
}//蛇身节点初始化

食物节点初始化

食物的位置是随机出现的,食物节点的初始化要用到随机函数生成随机数,请注意这个随机是针对节点的成员x和y来说的。创建随机x和y轴时要注意不能生成的节点在蛇身体的五个节点上,然后要在墙里面不能在墙上或者墙外面。其次y没什么要求,在墙内就行,而x必须是2的倍数,因为节点都采用了宽字符打印,如果不是2的倍数,有可能生成的食物半边在墙内,另外半边在墙外

	int x; int y;
again:do {x = rand()%51 + 2;y = rand()%26 + 1;//控制节点坐标生成在墙内} while (x % 2 != 0);//宽字符x必须是2的倍数snakenode* cur = ps->psnake;while (cur){if (x == cur->x &&y == cur->y)//判断生成的坐标是否是蛇身节点goto again;//如果是蛇身节点那么就跳转回上面重新生成x,ycur = cur->next;}

对于rand函数,rand()%51是生成0到50之间的随机数,加2 就变成了生成2到52之间的随机数(包括52),因为如果坐标是0,那么就生成在竖着的墙上了,坐标是54就生成在最右边竖着的墙上了。所以范围是2到52。rand()%26 + 1也是同理

食物节点初始化完整代码 
void foodInit(Snake* ps)
{int x; int y;
again:do {x = rand()%51 + 2;y = rand()%26 + 1;//控制节点坐标生成在墙内} while (x % 2 != 0);//宽字符x必须是2的倍数snakenode* cur = ps->psnake;while (cur){if (x == cur->x &&y == cur->y)//判断生成的坐标是否是蛇身节点goto again;//如果是蛇身节点那么就跳转回上面重新生成x,ycur = cur->next;}ps->pfood = (snakenode*)malloc(sizeof(snakenode));//pfood是维护食物节点的指针ps->pfood->x = x; ps->pfood->y = y;setpos(ps->pfood->x, ps->pfood->y);wprintf(L"%lc", FOOD);
}

三.游戏运行阶段 

这个阶段回去处理游戏按键与节点怎么对应起来以及游戏是怎么运行的

游戏按键的设置

如何将按键与游戏操作结合起来呢,将键盘上每个键的虚拟键值传递给函数,函数通过返回值来分辨按键的状态。win32 API给了一个函数GetAsyncKeyState ,GetAsyncKeyState 的返回值是short类型,在上⼀次调⽤ GetAsyncKeyState 函数后,如果返回的16位的short数据中,最⾼位是1,说明按键的状态是按下,如果最⾼是0,说明按键的状态是抬起;如果最低位被置为1则说明,该按键被按过,否则为0。

贪食蛇游戏检查最低位是不是1就可以了,可以用GetAsyncKeyState的返回值按位&1就可以知道最低是1还是0了

GetAsyncKeyState函数有一个参数,即虚拟键码(Virtual Key Code),用于指定要检查状态按键。

贪食蛇游戏我们只需要用到上下左右,F3 F4 空格,esc退出就可以了

在代码开头写成宏方便操作#define KEY_PRESS(VK) ((GetAsyncKeyState(VK)&0x1) ? 1 : 0)

这个VK就是我们要检查的具体虚拟按键代码,比如要检查↑,那么就是 KEY_PRESS(VK_UP),具体虚拟按键表格如下

虚拟按键代码
虚拟按键描述
VK_LBUTTON0x01鼠标左键
VK_RBUTTON0x02鼠标右键
VK_CANCEL0x03控制中断处理
VK_MBUTTON0x04鼠标中键
VK_XBUTTON10x05X1 鼠标按钮
VK_XBUTTON20x06X2 鼠标按钮
-0x07保留
VK_BACK0x08BACKSPACE 键
VK_TAB0x09TAB 键
-0x0A-0B保留
VK_CLEAR0x0CCLEAR 键
VK_RETURN0x0DENTER键
-0x0E-0楼未分配
VK_SHIFT0x10换档键
VK_CONTROL0x11CTRL 键
VK_MENU0x12Alt 键
VK_PAUSE0x13暂停键
VK_CAPITAL0x14CAPS LOCK 键
VK_KANA0x15IME 假名模式
VK_HANGUL0x15IME 韩文模式
VK_IME_ON0x16IME 开启
VK_JUNJA0x17IME Junja 模式
VK_FINAL0x18IME 最终模式
VK_HANJA0x19IME 汉字模式
VK_KANJI0x19IME 汉字模式
VK_IME_OFF0x1AIME 关闭
VK_ESCAPE0x1B电调键
VK_CONVERT0x1CIME 转换
VK_NONCONVERT0x1DIME 非转换
VK_ACCEPT0x1EIME 接受
VK_MODECHANGE0x1FIME 模式更改请求
VK_SPACE0x20空格键
VK_PRIOR0x21PAGE UP 键
VK_NEXT0x22PAGE DOWN 键
VK_END0x23END 键
VK_HOME0x24HOME键
VK_LEFT0x25向左箭头键
VK_UP0x26向上箭头键
VK_RIGHT0x27向右箭头键
VK_DOWN0x28向下箭头键
VK_SELECT0x29SELECT 键
VK_PRINT0x2APRINT 密钥
VK_EXECUTE0x2BEXECUTE 键
VK_SNAPSHOT0x2CPRINT SCREEN 键
VK_INSERT0x2DINS 密钥
VK_DELETE0x2EDEL键
VK_HELP0x2FHELP 键
0x300 键
0x311 键
0x322 键
0x333键
0x344键
0x355键
0x366键
0x377键
0x388键
0x399键
-0x3A-40定义
0x41一把钥匙
0x42B键
0x43C键
0x44D键
0x45E键
0x46F键
0x47G键
0x48H键
0x49I 键
0x4AJ 键
0x4BK键
0x4CL键
0x4DM键
0x4EN键
0x4FO键
0x50P键
0x51Q键
0x52R键
0x53S 键
0x54T键
0x55U键
0x56V键
0x57W键
0x58X键
0x59Y 键
0x5AZ键
VK_LWIN0x5B左 Windows 键
VK_RWIN0x5C右 Windows 键
VK_APPS0x5D应用程序密钥
-0x5E保留
VK_SLEEP0x5F计算机睡眠键
VK_NUMPAD00x60数字键盘 0 键
VK_NUMPAD10x61数字键盘 1 键
VK_NUMPAD20x62数字键盘 2 键
VK_NUMPAD30x63数字键盘 3 键
VK_NUMPAD40x64数字键盘 4 键
VK_NUMPAD50x65数字键盘 5 键
VK_NUMPAD60x66数字键盘 6 键
VK_NUMPAD70x67数字键盘 7 键
VK_NUMPAD80x68数字键盘 8 键
VK_NUMPAD90x69数字键盘 9 键
VK_MULTIPLY0x6A乘法键
VK_ADD0x6B添加密钥
VK_SEPARATOR0x6C分隔键
VK_SUBTRACT0x6D减去键
VK_DECIMAL0x6E十进制键
VK_DIVIDE0x6F分割键
VK_F10x70F1 键
VK_F20x71F2 键
VK_F30x72F3 键
VK_F40x73F4 键
VK_F50x74F5 键
VK_F60x75F6 键
VK_F70x76F7 键
VK_F80x77F8 键
VK_F90x78F9 键
VK_F100x79F10 键
VK_F110x7AF11 键
VK_F120x7BF12 键
VK_F130x7CF13 键
VK_F142岳F14 键
VK_F150x7EF15 键
VK_F160x7FF16 键
VK_F170x80F17 键
VK_F180x81F18 键
VK_F190x82F19 键
VK_F200x83F20 键
VK_F210x84F21 键
VK_F220x85F22 键
VK_F230x86F23 键
VK_F240x87F24 键
-0x88-8楼保留
VK_NUMLOCK0x90NUM LOCK 键
VK_SCROLL0x91SCROLL LOCK键
-0x92-96OEM 特定
-0x97-9楼未分配
VK_LSHIFT0xA0左 SHIFT 键
VK_RSHIFT0xA1右 SHIFT 键
VK_LCONTROL0xA2左 CONTROL 键
VK_RCONTROL0xA3右 CONTROL 键
VK_LMENU0xA4左 Alt 键
VK_RMENU0xA5右 Alt 键
VK_BROWSER_BACK0xA6浏览器后退键
VK_BROWSER_FORWARD0xA7浏览器转发键
VK_BROWSER_REFRESH0xA8浏览器刷新键
VK_BROWSER_STOP0xA9浏览器停止键
VK_BROWSER_SEARCH0xAA浏览器搜索键
VK_BROWSER_FAVORITES0xAB浏览器收藏夹键
VK_BROWSER_HOME0xAC浏览器“开始”和“主页”键
VK_VOLUME_MUTE0xAD音量静音键
VK_VOLUME_DOWN0xAE降低音量键
VK_VOLUME_UP0xAF音量调高键
VK_MEDIA_NEXT_TRACK0xB0下一曲目键
VK_MEDIA_PREV_TRACK0xB1上一页 Track 键
VK_MEDIA_STOP0xB2停止媒体键
VK_MEDIA_PLAY_PAUSE0xB3播放/暂停媒体键
VK_LAUNCH_MAIL0xB4启动邮件密钥
VK_LAUNCH_MEDIA_SELECT0xB5选择媒体密钥
VK_LAUNCH_APP10xB6启动应用程序 1 键
VK_LAUNCH_APP20xB7启动应用程序 2 键
-0xB8-B9型保留
VK_OEM_10xBA用于杂项字符;它可能因键盘而异。对于美标键盘,按键;:
VK_OEM_PLUS0xBB对于任何国家/地区,关键+
VK_OEM_COMMA0xBC对于任何国家/地区,关键,
VK_OEM_MINUS0xBD对于任何国家/地区,关键-
VK_OEM_PERIOD0xBE对于任何国家/地区,关键.
VK_OEM_20xBF用于杂项字符;它可能因键盘而异。对于美标键盘,按键/?
VK_OEM_30xC0用于杂项字符;它可能因键盘而异。对于美标键盘,按键`~
-0xC1-DA保留
VK_OEM_40xDB用于杂项字符;它可能因键盘而异。对于美标键盘,按键[{
VK_OEM_50xDC用于杂项字符;它可能因键盘而异。对于美标键盘,按键\\|
VK_OEM_60xDD用于杂项字符;它可能因键盘而异。对于美标键盘,按键]}
VK_OEM_70xDE用于杂项字符;它可能因键盘而异。对于美标键盘,按键'"
VK_OEM_80xDF用于杂项字符;它可能因键盘而异。
-0xE0保留
-0xE1OEM 特定
VK_OEM_1020xE2美国标准键盘上的键,或非美国 102 键键盘上的键<>\\|
-0xE3-E4型OEM 特定
VK_PROCESSKEY0xE5IME PROCESS 密钥
-0xE6OEM 特定
VK_PACKET0xE7用于传递 Unicode 字符,就好像它们是击键一样。键是用于非键盘输入法的 32 位虚拟键值的低位字。有关详细信息,请参阅 KEYBDINPUT、SendInput、WM_KEYDOWN 和 WM_KEYUP 中的备注VK_PACKET
-0xE8未分配
-0xE9-F5型OEM 特定
VK_ATTN0xF6收件人键
VK_CRSEL0xF7CrSel 密钥
VK_EXSEL0xF8ExSel 密钥
VK_EREOF0xF9擦除EOF密钥
VK_PLAY0xFA播放键
VK_ZOOM0xFB缩放键
VK_NONAME0xFC保留
VK_PA10xFDPA1 密钥
VK_OEM_CLEAR0xFE清除键

 对于左键,如果按了左键还要判断现在方向是不是朝右,然后才能把方向改为左边,因为朝右是绝对改变不了方向为左边的

if (KEY_PRESS(VK_LEFT) && ps->Dir != right)ps->Dir = left;

 对于右键,如果按了右键还要判断现在方向是不是朝左,然后才能把方向改为右边,因为朝左是绝对改变不了方向为右边的

if (KEY_PRESS(VK_RIGHT) && ps->Dir != left)ps->Dir = right;

方向为上和下也是同理,不能产生冲突

if (KEY_PRESS(VK_UP) && ps->Dir != down)ps->Dir = up;
if (KEY_PRESS(VK_DOWN) && ps->Dir != up)ps->Dir = down; 

 具体方向键的移动另外做了一个函数snakemove(ps);

方向键设置完了,现在设置功能键 

我是打算把空格键设置为暂停,Sleep是修眠函数,可以设置一个死循环,如果按了空格键就进入循环休眠,再按一次空格键就break跳出循环停止休眠。这样就达到暂停的效果了

if (KEY_PRESS(VK_SPACE))
{while (1){Sleep(200);if (KEY_PRESS(VK_SPACE))break;}
}

然后是退出ESC键,只需要在按这个键的时候,把状态从ok改为end就行了

if (KEY_PRESS(VK_ESCAPE))ps->statues = end;
if (KEY_PRESS(VK_F4))
{if (ps->sleeptime < 350){ps->sleeptime += 20;ps->foodweight -= 2;if (ps->sleeptime >= 350){ps->foodweight = 1;}}
}

snakemove移动函数

上面解决了按键问题,现在来解决一下按键对应的移动。先新建一个nextnode节点,这是下一步产生的节点

对于按了左键来说(一般此时都是向上或者向下的状态按左键),nextnode的x坐标要蛇头节点x-2,因为每次都是蛇头移动,而纵坐标y是保持不变的。

if (ps->Dir == left)
{nextnode->x = ps->psnake->x - 2;nextnode->y = ps->psnake->y;
}

对于按了右键来说(一般此时也都是向上或者向下的状态按右键),而nextnode的x坐标是加2,y轴依旧是不变的

if (ps->Dir == right)
{nextnode->x = ps->psnake->x + 2;nextnode->y = ps->psnake->y;
}

对于按了上键来说(一般此时蛇方向是向左或者向右状态),此时nextnode的x轴是不变的,y轴-1就可以了

if (ps->Dir == up)
{nextnode->y = ps->psnake->y - 1;nextnode->x = ps->psnake->x;
}

对于按了下键来说(一般此时蛇方向是向左或者向右状态),此时nextnode的x轴是不变的,y轴+1就可以了

if (ps->Dir == down)
{nextnode->y = ps->psnake->y + 1;nextnode->x = ps->psnake->x;
}

解决了下一个节点的坐标问题,然后来考虑下一个节点正好是食物节点以及不是食物节点的情况。判断是否是食物节点很好判断,直接if (nextnode->x == ps->pfood->x && nextnode->y == ps->pfood->y)

对于下一个节点是食物,我另外做了一个函数eatfood();如果下一个节点是食物,那直接头插法插进蛇身链表就可以了,同时蛇头变为这个食物节点,然后以新的食物节点作为头结点打印蛇身。  完了之后,因为吃了食物,所以总分数score要加上食物的分数foodweight。最后删除原有的食物节点,重新初始化一个食物节点

void eatfood(Snake* ps, snakenode* nextnode)
{nextnode->next= ps->psnake;ps->psnake =nextnode;snakenode* cur = ps->psnake;//头插食物节点while (cur){setpos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;//打印蛇身}ps->score += ps->foodweight;//分数更新free(ps->pfood);//释放旧的食物节点foodInit(ps);//新建食物节点
}//吃食物

对于下一个位置不是食物节点,首先下一个位置也要成为新头节点,然后打印蛇身,但是最后一个节点要打印空格,这样看上去就像删除了最后一个节点一样。

void notfood(Snake*ps, snakenode*nextnode)
{nextnode->next = ps->psnake;ps->psnake = nextnode;snakenode* cur = ps->psnake;while (cur->next->next)//找到最后一个节点{setpos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}setpos(cur->next->x, cur->next->y);printf("  ");//这个空格是两个空格free(cur->next);cur->next = NULL;
}

撞墙机制

因为我之前已经枚举了游戏状态,有一个状态是killbywall,所以只有判断蛇头是不是和四面墙的坐标重叠,你也可以是刚碰到墙不是重叠就判断撞墙

void _killbywall(Snake* ps)
{if (ps->psnake->x== 0 || ps->psnake->x == 54 || ps->psnake->y == 0 || ps->psnake->y == 27)ps->statues = killbywall;
}//撞墙

咬到自己机制 

同样也是用蛇头去判断,我选取的是蛇头的next节点以及之后的节点,作为咬到的判断条件。然后把状态改成killbyself

void _killbyself(Snake* ps)
{snakenode* cur = ps->psnake->next;while (cur){if (ps->psnake->x == cur->x && ps->psnake->y == cur->y){ps->statues = killbyself;break;}cur = cur->next;}
}//咬到自己

整个游戏的运行阶段就结束了,因为F3和F4按键是运行阶段设置的,所以我把打印分数和食物分数放到了 gamerun(Snake* ps)函数里,同时要注意的是每次按键都要设置休眠时间,不然的话会卡顿。

游戏运行阶段的全部代码如下,从下往上看

//游戏运行阶段void _killbywall(Snake* ps)
{if (ps->psnake->x== 0 || ps->psnake->x == 54 || ps->psnake->y == 0 || ps->psnake->y == 27)ps->statues = killbywall;
}//撞墙void _killbyself(Snake* ps)
{snakenode* cur = ps->psnake->next;while (cur){if (ps->psnake->x == cur->x && ps->psnake->y == cur->y){ps->statues = killbyself;break;}cur = cur->next;}
}//咬到自己void eatfood(Snake* ps, snakenode* nextnode)
{nextnode->next= ps->psnake;ps->psnake =nextnode;snakenode* cur = ps->psnake;//头插食物节点while (cur){setpos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;//打印蛇身}ps->score += ps->foodweight;//分数更新free(ps->pfood);//释放旧的食物节点foodInit(ps);//新建食物节点
}//吃食物void notfood(Snake*ps, snakenode*nextnode)
{nextnode->next = ps->psnake;ps->psnake = nextnode;snakenode* cur = ps->psnake;while (cur->next->next)//找到最后一个节点{setpos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}setpos(cur->next->x, cur->next->y);printf("  ");//这个空格是两个空格free(cur->next);cur->next = NULL;
}
void snakemove(Snake* ps)
{snakenode* nextnode = (snakenode*)malloc(sizeof(snakenode));if (ps->Dir == left){nextnode->x = ps->psnake->x - 2;nextnode->y = ps->psnake->y;}if (ps->Dir == right){nextnode->x = ps->psnake->x + 2;nextnode->y = ps->psnake->y;}if (ps->Dir == up){nextnode->y = ps->psnake->y - 1;nextnode->x = ps->psnake->x;}if (ps->Dir == down){nextnode->y = ps->psnake->y + 1;nextnode->x = ps->psnake->x;}if (nextnode->x == ps->pfood->x && nextnode->y == ps->pfood->y)eatfood(ps, nextnode);else{notfood(ps, nextnode);}_killbywall(ps);_killbyself(ps);
}void gamerun(Snake* ps)
{do{setpos(61, 8);printf("总分:%3d", ps->score);setpos(70, 8);printf("食物的分数:%02d", ps->foodweight);if (KEY_PRESS(VK_LEFT) && ps->Dir != right)ps->Dir = left;if (KEY_PRESS(VK_RIGHT) && ps->Dir != left)ps->Dir = right;if (KEY_PRESS(VK_UP) && ps->Dir != down)ps->Dir = up;if (KEY_PRESS(VK_DOWN) && ps->Dir != up)ps->Dir = down;if (KEY_PRESS(VK_SPACE)){while (1){Sleep(200);if (KEY_PRESS(VK_SPACE))break;}}if (KEY_PRESS(VK_ESCAPE))ps->statues = end;if (KEY_PRESS(VK_F3)){if (ps->sleeptime >=50){ps->sleeptime -= 20;ps->foodweight += 2;}}if (KEY_PRESS(VK_F4)){if (ps->sleeptime < 350){ps->sleeptime += 20;ps->foodweight -= 2;if (ps->sleeptime >= 350){ps->foodweight = 1;}}}Sleep(ps->sleeptime);snakemove(ps);} while (ps->statues == ok);
}

四.游戏结束阶段

游戏结束阶段就是收尾阶段,把各种死亡原因打印一下,告知为什么死的,然后释放蛇身节点

void endgame(Snake* ps)
{if (ps->statues==end){setpos(20, 13);printf("您主动已经退出了游戏\n");}else if (ps->statues == killbyself){setpos(20, 13);printf("您咬到了自己\n");}else if (ps->statues == killbywall){setpos(20, 13);printf("您撞墙了\n");}while (ps->psnake){snakenode* cur = ps->psnake->next;free(ps->psnake);ps->psnake = cur;}ps = NULL;
}//游戏结束阶段

然后我还在main那里加了一个循环以便于重新开始游戏

#include"贪食蛇的声明.h"
void text()
{char ch = 0;do{setlocale(LC_ALL, "");gamestart();Snake ps = {0};//里面的成员先全赋值为0snakeInit(&ps);foodInit(&ps);gamerun(&ps);endgame(&ps);setpos(20, 15);printf("再来一局吗?(Y/N):");//Y是重新开始scanf("%c", &ch);getchar();// 清理\n
} while (ch == 'Y' || ch == 'y');
}
int main()
{srand((unsigned int)time(NULL));text();
}

五.贪食蛇完整代码

测试.c文件代码

#include"贪食蛇的声明.h"
void text()
{char ch = 0;do{setlocale(LC_ALL, "");gamestart();Snake ps = {0};//里面的成员先全赋值为0snakeInit(&ps);foodInit(&ps);gamerun(&ps);endgame(&ps);setpos(20, 15);printf("再来一局吗?(Y/N):");//Y是重新开始scanf("%c", &ch);getchar();// 清理\n
} while (ch == 'Y' || ch == 'y');
}
int main()
{srand((unsigned int)time(NULL));text();
}

贪食蛇的声明.h文件

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#define KEY_PRESS(VK) ((GetAsyncKeyState(VK)&0x1) ? 1 : 0)
#include<stdio.h>
#include<windows.h>
#include<stdbool.h>
#include<locale.h>
#include<time.h>
#define wall L'□'
#include<stdlib.h>
#define BODY L'■'
#define FOOD L'★'
void setpos(int x, int y);
void gamestart();enum statue
{ok = 1,end,killbywall,//撞墙killbyself//咬到自己
};enum direction
{up=1,down,left,right
};
typedef  struct snakenode
{int x;int y;struct snakenode* next;
}snakenode;//蛇身节点和食物节点typedef struct snakegame
{snakenode* psnake;//蛇身体节点snakenode *pfood;//食物节点int score;//总分int foodweight;//食物分数enum statue statues;//游戏状态enum direction Dir;//方向int sleeptime;//睡眠时间
}Snake;//维护蛇的结构体void snakeInit(Snake* ps);
void foodInit(Snake* ps);
void gamerun(Snake* ps);
void snakemove(Snake* ps);
void endgame(Snake* ps);

贪食蛇的实现.h代码

#include"贪食蛇的声明.h"
void setpos(int x, int y)
{COORD pos = { x,y };HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);SetConsoleCursorPosition(houtput, pos);}
void welcome()
{setpos(40, 10);printf("欢迎来到贪食蛇小游戏\n");setpos(43, 15);system("pause");system("cls");//清屏setpos(38, 10);printf("用 ↑ ↓ → ←键操作蛇\n");setpos(38, 13);printf("f3表示加速,f4表示减速,加速能得到更多的分数");setpos(38, 18);system("pause");system("cls");}
void createmap()
{for (int i = 0; i < 56; i += 2){setpos(i, 0);wprintf(L"%lc", wall);}//打印第一个横着的墙for (int i = 1; i < 28; i++){setpos(0, i);wprintf(L"%lc", wall);}//打印最左边竖着的墙for (int i = 2; i < 56; i += 2){setpos(i, 27);wprintf(L"%lc", wall);}//最下面横着的墙for (int i = 1; i < 27; i++){setpos(54, i);wprintf(L"%lc", wall);}setpos(61, 10);printf("用 ↑ ↓ → ←键操作蛇\n");setpos(61, 12);printf("f3表示加速,f4表示减速\n");setpos(61, 15);printf("加速能得到更多的分数\n");//打印墙体旁边的提示信息setpos(61, 17);printf("esc键退出游戏\n");setpos(61, 19);printf("空格键暂停\n");
}void gamestart()
{system("title 贪食蛇");system("mode con cols=100 lines=30");HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);CONSOLE_CURSOR_INFO Info;GetConsoleCursorInfo(houtput, &Info);//获取光标控制台信息Info.bVisible = 0;//隐藏光标SetConsoleCursorInfo(houtput, &Info);//把修改后的结果设置回去welcome();createmap();
}void snakeInit(Snake* ps)
{for (int i = 0; i <10; i+=2){snakenode* cur = (snakenode*)malloc(sizeof(snakenode));if (ps->psnake == NULL){cur->next = ps->psnake;ps->psnake = cur;}else{cur->next = ps->psnake;ps->psnake = cur;}cur->x = 24 + i;cur->y = 5;//设置cur的x和y坐标setpos(cur->x, cur->y);//在cur坐标上打印蛇的身体wprintf(L"%lc", BODY);}ps->Dir = right;//方向ps->foodweight = 10;//一个食物的分数ps->score = 0;//总分ps->sleeptime = 200;//休眠时间ps->statues = ok;//游戏状态
}//蛇身节点初始化void foodInit(Snake* ps)
{int x; int y;
again:do {x = rand()%51 + 2;y = rand()%26 + 1;//控制节点坐标生成在墙内} while (x % 2 != 0);//宽字符x必须是2的倍数snakenode* cur = ps->psnake;while (cur){if (x == cur->x &&y == cur->y)//判断生成的坐标是否是蛇身节点goto again;//如果是蛇身节点那么就跳转回上面重新生成x,ycur = cur->next;}ps->pfood = (snakenode*)malloc(sizeof(snakenode));//pfood是维护食物节点的指针ps->pfood->x = x; ps->pfood->y = y;setpos(ps->pfood->x, ps->pfood->y);wprintf(L"%lc", FOOD);
}//食物节点初始化//游戏运行阶段void _killbywall(Snake* ps)
{if (ps->psnake->x== 0 || ps->psnake->x == 54 || ps->psnake->y == 0 || ps->psnake->y == 27)ps->statues = killbywall;
}//撞墙void _killbyself(Snake* ps)
{snakenode* cur = ps->psnake->next;while (cur){if (ps->psnake->x == cur->x && ps->psnake->y == cur->y){ps->statues = killbyself;break;}cur = cur->next;}
}//咬到自己void eatfood(Snake* ps, snakenode* nextnode)
{nextnode->next= ps->psnake;ps->psnake =nextnode;snakenode* cur = ps->psnake;//头插食物节点while (cur){setpos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;//打印蛇身}ps->score += ps->foodweight;//分数更新free(ps->pfood);//释放旧的食物节点foodInit(ps);//新建食物节点
}//吃食物void notfood(Snake*ps, snakenode*nextnode)
{nextnode->next = ps->psnake;ps->psnake = nextnode;snakenode* cur = ps->psnake;while (cur->next->next)//找到最后一个节点{setpos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}setpos(cur->next->x, cur->next->y);printf("  ");//这个空格是两个空格free(cur->next);cur->next = NULL;
}
void snakemove(Snake* ps)
{snakenode* nextnode = (snakenode*)malloc(sizeof(snakenode));if (ps->Dir == left){nextnode->x = ps->psnake->x - 2;nextnode->y = ps->psnake->y;}if (ps->Dir == right){nextnode->x = ps->psnake->x + 2;nextnode->y = ps->psnake->y;}if (ps->Dir == up){nextnode->y = ps->psnake->y - 1;nextnode->x = ps->psnake->x;}if (ps->Dir == down){nextnode->y = ps->psnake->y + 1;nextnode->x = ps->psnake->x;}if (nextnode->x == ps->pfood->x && nextnode->y == ps->pfood->y)eatfood(ps, nextnode);else{notfood(ps, nextnode);}_killbywall(ps);_killbyself(ps);
}void gamerun(Snake* ps)
{do{setpos(61, 8);printf("总分:%3d", ps->score);setpos(70, 8);printf("食物的分数:%02d", ps->foodweight);if (KEY_PRESS(VK_LEFT) && ps->Dir != right)ps->Dir = left;if (KEY_PRESS(VK_RIGHT) && ps->Dir != left)ps->Dir = right;if (KEY_PRESS(VK_UP) && ps->Dir != down)ps->Dir = up;if (KEY_PRESS(VK_DOWN) && ps->Dir != up)ps->Dir = down;if (KEY_PRESS(VK_SPACE)){while (1){Sleep(200);if (KEY_PRESS(VK_SPACE))break;}}if (KEY_PRESS(VK_ESCAPE))ps->statues = end;if (KEY_PRESS(VK_F3)){if (ps->sleeptime >=50){ps->sleeptime -= 20;ps->foodweight += 2;}}if (KEY_PRESS(VK_F4)){if (ps->sleeptime < 350){ps->sleeptime += 20;ps->foodweight -= 2;if (ps->sleeptime >= 350){ps->foodweight = 1;}}}Sleep(ps->sleeptime);snakemove(ps);} while (ps->statues == ok);
}
void endgame(Snake* ps)
{if (ps->statues==end){setpos(20, 13);printf("您主动已经退出了游戏\n");}else if (ps->statues == killbyself){setpos(20, 13);printf("您咬到了自己\n");}else if (ps->statues == killbywall){setpos(20, 13);printf("您撞墙了\n");}while (ps->psnake){snakenode* cur = ps->psnake->next;free(ps->psnake);ps->psnake = cur;}ps = NULL;
}//游戏结束阶段

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

有趣的CSS - 多彩变化的按钮

目录 整体效果核心代码html 代码css 部分代码 完整代码如下html 页面css 样式页面渲染效果 整体效果 这个按钮效果主要使用 :hover 、:active 伪选择器以及 animation 、transition 属性来让背景色循环快速移动形成视觉效果。 核心代码部分&#xff0c;简要说明了写法思路&…

frp新版toml配置

从frp v0.52.0 版本开始&#xff0c;frp 将TOML作为配置文件格式。INI 格式已被弃用&#xff0c;并将在未来的发布中移除。因此&#xff0c;frp v0.52.0 及更高版本的配置文件默认为TOML格式。 项目地址 GitHub&#xff1a;https://github.com/fatedier/frp/releases 服务端…

Django前后端分离之后端实践2

小实践&#xff1a;实现用户登录、注销及ORM管理功能、事务开启小实践 models.py class Books(models.Model):id models.CharField(primary_keyTrue,max_length20,verbose_name"图书ID")name models.CharField(max_length20,verbose_name图书名称)status models…

jsp商场会员卡管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 商场会员卡管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.…

Docker下安装GitLab

极狐GitLab Docker 镜像 | 极狐GitLab 安装所需最小配置 内存至少4G 系统内核至少3.10以上 uname -r 命令可以查看系统内核版本 安装Docker 1.更新 yum源 yum update 2.安装依赖(如果在操作第三步的时候提示yum-config-manager 未找到命令 就安装下面依赖) yum instal…

1Panel面板如何安装并结合内网穿透实现远程访问本地管理界面

文章目录 前言1. Linux 安装1Panel2. 安装cpolar内网穿透3. 配置1Panel公网访问地址4. 公网远程访问1Panel管理界面5. 固定1Panel公网地址 前言 1Panel 是一个现代化、开源的 Linux 服务器运维管理面板。高效管理,通过 Web 端轻松管理 Linux 服务器&#xff0c;包括主机监控、…

【数据分享】1929-2023年全球站点的逐年降雪深度数据(Shp\Excel\免费获取)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、能见度等指标&#xff0c;说到气象数据&#xff0c;最详细的气象数据是具体到气象监测站点的数据&#xff01; 之前我们分享过1929-2023年全球气象站点的逐年平均气温数据、逐年最高气温数据…

Stable Diffusion 模型下载:Disney Pixar Cartoon Type B(迪士尼皮克斯动画片B类)

文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八案例九案例十 下载地址 模型介绍 这是我之前的模型迪士尼皮克斯卡通类型A与我自己训练的Lora在中途旅程图像上的合并结果。与之前的版本相比&#xff0c;男性和老年人看起来更像真正的皮克斯角色&a…

计算机设计大赛 深度学习+python+opencv实现动物识别 - 图像识别

文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络3.1卷积层3.2 池化层3.3 激活函数&#xff1a;3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 inception_v3网络5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; *…

算法学习——LeetCode力扣链表篇2

算法学习——LeetCode力扣链表篇2 24. 两两交换链表中的节点 24. 两两交换链表中的节点 - 力扣&#xff08;LeetCode&#xff09; 描述 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&…

飞天使-k8s知识点16-kubernetes实操1-pod

文章目录 深入Pod 创建Pod&#xff1a;配置文件详解写个pod的yaml 文件深入Pod 探针&#xff1a;探针技术详解 深入Pod 创建Pod&#xff1a;配置文件详解 资源清单参考链接&#xff1a;https://juejin.cn/post/6844904078909128712写个pod的yaml 文件 apiVersion: v1 kind: P…

jmeter二次开发函数-生成身份证号

代码参考这个 java 随机生成身份证代码 Java的身份证号码工具类 pom文件添加 <dependency><groupId>org.apache.jmeter</groupId><artifactId>ApacheJMeter_core</artifactId><version>5.4.1</version></dependency><d…

【iOS】——使用ZXingObjC库实现条形码识别并请求信息

文章目录 前言一、实现步骤二、扫描界面和扫描框的样式1.扫描界面2.扫描框 三、实现步骤 前言 ZXing库是一个专门用来解析多种二维码和条形码&#xff08;包括包括 QR Code、Aztec Code、UPC、EAN、Code 39、Code 128等&#xff09;的开源性质的处理库&#xff0c;而ZingObjC库…

Spring Web Body 转化常见错误

在 Spring 中&#xff0c;对于 Body 的处理很多是借助第三方编解码器来完成的。例如常见的 JSON 解析&#xff0c;Spring 都是借助于 Jackson、Gson 等常见工具来完成。所以在 Body 处理中&#xff0c;我们遇到的很多错误都是第三方工具使用中的一些问题。 真正对于 Spring 而…

如何部署Linux AMH服务器管理面板并结合内网穿透远程访问

文章目录 1. Linux 安装AMH 面板2. 本地访问AMH 面板3. Linux安装Cpolar4. 配置AMH面板公网地址5. 远程访问AMH面板6. 固定AMH面板公网地址 AMH 是一款基于 Linux 系统的服务器管理面板&#xff0c;它提供了一系列的功能&#xff0c;包括网站管理、FTP 管理、数据库管理、DNS 管…

如何利用边缘计算网关进行机床数据采集,以提高数据采集的效率和准确性-天拓四方

边缘计算网关集成了数据采集、处理和传输功能的嵌入式设备。它位于传感器和执行器组成的设备层与云计算平台之间&#xff0c;能够实时处理和响应本地设备的数据请求&#xff0c;减轻云平台的压力&#xff0c;提高数据处理的速度和效率。同时&#xff0c;边缘计算网关还可以将处…

为什么是0.1uF电容?

旁路电容是电子设计中常用的电容器之一&#xff0c;主要用于过滤电源噪声和稳定电源电压。在实际应用中&#xff0c;0.1uF电容器是最常用的旁路电容值之一&#xff0c;那么为什么常用旁路电容是0.1uF而不是其他值&#xff1f;这个值又是怎么来的呢&#xff1f;本文将深入探讨这…

linux centos 安装teleport

效果 安装 1.创建目录 mkdir -p /opt/teleport/data cd /opt/teleport/2.下载解压文件 wget https://tp4a.com/static/download/teleport-server-linux-x64-3.6.4-b3.tar.gz tar -xvf teleport-server-linux-x64-3.6.4-b3.tar.gz3.安装 cd /opt/teleport/teleport-server-l…

jsp粉丝社区系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 粉丝社区系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

闲聊电脑(6)装个 Windows(二)

闲聊电脑&#xff08;6&#xff09;装个 Windows&#xff08;二&#xff09; 夜深人静&#xff0c;万籁俱寂&#xff0c;老郭趴在电脑桌上打盹&#xff0c;桌子上的小黄鸭和桌子旁的冰箱又开始窃窃私语…… 小黄鸭&#xff1a;冰箱大哥&#xff0c;上次说的镜像文件到底长啥样…