C语言贪吃蛇(可在头文件中添加食物,选择撞墙是否会死)

2024-04-19 23:52

本文主要是介绍C语言贪吃蛇(可在头文件中添加食物,选择撞墙是否会死),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 项目目标

项目为控制台程序,在控制台上实现。

1. 实现游戏开始界面,让用户选择模式(撞墙/循环)等;

2. 实现地图的绘制;

3. 实现贪吃蛇,并使其根据用户的命令移动;

4. 实现食物的随机刷新,并为每一种食物设置分值;

5. 在游戏过程中打印适当的提示信息以及实时信息的刷新;

6. 实现贪吃蛇的变长;

7. 实时检测游戏状态(正常/撞墙/撞到自己);

2. 所需知识

C语言函数、枚举、结构体、动态内存管理、预处理指令、链表、Win32 API等。

这些知识,想必大家在学习C语言的过程中已经熟练到出神入化了,但是对于Win32 API可能会感到有点陌生。

接下来我们重点介绍一下Win32 API。

2.1 WIn32 API

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

Win32 API也就是Microsoft Windows 32位平台的应用程序编程接口。

利用Win32 API提供的函数,我们就可以比较方便地在控制台上进行信息的打印,地图的绘制等。

以下为这个项目需要用到的一些API函数。


2.1.1 GetStdHandle 函数 - Windows Console | Microsoft Learn

HANDLE GetStdHandle(DWORD nStdHandle);

GetStdHandle是⼀个Windows API函数。它用于从⼀个特定的标准设备(标准输入、标准输出或标准错误)中取得⼀个句柄(用来标识不同设备的数值,类型为HANDLE),使用这个句柄可以操作设备。

句柄其实就类似于FILE*指针:当你需要对某个文件进行操作时,你需要将对应的文件指针传入对应的函数;当你需要对某个设备进行操作时,你需要将对应的句柄传入对应的函数。

他的参数有以下三个:

含义
STD_INPUT_HANDLE标准输入设备
STD_OUTPUT_HANDLE标准输出设备
STD_ERROR_HANDLE标准错误设备

 

控制台的屏幕属于标准输出设备,所以在该项目中我们在使用这个函数时传入的都是STD_OUTPUT_HANDLE,然后定义一个HANDLE类型的变量来接收其返回的句柄即可。

例如:

HANDLE hOutput = NULL;
//获取标准输出的句柄(⽤来标识不同设备的数值)
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);

 2.1.2 GetConsoleCursorInfo 函数 - Windows Console | Microsoft Learn

BOOL WINAPI GetConsoleCursorInfo(HANDLE hConsoleOutput,PCONSOLE_CURSOR_INFO lpConsoleCursorInfo
);

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

它的第一个参数为标准输出设备的句柄,第二个参数为一个指向 CONSOLE_CURSOR_INFO(CONSOLE_CURSOR_INFO 结构 - Windows Console | Microsoft Learn) 结构的指针,该结构接收有关控制台游标的信息。

CONSOLE_CURSOR_INFO结构的定义如下

typedef struct _CONSOLE_CURSOR_INFO {DWORD dwSize;BOOL bVisible;
} CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO;

• dwSize:表示光标填充的字符单元格的百分比, 此值介于1到100之间。

                  光标外观会变化,范围从完全填充单元格到单元底部的水平线条。

• bVisible:表示光标的可见性。 如果光标可见,则此成员为 TRUE。

在使用时,我们需要先定义一个CONSOLE_CURSOR_INFO类型的变量,然后将其传入函数中。

此时,这个变量中就存储了当前光标的大小和可见性信息,我们可以通过访问这个结构体变量的成员来修改光标的参数。

例如:

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

但是,该变量只是获得了一个备份并将其储存,并没有直接与光标建立联系。

要使修改后的参数得到应用,我们还需要调用GetConsoleCursorInfo函数。


2.1.3 SetConsoleCursorInfo 函数 - Windows Console | Microsoft Learn

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

SetConsoleCursorInfo函数用于设置光标的参数,本质上就是让刚才获得的CONSOLE_CURSOR_INFO类型的变量存储的信息得到应用。

