建设银行湖北省分行 网站/广州网站建设推广专家
演示视频
目录
一.概述
二.游戏开始前
修改控制台程序标题和大小
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_LBUTTON | 0x01 | 鼠标左键 |
VK_RBUTTON | 0x02 | 鼠标右键 |
VK_CANCEL | 0x03 | 控制中断处理 |
VK_MBUTTON | 0x04 | 鼠标中键 |
VK_XBUTTON1 | 0x05 | X1 鼠标按钮 |
VK_XBUTTON2 | 0x06 | X2 鼠标按钮 |
- | 0x07 | 保留 |
VK_BACK | 0x08 | BACKSPACE 键 |
VK_TAB | 0x09 | TAB 键 |
- | 0x0A-0B | 保留 |
VK_CLEAR | 0x0C | CLEAR 键 |
VK_RETURN | 0x0D | ENTER键 |
- | 0x0E-0楼 | 未分配 |
VK_SHIFT | 0x10 | 换档键 |
VK_CONTROL | 0x11 | CTRL 键 |
VK_MENU | 0x12 | Alt 键 |
VK_PAUSE | 0x13 | 暂停键 |
VK_CAPITAL | 0x14 | CAPS LOCK 键 |
VK_KANA | 0x15 | IME 假名模式 |
VK_HANGUL | 0x15 | IME 韩文模式 |
VK_IME_ON | 0x16 | IME 开启 |
VK_JUNJA | 0x17 | IME Junja 模式 |
VK_FINAL | 0x18 | IME 最终模式 |
VK_HANJA | 0x19 | IME 汉字模式 |
VK_KANJI | 0x19 | IME 汉字模式 |
VK_IME_OFF | 0x1A | IME 关闭 |
VK_ESCAPE | 0x1B | 电调键 |
VK_CONVERT | 0x1C | IME 转换 |
VK_NONCONVERT | 0x1D | IME 非转换 |
VK_ACCEPT | 0x1E | IME 接受 |
VK_MODECHANGE | 0x1F | IME 模式更改请求 |
VK_SPACE | 0x20 | 空格键 |
VK_PRIOR | 0x21 | PAGE UP 键 |
VK_NEXT | 0x22 | PAGE DOWN 键 |
VK_END | 0x23 | END 键 |
VK_HOME | 0x24 | HOME键 |
VK_LEFT | 0x25 | 向左箭头键 |
VK_UP | 0x26 | 向上箭头键 |
VK_RIGHT | 0x27 | 向右箭头键 |
VK_DOWN | 0x28 | 向下箭头键 |
VK_SELECT | 0x29 | SELECT 键 |
VK_PRINT | 0x2A | PRINT 密钥 |
VK_EXECUTE | 0x2B | EXECUTE 键 |
VK_SNAPSHOT | 0x2C | PRINT SCREEN 键 |
VK_INSERT | 0x2D | INS 密钥 |
VK_DELETE | 0x2E | DEL键 |
VK_HELP | 0x2F | HELP 键 |
0x30 | 0 键 | |
0x31 | 1 键 | |
0x32 | 2 键 | |
0x33 | 3键 | |
0x34 | 4键 | |
0x35 | 5键 | |
0x36 | 6键 | |
0x37 | 7键 | |
0x38 | 8键 | |
0x39 | 9键 | |
- | 0x3A-40 | 定义 |
0x41 | 一把钥匙 | |
0x42 | B键 | |
0x43 | C键 | |
0x44 | D键 | |
0x45 | E键 | |
0x46 | F键 | |
0x47 | G键 | |
0x48 | H键 | |
0x49 | I 键 | |
0x4A | J 键 | |
0x4B | K键 | |
0x4C | L键 | |
0x4D | M键 | |
0x4E | N键 | |
0x4F | O键 | |
0x50 | P键 | |
0x51 | Q键 | |
0x52 | R键 | |
0x53 | S 键 | |
0x54 | T键 | |
0x55 | U键 | |
0x56 | V键 | |
0x57 | W键 | |
0x58 | X键 | |
0x59 | Y 键 | |
0x5A | Z键 | |
VK_LWIN | 0x5B | 左 Windows 键 |
VK_RWIN | 0x5C | 右 Windows 键 |
VK_APPS | 0x5D | 应用程序密钥 |
- | 0x5E | 保留 |
VK_SLEEP | 0x5F | 计算机睡眠键 |
VK_NUMPAD0 | 0x60 | 数字键盘 0 键 |
VK_NUMPAD1 | 0x61 | 数字键盘 1 键 |
VK_NUMPAD2 | 0x62 | 数字键盘 2 键 |
VK_NUMPAD3 | 0x63 | 数字键盘 3 键 |
VK_NUMPAD4 | 0x64 | 数字键盘 4 键 |
VK_NUMPAD5 | 0x65 | 数字键盘 5 键 |
VK_NUMPAD6 | 0x66 | 数字键盘 6 键 |
VK_NUMPAD7 | 0x67 | 数字键盘 7 键 |
VK_NUMPAD8 | 0x68 | 数字键盘 8 键 |
VK_NUMPAD9 | 0x69 | 数字键盘 9 键 |
VK_MULTIPLY | 0x6A | 乘法键 |
VK_ADD | 0x6B | 添加密钥 |
VK_SEPARATOR | 0x6C | 分隔键 |
VK_SUBTRACT | 0x6D | 减去键 |
VK_DECIMAL | 0x6E | 十进制键 |
VK_DIVIDE | 0x6F | 分割键 |
VK_F1 | 0x70 | F1 键 |
VK_F2 | 0x71 | F2 键 |
VK_F3 | 0x72 | F3 键 |
VK_F4 | 0x73 | F4 键 |
VK_F5 | 0x74 | F5 键 |
VK_F6 | 0x75 | F6 键 |
VK_F7 | 0x76 | F7 键 |
VK_F8 | 0x77 | F8 键 |
VK_F9 | 0x78 | F9 键 |
VK_F10 | 0x79 | F10 键 |
VK_F11 | 0x7A | F11 键 |
VK_F12 | 0x7B | F12 键 |
VK_F13 | 0x7C | F13 键 |
VK_F14 | 2岳 | F14 键 |
VK_F15 | 0x7E | F15 键 |
VK_F16 | 0x7F | F16 键 |
VK_F17 | 0x80 | F17 键 |
VK_F18 | 0x81 | F18 键 |
VK_F19 | 0x82 | F19 键 |
VK_F20 | 0x83 | F20 键 |
VK_F21 | 0x84 | F21 键 |
VK_F22 | 0x85 | F22 键 |
VK_F23 | 0x86 | F23 键 |
VK_F24 | 0x87 | F24 键 |
- | 0x88-8楼 | 保留 |
VK_NUMLOCK | 0x90 | NUM LOCK 键 |
VK_SCROLL | 0x91 | SCROLL LOCK键 |
- | 0x92-96 | OEM 特定 |
- | 0x97-9楼 | 未分配 |
VK_LSHIFT | 0xA0 | 左 SHIFT 键 |
VK_RSHIFT | 0xA1 | 右 SHIFT 键 |
VK_LCONTROL | 0xA2 | 左 CONTROL 键 |
VK_RCONTROL | 0xA3 | 右 CONTROL 键 |
VK_LMENU | 0xA4 | 左 Alt 键 |
VK_RMENU | 0xA5 | 右 Alt 键 |
VK_BROWSER_BACK | 0xA6 | 浏览器后退键 |
VK_BROWSER_FORWARD | 0xA7 | 浏览器转发键 |
VK_BROWSER_REFRESH | 0xA8 | 浏览器刷新键 |
VK_BROWSER_STOP | 0xA9 | 浏览器停止键 |
VK_BROWSER_SEARCH | 0xAA | 浏览器搜索键 |
VK_BROWSER_FAVORITES | 0xAB | 浏览器收藏夹键 |
VK_BROWSER_HOME | 0xAC | 浏览器“开始”和“主页”键 |
VK_VOLUME_MUTE | 0xAD | 音量静音键 |
VK_VOLUME_DOWN | 0xAE | 降低音量键 |
VK_VOLUME_UP | 0xAF | 音量调高键 |
VK_MEDIA_NEXT_TRACK | 0xB0 | 下一曲目键 |
VK_MEDIA_PREV_TRACK | 0xB1 | 上一页 Track 键 |
VK_MEDIA_STOP | 0xB2 | 停止媒体键 |
VK_MEDIA_PLAY_PAUSE | 0xB3 | 播放/暂停媒体键 |
VK_LAUNCH_MAIL | 0xB4 | 启动邮件密钥 |
VK_LAUNCH_MEDIA_SELECT | 0xB5 | 选择媒体密钥 |
VK_LAUNCH_APP1 | 0xB6 | 启动应用程序 1 键 |
VK_LAUNCH_APP2 | 0xB7 | 启动应用程序 2 键 |
- | 0xB8-B9型 | 保留 |
VK_OEM_1 | 0xBA | 用于杂项字符;它可能因键盘而异。对于美标键盘,按键;: |
VK_OEM_PLUS | 0xBB | 对于任何国家/地区,关键+ |
VK_OEM_COMMA | 0xBC | 对于任何国家/地区,关键, |
VK_OEM_MINUS | 0xBD | 对于任何国家/地区,关键- |
VK_OEM_PERIOD | 0xBE | 对于任何国家/地区,关键. |
VK_OEM_2 | 0xBF | 用于杂项字符;它可能因键盘而异。对于美标键盘,按键/? |
VK_OEM_3 | 0xC0 | 用于杂项字符;它可能因键盘而异。对于美标键盘,按键`~ |
- | 0xC1-DA | 保留 |
VK_OEM_4 | 0xDB | 用于杂项字符;它可能因键盘而异。对于美标键盘,按键[{ |
VK_OEM_5 | 0xDC | 用于杂项字符;它可能因键盘而异。对于美标键盘,按键\\| |
VK_OEM_6 | 0xDD | 用于杂项字符;它可能因键盘而异。对于美标键盘,按键]} |
VK_OEM_7 | 0xDE | 用于杂项字符;它可能因键盘而异。对于美标键盘,按键'" |
VK_OEM_8 | 0xDF | 用于杂项字符;它可能因键盘而异。 |
- | 0xE0 | 保留 |
- | 0xE1 | OEM 特定 |
VK_OEM_102 | 0xE2 | 美国标准键盘上的键,或非美国 102 键键盘上的键<> \\| |
- | 0xE3-E4型 | OEM 特定 |
VK_PROCESSKEY | 0xE5 | IME PROCESS 密钥 |
- | 0xE6 | OEM 特定 |
VK_PACKET | 0xE7 | 用于传递 Unicode 字符,就好像它们是击键一样。键是用于非键盘输入法的 32 位虚拟键值的低位字。有关详细信息,请参阅 KEYBDINPUT、SendInput、WM_KEYDOWN 和 WM_KEYUP 中的备注VK_PACKET |
- | 0xE8 | 未分配 |
- | 0xE9-F5型 | OEM 特定 |
VK_ATTN | 0xF6 | 收件人键 |
VK_CRSEL | 0xF7 | CrSel 密钥 |
VK_EXSEL | 0xF8 | ExSel 密钥 |
VK_EREOF | 0xF9 | 擦除EOF密钥 |
VK_PLAY | 0xFA | 播放键 |
VK_ZOOM | 0xFB | 缩放键 |
VK_NONAME | 0xFC | 保留 |
VK_PA1 | 0xFD | PA1 密钥 |
VK_OEM_CLEAR | 0xFE | 清除键 |
对于左键,如果按了左键还要判断现在方向是不是朝右,然后才能把方向改为左边,因为朝右是绝对改变不了方向为左边的
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;
咬到自己机制
同样也是用蛇头去判断,我选取的是蛇头的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;
}//游戏结束阶段
相关文章:

c语言贪食蛇游戏
演示视频 目录 一.概述 二.游戏开始前 修改控制台程序标题和大小 Win32 API GetStdHandle函数 GetConsoleCursorInfo函数和SetConsoleCursorInfo函数 SetConsoleCursorPosition函数 游戏开篇界面处理 创建地图 蛇身节点以及食物节点初始化 蛇身的初始化 整体蛇节点…...

国际物流数字化运输方式选择指南 | 箱讯科技
国际物流涉及多种运输方式,每种方式都有其独特的优势和适用场景。选择合适的运输方式对于确保货物安全、及时到达目的地并控制成本至关重要。以下是对六种主要国际运输方式的简要介绍和选择建议: 国际快递:适用于小件、高价值或急需的货物。…...

FPS游戏框架漫谈第二十天
今天我们聊的话题是: 《吃鸡中武器护甲逻辑》 当我们接到一个需求就是给我们游戏中的特定的模式指定的武器支持加护甲的功能 那么这个流程是什么样的呢? 第一步一般这个新增护甲的配置属性肯定是加载武器的Config json文件里面的呢,并且是支持…...

ChatGPT高效提问—prompt常见用法(续篇四)
ChatGPT高效提问—prompt常见用法(续篇四) 1.1 知识生成 知识生成是指使用自然语言处理技术,通过ChatGPT等AI模型生成与特定主题相关的知识、文本或回答。在知识生成过程中,模型接收prompt输入的问题、指令或上下文信息&…...

【蓝桥杯单片机记录】IO基础与LED控制
目录 一、IO基础 1.1 IAP15F2K61S2芯片原理图 1.2不同工作模式 二、新建工程的一些补充 2.1 keil中没有IAP15F2K61S2的头文件 解决:在isp软件中找到如下编辑 2.2keil中的芯片选择 2.3推荐字体 三、sbit关键字 四、LED控制 4.1原理图 4.2不能直接通过IO…...

java 回答问题
1. How do you create a variable with the numeric value 5? int x 5; 2. The value of a string variable can be surrounded by single quotes. False 3. Which method can be used to return a string in upper case letters? toUpperCase()...

彻底学会系列:一、机器学习之线性回归(一)
1.基本概念(basic concept) 线性回归: 有监督学习的一种算法。主要关注多个因变量和一个目标变量之间的关系。 因变量: 影响目标变量的因素: X 1 , X 2 . . . X_1, X_2... X1,X2... ,连续值或离散值。 目标变量: …...

FPGA:我的零基础学习路线(2022秋招已上岸)持续更新中~
可内推简历,丝我即可 前言 初次接触FPGA是在2022年3月左右,正处在研二下学期,面临着暑假找工作,周围的同学大多选择了互联网,出于对互联网的裁员形势下,我选择了FPGA,对于硬件基础知识我几乎是…...

阿里云游戏服务器多少钱一个月?
阿里云游戏服务器租用价格表:4核16G服务器26元1个月、146元半年,游戏专业服务器8核32G配置90元一个月、271元3个月,阿里云服务器网aliyunfuwuqi.com分享阿里云游戏专用服务器详细配置和精准报价: 阿里云游戏服务器租用价格表 阿…...

Win32 SDK Gui编程系列之--ListView自绘OwnerDraw(续)
通过所有者绘制的列表视图(2) 所有者绘制列表视图的基础已在前一页中说明。本页将展示如何在所有者绘制列表视图中显示数据库表数据。 1、访问日志 正如在另一个页面中所述,本网站的访问日志目前是通过SQLite3数据库管理的。 以下是上述程序执行的结果。为…...

Android 应用添加系统签名权限的几种方式实现介绍
Android 应用添加系统签名权限的几种方式实现介绍 文章目录 Android 应用添加系统签名权限的几种方式实现介绍一、前言二、Android 应用添加系统签名权限的几种方式介绍1、在Android Studio添加系统签名文件2、源码编译apk添加系统签名Android.mkAndroid.bp 3、源码编译app代码…...

麒麟V10+飞腾处理器源码编译qt
1.下载qt源码 2.百度解压命令,进行解压 3.cd进文件目录 4.使用./configure命令进行配置(重点:记得看说明) Usage: configure [-h] [-prefix <dir>] [-prefix-install] [-bindir <dir>] [-libdir <dir>][-docdir <dir>] [-headerdir <dir&g…...

MacOS 查AirPods 电量技巧:可实现低电量提醒、自动弹窗
要怎么透过macOS 来查询AirPods 电量呢?当AirPods 和Mac 配对后,有的朋友想通过Mac来查询AirPods有多少电量,这个里有几个技巧,下面我们来介绍一下。 透过Mac 查AirPods 电量技巧 技巧1. 利用状态列上音量功能查询 如要使用此功能…...

python介绍,安装Cpython解释器,IDE工具pycharm的使用
python介绍 官方的Python解释器本质是基于C语言开发的一个软件,该软件的功能就是读取以py.结尾的文件内容,然后按照Guido定义好的语法和规则去翻译并执行相应的代码。这种C实现的解释器被称为Cpython。 python解释器的种类:Jython IPyth…...

服务器安装Docker (centOS)
1. 卸载旧版本的Docker(如果有) 首先,如果您的系统上安装了旧版本的Docker,需要将其卸载。Docker的旧版本称为docker或docker-engine。使用以下命令来卸载旧版本: sudo yum remove docker \ docker-client \ docker-…...

解析spritf和sscanf与模拟常用字符串函数strchr,strtok(二)
今天又来继续我们的字符串函数的文章,这也是最后一篇了。希望这两篇文章能让各位理解透字符串函数。 目录 strchr strtok sprintf和sscanf strchr strchr 是一个用于在字符串中查找特定字符首次出现位置的函数。以下是解析和模拟实现 strchr 函数的示例&…...

备战蓝桥杯---搜索(进阶4)
话不多说,直接看题: 下面是分析: (ab)%c(a%cb%c)%c; (a*b)%c(a%c*b%c)%c; 因此,如果两个长度不一样的值%m为相同值,那就舍弃长的(因为再加1位只不过是原来值*10那位值,因此他们得出的%m还是同…...

51单片机基础(C语言):定时器时钟
1.使用定时器 1 和LCD1602设计一个简易数字时钟。 main.c #include <REGX52.H> #include "Delay.h" #include "LCD1602.h" #include "Timer0.h"unsigned char Sec55,Min59,Hour23;void main() {LCD_Init();Timer0Init();LCD_ShowString(…...

单片机无线发射的原理剖析
目录 一、EV1527编码格式 二、OOK&ASK的简单了解 三、433MHZ 四、单片机的地址ID 五、基于STC15W104单片机实现无线通信 无线发射主要运用到了三个知识点:EV1527格式;OOk;433MHZ。下面我们来分别阐述: EV1527是数据的编…...

Redis的过期键的删除策略
我们都知道,Redis是key-value数据库,我们可以设置Redis中缓存的key的过期时间。Redis的过期策略就是指当Redis中缓存的key过期了,Redis如何处理。 过期策略通常有以下三种: 定时过期:每个设置过期时间的key都需要创建…...

放假--寒假自学版 day1(补2.5)
fread 函数: 今日练习 C语言面试题5道~ 1. static 有什么用途?(请至少说明两种) 1) 限制变量的作用域 2) 设置变量的存储域 2. 引用与指针有什么区别? 1) 引用必须被初始化,指针不必。 2) 引用初始…...

LLM(5) | Encoder 和 Decoder 架构
LLM(5) | Encoder 和 Decoder 架构 文章目录 LLM(5) | Encoder 和 Decoder 架构0. 目的1. 概要2. encoder 和 decoder 风格的 transformer (Encoder- And Decoder-Style Transformers)原始的 transformer (The original transformer)编码器 (Encoders)解码器 (Decoders)编码器和…...

CV | Medical-SAM-Adapter论文详解及项目实现
******************************* 👩⚕️ 医学影像相关直达👨⚕️******************************* CV | SAM在医学影像上的模型调研【20240207更新版】-CSDN博客 CV | Segment Anything论文详解及代码实现 本文主要讲解Medical-SAM-Adapter论文及项…...

C++初阶:容器(Containers)vector常用接口详解
介绍完了string类的相关内容后:C初阶:适合新手的手撕string类(模拟实现string类) 接下来进入新的篇章,容器vector介绍: 文章目录 1.vector的初步介绍2.vector的定义(constructor)3.v…...

flink写入es的参数解析
ElasticsearchSink内部使用BulkProcessor一次将一批动作(ActionRequest)发送到ES集群。在发送批量动作前,BulkProcessor先缓存,再刷新。缓存刷新的间隔,支持基于Action数量、基于Action大小、基于时间间隔3种策略。BulkProcessor支持在同一次…...

逆向工程:揭开科技神秘面纱的艺术
在当今这个科技飞速发展的时代,我们每天都在与各种电子产品、软件应用打交道。然而,你是否想过,这些看似复杂的高科技产品是如何被创造出来的?今天,我们就来探讨一下逆向工程这一神秘而又令人着迷的领域。 一、什么是…...

决策树的相关知识点
📕参考:ysu老师课件西瓜书 1.决策树的基本概念 【决策树】:决策树是一种描述对样本数据进行分类的树形结构模型,由节点和有向边组成。其中每个内部节点表示一个属性上的判断,每个分支代表一个判断结果的输出ÿ…...

【数据结构】单向链表实现 超详细
目录 一. 单链表的实现 1.准备工作及其注意事项 1.1 先创建三个文件 1.2 注意事项:帮助高效记忆和理解 2.链表的基本功能接口 2.0 创建一个 链表 2.1 链表的打印 3.链表的创建新节点接口 4.链表的节点插入功能接口 4.1 尾插接口 4.2 头插接口 4.3 指定位…...

Opencc4j 开源中文繁简体使用介绍
Opencc4j Opencc4j 支持中文繁简体转换,考虑到词组级别。 Features 特点 严格区分「一简对多繁」和「一简对多异」。 完全兼容异体字,可以实现动态替换。 严格审校一简对多繁词条,原则为「能分则不合」。 词库和函数库完全分离,…...

vue 下载二进制文件
文章目录 概要技术细节 概要 vue 下载后端返回的二进制文件流 技术细节 import axios from "axios"; const baseUrl process.env.VUE_APP_BASE_API; //downLoadPdf("/pdf/download?pdfName" res .pdf, res); export function downLoadPdf(str, fil…...