它的参数与GetConsoleCursorInfo函数一模一样,只需要在设置完光标参数之后,将变量再统统扔给它即可。

例如:

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

 2.1.4 SetConsoleCursorPosition 函数 - Windows Console | Microsoft Learn

BOOL WINAPI SetConsoleCursorPosition(HANDLE hConsoleOutput,COORD pos
);

SetConsoleCursorPosition函数用于设置指定控制台屏幕缓冲区中的光标位置,我们将想要设置的坐标信息放在COORD(COORD 结构 - Windows Console | Microsoft Learn)类型的pos中,调用SetConsoleCursorPosition函数将光标位置设置到指定的位置。

COORD结构体的定义如下:

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

COORD 是Windows API中定义的一个结构体,表示一个字符在控制台屏幕幕缓冲区上的坐标,坐标系 (0,0) 的原点位于缓冲区的顶部左侧单元格。

水平向右为x轴正方向,竖直向下为y轴正方向。

y轴的单位长度(一个中文字符的高度/宽度)是x轴单位长度的两倍。

例如: 

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

这段代码就是将光标的位置设置到(10,5)的位置。

由于在项目中,无论是绘制地图,打印蛇,打印食物还是在指定位置打印信息都需要设置光标位置,所以我们将设置光标位置的功能封装为了一个函数SetPos。

//设置光标的坐标
void SetPos(short x, short y)
{COORD pos = { x, y };HANDLE hOutput = NULL;//获取标准输出的句柄(⽤来标识不同设备的数值)hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//设置标准输出上光标的位置为posSetConsoleCursorPosition(hOutput, pos);
}

2.1.5 getAsyncKeyState 函数 (winuser.h) - Win32 apps | Microsoft Learn

SHORT GetAsyncKeyState(int vKey
);

GetAsyncKeyState函数用于获取按键的状态。

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

虚拟键码 (Winuser.h) - Win32 apps | Microsoft Learn 

GetAsyncKeyState 的返回值是short类型,在上一次调用 GetAsyncKeyState 函数后,如果返回的16位的short数据中:

• 最高位是1,说明按键的状态是按下,如果最高是0,说明按键的状态是抬 起。

• 如果最低位被置为1则说明,该按键被按过,否则为0。

如果我们要判断一个键是否被按过,可以检测GetAsyncKeyState返回值的最低值是否为1.

为了使用方便,我们定义了下面这个宏:

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

2.2 C语言的国际化特性

如果你需要用一些中文的宽字符来表示表示墙体,蛇,食物的话,就需要用到这个知识。

例如:打印墙体使用宽字符:□,打印蛇使用宽字符●,打印食物使用宽字符★

具体的细节,如果感兴趣的话可以自己去了解,在该项目中,你只需要知道setlocale函数即可。

setlocale - C++ Reference

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

要使程序能够打印这些宽字符,只需要下面这个语句即可:

setlocal(LC_ALL, "");

3. 项目实现

3.1 Snake.h

这里我没有使用宽字符来表示墙,蛇,和食物,而是直接使用的汉字,目的是为了方便读者分辨定义的符号是什么意思。

要增加食物数量或种类的话,将FOOD_MAX的值修改之后,在FOOD_SHAPES和FOOD_WEIGHTS中分别添加其符号和分值即可。

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <locale.h>
#include <time.h>
#include <stdbool.h>#define WALL L'墙'
#define BODY L'蛇'#define FOOD_MAX 3//食物种数#define FOOD_SHAPES {L'史', L'蕉', L'苹'}//食物外形列表
#define FOOD_WEIGHTS {1145, 10, 20}//食物分值列表#define ORIGIN_LEN 5
#define ORIGIN_X 24
#define ORIGIN_Y 5
#define KEY_PRESS(vk) ((GetAsyncKeyState(vk) & 0x1) ? 1 : 0)//类型定义
enum DIRECTIONS//方向
{UP,//上DOWN,//下LEFT,//左RIGHT//右
};enum STATUS//游戏状态
{NORMAL,//正常END_NORMAL,//正常退出END_WALL,//撞墙结束END_SELF//撞到自己结束
};//蛇身结点
typedef struct SnakeNode
{int x;int y;struct SnakeNode* next;
}SnakeNode, *pSnakeNode;//食物结点
typedef struct Food
{int x;int y;int weight;WCHAR shape;
}Food, *pFood;//贪吃蛇游戏
typedef struct Snake
{pSnakeNode pSnakeHead;//蛇头Food Recipe[FOOD_MAX];//食物清单enum DIRECTIONS Direction;//运动方向enum STATUS Status;//游戏状态int Score;//总分数int SleepTime;//睡眠时间int Attached;//附加分数
}Snake, *pSnake;//函数定义//设置光标位置
void SetPos(int x, int y);//游戏开始
int GameBegin(pSnake ps);
//欢迎界面
int WelComeToGame();
//创建地图26/58
void CreatMap();
//初始化贪吃蛇
void InitSnake(pSnake ps);
//初始化食物
void InitRecipe(pSnake ps);//游戏运行
void GameRun(pSnake ps, int flag);
//打印提示信息
void PrintHelpInfo();
//打印实时信息
void PrintTimelyInfo(pSnake ps);
//暂停
void Pause(pSnake ps);
//蛇行
void SnakeMove(pSnake ps, int flag);
//是否即将触碰食物
int IsTouchingFood(pSnakeNode pn, pSnake ps);
//没吃到食物
void NoFood(pSnake ps);
//改变某食物坐标
void FoodPosModify(pSnake ps, int pos);
//检测是否撞墙
void TouchingWall(pSnakeNode pn, pSnake ps, int flag);
//检测是否撞到自己
void TouchingSelf(pSnakeNode pn, pSnake ps);//游戏结束
void GameEnd(pSnake ps);

3.2 Snake.c

#define _CRT_SECURE_NO_WARNINGS
#include "Snake.h"
//设置光标位置
void SetPos(int x, int y)
{HANDLE HandOutPut = GetStdHandle(STD_OUTPUT_HANDLE);COORD pos = { x, y };SetConsoleCursorPosition(HandOutPut, pos);
}//欢迎界面
int WelComeToGame()
{SetPos(45, 14);wprintf(L"%ls", L"欢迎来到贪吃蛇小游戏");SetPos(45, 16);wprintf(L"%ls", L"1.撞墙模式(撞墙会死)");SetPos(45, 17);wprintf(L"%ls", L"2.循环模式(撞墙不会死)");int choice = 0;SetPos(43, 16);printf(">");do{if (KEY_PRESS(VK_UP))//撞墙模式{SetPos(43, 16);printf(">");SetPos(43, 17);printf(" ");choice = 0;}else if (KEY_PRESS(VK_DOWN))//循环模式{SetPos(43, 17);printf(">");SetPos(43, 16);printf(" ");choice = 1;}else if (KEY_PRESS(VK_RETURN)){break;}} while (1);SetPos(45, 25);system("pause");system("cls");SetPos(37, 14);wprintf(L"用上下左右来控制蛇的移动,按F3加速,按F4减速\n");SetPos(48, 15);wprintf(L"加速能获得更高的分数\n");SetPos(48, 17);system("pause");system("cls");return choice;
}//创建地图26/58
void CreatMap()
{int i = 0;//上for (i = 0; i < 29; i++){wprintf(L"%lc", WALL);}//下SetPos(0, 26);for (i = 0; i < 29; i++){wprintf(L"%lc", WALL);}//左右for (i = 1; i < 26; i++){SetPos(0, i);wprintf(L"%lc", WALL);SetPos(56, i);wprintf(L"%lc", WALL);}
}//初始化贪吃蛇
void InitSnake(pSnake ps)
{//初始化贪吃蛇属性ps->pSnakeHead = NULL;ps->Direction = RIGHT;ps->Score = 0;ps->Status = NORMAL;ps->SleepTime = 200;ps->Attached = 0;//创建蛇pSnakeNode cur = NULL;for (int i = 0; i < ORIGIN_LEN; i++){cur = (pSnakeNode)malloc(sizeof(SnakeNode));if (cur == NULL){perror("InitSnake::malloc");return;}cur->next = NULL;cur->x = ORIGIN_X + 2 * i;cur->y = ORIGIN_Y;//头插cur->next = ps->pSnakeHead;ps->pSnakeHead = cur;}//打印蛇cur = ps->pSnakeHead;while (cur){SetPos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}}//获取合法的食物坐标
void GetPos(pSnake ps, int* x, int* y)
{again:do{*x = rand() % 54 + 2;*y = rand() % 25 + 1;} while (*x % 2 != 0);pSnakeNode cur = ps->pSnakeHead;while (cur){if (cur->x == *x && cur->y == *y)goto again;cur = cur->next;}for (int i = 0; i < FOOD_MAX; i++){if (ps->Recipe[i].x == *x && ps->Recipe[i].y == *y)goto again;}
}//初始化食物
void InitRecipe(pSnake ps)
{int x = 0;int y = 0;WCHAR shapes[FOOD_MAX] = FOOD_SHAPES;int weights[FOOD_MAX] = FOOD_WEIGHTS;for (int i = 0; i < FOOD_MAX; i++){GetPos(ps, &x, &y);ps->Recipe[i].x = x;ps->Recipe[i].y = y;ps->Recipe[i].shape = shapes[i];ps->Recipe[i].weight = weights[i];SetPos(x, y);wprintf(L"%lc", ps->Recipe[i].shape);}
}//游戏开始
int GameBegin(pSnake ps)
{system("mode con cols=100 lines=30");system("title 贪吃蛇");//欢迎界面int flag = WelComeToGame();//创建地图27/58CreatMap();//初始化贪吃蛇InitSnake(ps);//初始化食物InitRecipe(ps);return flag;
}//打印提示信息
void PrintHelpInfo()
{SetPos(64, 16);wprintf(L"%ls", L"不能咬到自己");SetPos(64, 17);wprintf(L"%ls", L"用上下左右来控制蛇移动");SetPos(64, 18);wprintf(L"%ls", L"按F3加速,按F4减速");SetPos(64, 19);wprintf(L"%ls", L"按ESC退出游戏,按空格暂停游戏");
}//打印实时信息
void PrintTimelyInfo(pSnake ps)
{SetPos(64, 9);printf("总分数:%d\n", ps->Score);for (int i = 0; i < FOOD_MAX; i++){SetPos(64, 11 + i);wprintf(L"%lc", ps->Recipe[i].shape);printf("的分数为:%d", ps->Recipe[i].weight);}SetPos(64, 11 + FOOD_MAX);printf("附加分数为:%d", ps->Attached);
}//暂停
void Pause(pSnake ps)
{while (1){Sleep(200);if (KEY_PRESS(VK_SPACE)){break;}if (KEY_PRESS(VK_ESCAPE)){ps->Status = END_NORMAL;break;}}
}//是否即将触碰食物(是,则返回食物下标;否,则返回-1)
int IsTouchingFood(pSnakeNode pn, pSnake ps)
{for (int i = 0; i < FOOD_MAX; i++){if (pn->x == ps->Recipe[i].x && pn->y == ps->Recipe[i].y)return i;}return -1;
}//没吃到食物
void NoFood(pSnake ps)
{pSnakeNode cur = ps->pSnakeHead;while (cur->next->next){cur = cur->next;}SetPos(cur->next->x, cur->next->y);printf("  ");free(cur->next);cur->next = NULL;
}//改变某食物坐标
void FoodPosModify(pSnake ps, int pos)
{int x = 0;int y = 0;GetPos(ps, &x, &y);ps->Recipe[pos].x = x;ps->Recipe[pos].y = y;SetPos(x, y);wprintf(L"%lc", ps->Recipe[pos].shape);
}//检测是否撞墙
void TouchingWall(pSnakeNode pn, pSnake ps, int flag)
{if (flag == 1){if (pn->x == 0){pn->x = 54;}if (pn->x == 56){pn->x = 2;}if (pn->y == 26){pn->y = 1;}if (pn->y == 0){pn->y = 25;}}else{if (pn->x == 0 || pn->x == 56 || pn->y == 26 || pn->y == 0){ps->Status = END_WALL;}}
}//检测是否撞到自己
void TouchingSelf(pSnakeNode pn, pSnake ps)
{pSnakeNode cur = ps->pSnakeHead;while (cur){if (cur->x == pn->x && cur->y == pn->y){ps->Status = END_SELF;return;}cur = cur->next;}
}//蛇行
void SnakeMove(pSnake ps, int flag)
{pSnakeNode newhead = (pSnakeNode)malloc(sizeof(SnakeNode));if (newhead == NULL){perror("SnakeMove::malloc");return;}switch (ps->Direction){case UP:newhead->x = ps->pSnakeHead->x;newhead->y = ps->pSnakeHead->y - 1;break;case DOWN:newhead->x = ps->pSnakeHead->x;newhead->y = ps->pSnakeHead->y + 1;break;case LEFT:newhead->x = ps->pSnakeHead->x - 2;newhead->y = ps->pSnakeHead->y;break;case RIGHT:newhead->x = ps->pSnakeHead->x + 2;newhead->y = ps->pSnakeHead->y;break;}//检测是否撞墙TouchingWall(newhead, ps, flag);//检测是否撞到自己TouchingSelf(newhead, ps);newhead->next = ps->pSnakeHead;ps->pSnakeHead = newhead;SetPos(newhead->x, newhead->y);wprintf(L"%lc", BODY);//判断是否即将碰到食物int judge = IsTouchingFood(newhead, ps);if (judge == -1){//还没吃到食物,删掉最后一个结点NoFood(ps);}else{//修改某食物坐标FoodPosModify(ps, judge);ps->Score += ps->Recipe[judge].weight + ps->Attached;}}//游戏运行
void GameRun(pSnake ps, int flag)
{//打印提示信息PrintHelpInfo(ps);do{//打印实时信息PrintTimelyInfo(ps);//检测按键if (KEY_PRESS(VK_UP) && ps->Direction != DOWN){ps->Direction = UP;}else if (KEY_PRESS(VK_DOWN) && ps->Direction != UP){ps->Direction = DOWN;}else if (KEY_PRESS(VK_LEFT) && ps->Direction != RIGHT){ps->Direction = LEFT;}else if (KEY_PRESS(VK_RIGHT) && ps->Direction != LEFT){ps->Direction = RIGHT;}else if (KEY_PRESS(VK_SPACE)){//暂停Pause(ps);}else if (KEY_PRESS(VK_ESCAPE)){ps->Status = END_NORMAL;}else if (KEY_PRESS(VK_F3)){//加速if (ps->SleepTime > 80){ps->SleepTime -= 30;ps->Attached += 2;}}else if (KEY_PRESS(VK_F4)){//减速if (ps->SleepTime < 320){ps->SleepTime += 30;ps->Attached -= 2;}}SnakeMove(ps, flag);Sleep(ps->SleepTime);} while (ps->Status == NORMAL);
}
//游戏结束
void GameEnd(pSnake ps)
{SetPos(24, 12);switch (ps->Status){case END_NORMAL:printf("退出游戏!\n");break;case END_WALL:printf("撞墙啦牢底!\n");break;case END_SELF:printf("紫砂啦牢底!\n");break;}SetPos(24, 13);//释放蛇身链表pSnakeNode cur = ps->pSnakeHead;while (cur){pSnakeNode del = cur;cur = cur->next;free(del);}
}

3.3 test.c

#define _CRT_SECURE_NO_WARNINGS
#include "Snake.h"void SnakeGame()
{Snake snake = { 0 };//光标隐藏HANDLE HandOutPut = GetStdHandle(STD_OUTPUT_HANDLE);CONSOLE_CURSOR_INFO CursorInfo;GetConsoleCursorInfo(HandOutPut, &CursorInfo);CursorInfo.bVisible = false;SetConsoleCursorInfo(HandOutPut, &CursorInfo);int ch = 0;do{fflush(stdin);//游戏开始int flag = GameBegin(&snake);//游戏运行GameRun(&snake, flag);//游戏结束GameEnd(&snake);printf("要再来一次吗(Y/N):");ch = getchar();while (getchar() != '\n');KEY_PRESS(VK_RETURN);} while (ch == 'Y' || ch == 'y');SetPos(0, 28);
}int main()
{setlocale(LC_ALL, "");srand((unsigned int)time(NULL));SnakeGame();return 0;
}

这篇关于C语言贪吃蛇(可在头文件中添加食物,选择撞墙是否会死)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/918782

相关文章

python判断文件是否存在常用的几种方式

《python判断文件是否存在常用的几种方式》在Python中我们在读写文件之前,首先要做的事情就是判断文件是否存在,否则很容易发生错误的情况,:本文主要介绍python判断文件是否存在常用的几种... 目录1. 使用 os.path.exists()2. 使用 os.path.isfile()3. 使用

Go语言中泄漏缓冲区的问题解决

《Go语言中泄漏缓冲区的问题解决》缓冲区是一种常见的数据结构,常被用于在不同的并发单元之间传递数据,然而,若缓冲区使用不当,就可能引发泄漏缓冲区问题,本文就来介绍一下问题的解决,感兴趣的可以了解一下... 目录引言泄漏缓冲区的基本概念代码示例:泄漏缓冲区的产生项目场景:Web 服务器中的请求缓冲场景描述代码

Go语言如何判断两张图片的相似度

《Go语言如何判断两张图片的相似度》这篇文章主要为大家详细介绍了Go语言如何中实现判断两张图片的相似度的两种方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 在介绍技术细节前,我们先来看看图片对比在哪些场景下可以用得到:图片去重:自动删除重复图片,为存储空间"瘦身"。想象你是一个

Go语言中Recover机制的使用

《Go语言中Recover机制的使用》Go语言的recover机制通过defer函数捕获panic,实现异常恢复与程序稳定性,具有一定的参考价值,感兴趣的可以了解一下... 目录引言Recover 的基本概念基本代码示例简单的 Recover 示例嵌套函数中的 Recover项目场景中的应用Web 服务器中

Python如何判断字符串中是否包含特殊字符并替换

《Python如何判断字符串中是否包含特殊字符并替换》这篇文章主要为大家详细介绍了如何使用Python实现判断字符串中是否包含特殊字符并使用空字符串替换掉,文中的示例代码讲解详细,感兴趣的小伙伴可以了... 目录python判断字符串中是否包含特殊字符方法一:使用正则表达式方法二:手动检查特定字符Pytho

Go语言中使用JWT进行身份验证的几种方式

《Go语言中使用JWT进行身份验证的几种方式》本文主要介绍了Go语言中使用JWT进行身份验证的几种方式,包括dgrijalva/jwt-go、golang-jwt/jwt、lestrrat-go/jw... 目录简介1. github.com/dgrijalva/jwt-go安装:使用示例:解释:2. gi

Go 语言中的 Struct Tag 的用法详解

《Go语言中的StructTag的用法详解》在Go语言中,结构体字段标签(StructTag)是一种用于给字段添加元信息(metadata)的机制,常用于序列化(如JSON、XML)、ORM映... 目录一、结构体标签的基本语法二、json:"token"的具体含义三、常见的标签格式变体四、使用示例五、使用

Go语言使用slices包轻松实现排序功能

《Go语言使用slices包轻松实现排序功能》在Go语言开发中,对数据进行排序是常见的需求,Go1.18版本引入的slices包提供了简洁高效的排序解决方案,支持内置类型和用户自定义类型的排序操作,本... 目录一、内置类型排序:字符串与整数的应用1. 字符串切片排序2. 整数切片排序二、检查切片排序状态:

基于Go语言实现Base62编码的三种方式以及对比分析

《基于Go语言实现Base62编码的三种方式以及对比分析》Base62编码是一种在字符编码中使用62个字符的编码方式,在计算机科学中,,Go语言是一种静态类型、编译型语言,它由Google开发并开源,... 目录一、标准库现状与解决方案1. 标准库对比表2. 解决方案完整实现代码(含边界处理)二、关键实现细

如何合理管控Java语言的异常

《如何合理管控Java语言的异常》:本文主要介绍如何合理管控Java语言的异常问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、介绍2、Thorwable类3、Error4、Exception类4.1、检查异常4.2、运行时异常5、处理方式5.1. 捕获异常