【C语言】C语言经典小游戏:贪吃蛇(下)

article/2025/7/13 8:00:48

文章目录

  • 一、游戏前准备
  • 二、游戏开始
    • 1、游戏开始函数(GameStart)
      • 1)打印欢迎界⾯(WelcomeToGame)
      • 2)创建地图(CreateMap)
      • 3)初始化蛇⾝(InitSnake)
      • 4)创建⻝物(CreateFood)
  • 三、游戏运⾏
    • 1、准备工作
      • 1)帮助信息(PrintHelpInfo)
      • 2)判断按键状态(宏KEY_PRESS)
      • 3)暂停(Pause)
    • 2、游戏运行函数(GameRun)
      • 1)蛇移动(SnakeMove)
        • 1.a)下一个节点是否是食物(NextIsFood)
        • 1.b)是食物(EatFood)
        • 1.c)不是食物(NoFood)
        • 1.d)撞墙(KillByWall)
        • 1.e)撞到自身(KillBySelf)
  • 四、游戏结束
    • 1、游戏结束函数(GameEnd)

一、游戏前准备

我们首先需要创建三个文件:
Snake.h:结构体、枚举的定义,方法的声明。
Snake.c:方法的实现。
test.c:方法的测试。

首先先在Snake.h文件中定义贪吃蛇的结构体、枚举、以及包含的头文件和各种方法的声明:

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#include<stdbool.h>
#include<time.h>#define POS_X 24
#define POS_Y 5
#define WALL L'□'
#define BODY L'●'
#define FOOD L'★'//蛇的方向
enum DIRECTION
{UP = 1,//1DOWN,//2LEFT,//3RIGHT//4
};//蛇的状态
enum GAME_STATUS
{OK,//正常运行  0KILL_BY_WALL,//撞墙 1KILL_BY_SELF,//咬到自己 2END_NORMAL//正常结束 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 _food_weight;//一个食物的分数int _score;//总成绩int _sleep_time;//休息时间,时间越短,速度越快
}Snake, * pSnake;//定位光标的位置
void SetPos(short x, short y);//游戏的初始化
void GameStart(pSnake ps);//欢迎界面
void WelcomeToGame();//创建地图
void CreateMap();//初始化蛇身
void InitSnake(pSnake ps);	//游戏运行的逻辑
void GameRun(pSnake ps);//蛇的移动(走一步)
void SnakeMove(pSnake ps);//判断下一个坐标是否是食物
int NextIsFood(pSnakeNode pn,pSnake ps);//下一个位置是食物,就吃掉食物
void EatFood(pSnakeNode pn, pSnake ps);//下一个位置不是食物
void NoFood(pSnakeNode pn, pSnake ps);//检测蛇是否撞墙
void KillByWall(pSnake ps);//检测蛇是否撞到自己
void KillBySelf(pSnake ps);//游戏善后的工作
void GameEnd(pSnake ps);

接着我们再在Snake.c文件中编写定位光标位置的方法:

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

然后再进入test.c文件设置程序⽀持本地模式,并进⼊游戏的主逻辑。
主逻辑分为3个过程:

  • 游戏开始(GameStart):完成游戏的初始化。
  • 游戏运⾏(GameRun):完成游戏运⾏逻辑的实现。
  • 游戏结束(GameEnd):完成游戏结束的说明,实现资源释放。
#include<locale.h>
#include"Snake.h"void test()
{int ch = 0;do{system("cls");//创建贪吃蛇Snake snake = { 0 };//初始化游戏//1.打印环境界面和功能介绍//2.绘制地图//3.创建蛇//4.创建食物//5.设置游戏的相关信息GameStart(&snake);//运行游戏GameRun(&snake);//结束游戏GameEnd(&snake);SetPos(20, 15);printf("再来一局吗!(Y/N):");ch = getchar();while (getchar() != '\n');//清理\n} while (ch == 'Y' || ch == 'y');SetPos(0, 27);
}int main()
{//设置适配本地环境setlocale(LC_ALL, "");srand((unsigned int)time(NULL));test();return 0;
}

二、游戏开始

1、游戏开始函数(GameStart)

这个模块完成游戏的初始化任务:

  • 控制台窗⼝⼤⼩的设置。
  • 控制台窗⼝名字的设置。
  • ⿏标光标的隐藏。
  • 打印欢迎界⾯。
  • 创建地图。
  • 初始化蛇。
  • 创建第⼀个⻝物。

我们先在Snake.c文件中创建游戏开始的函数GameStart

void GameStart(pSnake ps)
{//设置窗口大小和名字system("mode con cols=100 lines=30");system("title 贪吃蛇");//获得输出句柄HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);//获得光标属性CONSOLE_CURSOR_INFO CursorInfo;	GetConsoleCursorInfo(houtput, &CursorInfo);//隐藏光标CursorInfo.bVisible = false;//设置光标属性SetConsoleCursorInfo(houtput, &CursorInfo);//打印欢迎界面WelcomeToGame();//绘制地图CreateMap();//创建蛇InitSnake(ps);//创建食物CreateFood(ps);
}

然后再在test.c中进行测试:

void test()
{Snake snake = { 0 };GameStart(&snake);	getchar();//暂停程序执行,等待用户输入
}int main()
{test();return 0;
}

运行结果:
在这里插入图片描述
可以看到此时窗口的大小和名字已经被成功设置,并且光标也被隐藏了。

接着就可以在GameStart函数中调用其他函数的方法。

1)打印欢迎界⾯(WelcomeToGame)

在游戏正式开始之前,做⼀些功能提醒。

欢迎界面函数:

void WelcomeToGame()
{SetPos(40, 14);wprintf(L"欢迎来到贪吃蛇小游戏\n");SetPos(42, 20);system("pause");//等待用户按任意键system("cls"); //清屏SetPos(25, 14);wprintf(L"用↑.↓.←.→来控制蛇的移动,按F3加速,F4减速\n");SetPos(25, 15);wprintf(L"加速能够得到更高的分数\n");SetPos(42, 20);system("pause");system("cls");
}

再进行测试:

void test()
{Snake snake = { 0 };GameStart(&snake);	getchar();
}int main()
{//设置为本地环境setlocale(LC_ALL,"");test();return 0;
}

运行结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2)创建地图(CreateMap)

创建地图就是将墙打印出来,因为是宽字符打印,所以使⽤wprintf函数,打印格式串前使⽤L。打印地图的关键是要算好坐标,才能在想要的位置打印墙体。

墙体打印的宽字符先在Snake.h文件中进行宏定义。

#define WALL L'□' 

易错点: 就是坐标的计算
上:(0,0)到(56,0)
下:(0,26)到(56,26)
左:(0,1)到(0,25)
右:(56,1)到(56,25)

创建地图函数:

void CreateMap()
{//上for (int i = 0; i < 29; i++){wprintf(L"%lc", WALL);//一个宽字符占2格横坐标}//下SetPos(0, 26);for (int i = 0; i < 29; i++){wprintf(L"%lc", WALL);}//左for (int i = 1; i <= 25; i++){SetPos(0, i);wprintf(L"%lc", WALL);}//右for (int i = 1; i <= 25; i++){SetPos(56, i);wprintf(L"%lc", WALL);}
}

再进行测试:

void test()
{Snake snake = { 0 };GameStart(&snake);	getchar();
}int main()
{//设置为本地环境setlocale(LC_ALL,"");test();return 0;
}

运行结果:
在这里插入图片描述

3)初始化蛇⾝(InitSnake)

蛇最开始⻓度为5节,每节对应链表的⼀个节点,蛇⾝的每⼀个节点都有⾃⼰的坐标。

  • 创建5个节点,然后将每个节点存放在链表中进⾏管理。
  • 创建完蛇⾝后,将蛇的每⼀节打印在屏幕上。
  • 蛇的初始位置从(24,5)开始

需要将初始位置在Snake.h文件中进行宏定义:

#define POS_X 24
#define POS_Y 5

设置蛇的属性:

  • 游戏状态是:OK
  • 蛇的移动速度:200毫秒
  • 蛇的默认⽅向:RIGHT
  • 初始成绩:0
  • 每个⻝物的分数:10

蛇⾝打印的宽字符也在Snake.h文件中进行宏定义:

#define BODY L'●' 

初始化蛇⾝函数:

void InitSnake(pSnake ps)
{//当前开辟的蛇节点的指针pSnakeNode cur = NULL;//开辟5个节点for (int i = 0; i < 5; i++){//开辟空间cur = (pSnakeNode)malloc(sizeof(SnakeNode));//如果开辟失败if (cur == NULL){perror("InitSnake()::malloc()");return;}cur->next = NULL;cur->x = POS_X + 2 * i;cur->y = POS_Y;//头插法插入链表//空链表if (ps->_pSnake == NULL){ps->_pSnake = cur;}//非空else{cur->next = ps->_pSnake;ps->_pSnake = cur;}}//打印蛇身cur = ps->_pSnake;while (cur){SetPos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}//设置蛇的属性ps->_status = OK;ps->_sleep_time = 200;//毫秒ps->_dir = RIGHT;ps->_score = 0;ps->_food_weight = 10;
}

再进行测试:

void test()
{Snake snake = { 0 };GameStart(&snake);	getchar();
}int main()
{//设置为本地环境setlocale(LC_ALL,"");test();return 0;
}

运行结果:
在这里插入图片描述

4)创建⻝物(CreateFood)

  • 先随机⽣成⻝物的坐标
    • x坐标必须是2的倍数
    • ⻝物的坐标不能和蛇⾝任意节点的坐标重复
  • 创建⻝物节点,打印⻝物

⻝物打印的宽字符在Snake.h文件中进行宏定义:

#define FOOD L'★'

创建⻝物的函数:

void CreateFood(pSnake ps)
{//先随机生成食物的坐标int x = 0;int y = 0;again:do{x = rand() % 53 + 2;  //x:2~54y = rand() % 25 + 1;  //y:1~25} while (x % 2 != 0);//食物坐标不能和蛇身体坐标冲突pSnakeNode cur = ps->_pSnake;//指向蛇头的指针while (cur){//随机生成的坐标冲突了就重新生成if (x == cur->x && y == cur->y){goto again;}cur = cur->next;}//创建食物节点pSnakeNode pFood = (pSnakeNode)malloc(sizeof(SnakeNode));if (pFood == NULL){perror("CreateFood()::malloc()");return;}pFood->x = x;pFood->y = y;pFood->next = NULL;//打印食物节点SetPos(x, y);wprintf(L"%lc", FOOD);ps->_pFood = pFood;//食物节点地址赋值给_pFood
}

再进行测试:

void test()
{Snake snake = { 0 };GameStart(&snake);	getchar();
}int main()
{//设置为本地环境setlocale(LC_ALL,"");test();return 0;
}

运行结果:
在这里插入图片描述

三、游戏运⾏

在完成了游戏开始部分后,现在我们开始进入游戏运行的部分。

1、准备工作

1)帮助信息(PrintHelpInfo)

游戏运⾏期间,右侧需要打印帮助信息,提⽰玩家。

帮助信息函数:

void PrintHelpInfo()
{SetPos(64, 14);wprintf(L"%ls", L"不能穿墙,不能咬到自己");SetPos(64, 15);wprintf(L"%ls", L"用↑.↓.←.→来控制蛇的移动");SetPos(64, 16);wprintf(L"%ls", L"按F3加速,F4减速");SetPos(64, 17);wprintf(L"ls", L"按Esc退出游戏,按空格暂停游戏");SetPos(64, 19);wprintf(L"ls", L"《怀旧》制作");
}

运行结果:
在这里插入图片描述

2)判断按键状态(宏KEY_PRESS)

根据游戏状态检查游戏是否继续,如果是状态是OK,游戏继续,否则游戏结束。
如果游戏继续,就检测按键情况,确定蛇下⼀步的⽅向,或者是否加速减速,是否暂停或者退出游戏。

因此我们还需要判断按键使用情况,通过宏定义来实现:

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

需要的虚拟按键的罗列:

  • 上:VK_UP
  • 下:VK_DOWN
  • 左:VK_LEFT
  • 右:VK_RIGHT
  • 空格:VK_SPACE
  • ESC:VK_ESCAPE
  • F3:VK_F3
  • F4:VK_F4

3)暂停(Pause)

当我们按空格键之后,游戏要能达到暂停的效果。

暂停函数:

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

2、游戏运行函数(GameRun)

接着再在Snake.c文件中创建游戏运行的函数GameRun

void GameRun(pSnake ps)
{//打印帮助信息PrintHelpInfo();//游戏主体do{//打印总分数和食物分SetPos(64, 10);printf("总分数:%d\n", ps->_score);SetPos(64, 11);printf("当前食物的分数:%2d\n", ps->_food_weight);//检测按键//上if (KEY_PRESS(VK_UP) && ps->_dir != DOWN)//按上键时蛇方向不能为下{ps->_dir = UP;}//下else if (KEY_PRESS(VK_DOWN) && ps->_dir != UP){ps->_dir = DOWN;}//左else if (KEY_PRESS(VK_LEFT) && ps->_dir != RIGHT){ps->_dir = LEFT;}//右else if (KEY_PRESS(VK_RIGHT) && ps->_dir != LEFT){ps->_dir = RIGHT;}//空格(暂停)else if (KEY_PRESS(VK_SPACE)){Pause();}//Esc(正常退出游戏)else if (KEY_PRESS(VK_ESCAPE)){ps->_status = END_NORMAL;}//F3(加速)else if (KEY_PRESS(VK_F3)){//休息时间如果大于80  休息时间减少30   一个食物的分数加2if (ps->_sleep_time > 80){ps->_sleep_time -= 30;ps->_food_weight += 2;}}//F4(减速)else if (KEY_PRESS(VK_F4)){//一个食物的分数如果大于2  休息时间增加30  一个食物的分数-2if (ps->_food_weight > 2){ps->_sleep_time += 30;ps->_food_weight -= 2;}}//蛇的移动SnakeMove(ps);//休眠时间Sleep(ps->_sleep_time);} while (ps->_status == OK);
}

再进行测试:

void test()
{Snake snake = { 0 };GameStart(&snake);	GameRun(&snake);getchar();
}int main()
{//设置为本地环境setlocale(LC_ALL,"");srand((unsigned int)time(NULL));//确保食物产生的坐标是真正随机的test();return 0;
}

运行结果:
在这里插入图片描述

1)蛇移动(SnakeMove)

  • 先创建下⼀个节点,根据移动⽅向和蛇头的坐标,得到蛇移动到下⼀个位置的坐标。
  • 看下⼀个位置是否是⻝物,是⻝物就做吃⻝物处理。
  • 如果不是⻝物则做前进⼀步的处理。
  • 蛇⾝移动后,判断是否会撞墙或者撞上⾃⼰蛇⾝,从⽽影响游戏的状态。

蛇移动函数:

void SnakeMove(pSnake ps)
{//创建蛇即将到的下一个节点  pSnakeNode pNextNode = (pSnakeNode)malloc(sizeof(SnakeNode));if (pNextNode == NULL){perror("SnakeMove()::malloc()");return;}//蛇即将到的下一个节点的坐标//根据方向和蛇头坐标来得到switch (ps->_dir){//上case UP:pNextNode->x = ps->_pSnake->x;pNextNode->y = ps->_pSnake->y - 1;break;//下case DOWN:pNextNode->x = ps->_pSnake->x;pNextNode->y = ps->_pSnake->y + 1;break;//左case LEFT:pNextNode->x = ps->_pSnake->x - 2;pNextNode->y = ps->_pSnake->y;break;//右case RIGHT:pNextNode->x = ps->_pSnake->x + 2;pNextNode->y = ps->_pSnake->y;break;}//检测下一个节点是否是食物if (NextIsFood(pNextNode, ps)){//是食物EatFood(pNextNode, ps);}else{//不是食物NoFood(pNextNode, ps);}//检测蛇是否撞墙KillByWall(ps);//检测蛇是否撞到自己KillBySelf(ps);
}
1.a)下一个节点是否是食物(NextIsFood)

判断传入的节点 pn的坐标是否与食物坐标相同。

下一个节点是否是食物函数:

int NextIsFood(pSnakeNode pn, pSnake ps)
{return (ps->_pFood->x == pn->x && ps->_pFood->y == pn->y);
}
1.b)是食物(EatFood)

是食物函数:

void EatFood(pSnakeNode pn, pSnake ps)
{//头插法//食物节点成为新的蛇头ps->_pFood->next = ps->_pSnake;ps->_pSnake = ps->_pFood;//释放pn节点(下一个位置)free(pn);pn = NULL;//打印蛇身pSnakeNode cur = ps->_pSnake;while (cur);{SetPos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}//吃掉单个食物的分数加到总分ps->_score += ps->_food_weight;//重新创建食物CreateFood(ps);
}
1.c)不是食物(NoFood)

下⼀个节点成为新的蛇头,并将之前蛇⾝最后⼀个节点打印为空格,并释放掉。

注意: 释放最后⼀个结点后,还得将结点的指针改为NULL,保证蛇尾打印可以正常结束,不会越界访问。

不是食物函数:

void NoFood(pSnakeNode pn, pSnake ps)
{//头插法  //下一个节点成为新的蛇头pn->next = ps->_pSnake;ps->_pSnake = pn;//打印蛇身pSnakeNode cur = ps->_pSnake;while (cur->next->next){SetPos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}//蛇身最后一个节点打印为空白(2个空格)SetPos(cur->next->x, cur->next->y);printf(" ");//再释放掉并置为NULLfree(cur->next);cur->next = NULL;
}
1.d)撞墙(KillByWall)

判断蛇头的坐标是否和墙的坐标冲突。

撞墙函数:

void KillByWall(pSnake ps)
{if (ps->_pSnake->x == 0 || ps->_pSnake->x == 56 ||ps->_pSnake->y == 0 || ps->_pSnake->y == 26){ps->_status = KILL_BY_WALL;}
}
1.e)撞到自身(KillBySelf)

判断蛇头的坐标是否和蛇⾝体的坐标冲突。

撞到自身函数:

void KillBySelf(pSnake ps)
{//记录除蛇头外的第一个蛇身节点pSnakeNode cur = ps->_pSnake->next;//遍历除蛇头的所有蛇身节点坐标while (cur){if (cur->x == ps->_pSnake->x && cur->y == ps->_pSnake->y){ps->_status = KILL_BY_SELF;break;}cur = cur->next;}
}

四、游戏结束

1、游戏结束函数(GameEnd)

当游戏状态不再是OK(游戏继续)的时候,要告知游戏结束的原因,并且释放蛇⾝节点。

Snake.c文件中创建游戏运行的函数GameRun

void GameEnd(pSnake ps)
{//判断游戏状态SetPos(24, 12);switch (ps->_status){//正常结束case END_NORMAL:wprintf(L"您主动结束游戏\n");break;//撞墙case KILL_BY_WALL:wprintf(L"您撞到墙上,游戏结束\n");break;//咬到自身case KILL_BY_SELF:wprintf(L"您咬到了自己,游戏结束\n");break;}//释放蛇身链表pSnakeNode cur = ps->_pSnake;while (cur){pSnakeNode del = cur;cur = cur->next;free(del);}
}

当完成了上面的所有方法后,我们就可以在test.c文件中来实现整个游戏了。

#include<locale.h>
#include"Snake.h"void test()
{int ch = 0;do{Snake snake = { 0 };GameStart(&snake);GameRun(&snake);GameEnd(&snake);SetPos(20, 15);printf("再来一局吗!(Y/N):");ch=getchar();while (getchar() != '\n');} while (ch == 'Y' || ch == 'y');SetPos(0, 27);
}int main()
{//设置为本地环境setlocale(LC_ALL,"");srand((unsigned int)time(NULL));//产生随机的食物test();return 0;
}

运行结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

点击查看:贪吃蛇源代码


http://www.hkcw.cn/article/CyqiuioCAg.shtml

相关文章

循序渐进 Android Binder(一):IPC 基本概念和 AIDL 跨进程通信的简单实例

Binder 给人的第一印象是”捆绑者“&#xff0c;即将两个需要建立关系的事物用某些工具束缚在一起。在 Android 中&#xff0c;Binder 是一种高效的跨进程通信&#xff08;IPC&#xff09;机制&#xff0c;它将可以将运行在不同进程中的组件进行绑定&#xff0c;以实现彼此通信…

ISBN书号查询接口如何用PHP实现调用?

一、什么是ISBN书号查询接口 ISBN数据查询接口是一项图书信息查询服务。它基于全球通用的ISBN编码系统&#xff0c;帮助用户快速获取图书的详细信息&#xff0c;包括书名、作者、出版社、出版时间、价格、封面等关键字段。 该接口广泛应用于电商平台、图书馆管理系统、二手书…

Linux(信号)

目录 一 什么是信号 二 Linux中的信号 1. 查看信号&#xff1a;kill -l 2. 自定义信号的处理方式 2.1 API 2.2 demo 3. 理解信号的发送 4. 信号产生的方式 三 信号保存 四 捕捉信号 1. 先来说说硬件中断&#xff1a; 1. 谁调度操作系统&#xff1f; 2. 理解时间片…

[Windows] Simple Live v1.8.3 开源聚合直播 :支持哔哩哔哩 虎牙 斗鱼 抖音

Simple Live 是一款基于 AllLive 项目 开发的开源聚合直播 APP&#xff0c;支持 哔哩哔哩、虎牙、斗鱼、抖音 等主流平台&#xff0c;具备 无广告、低占用、弹幕互动 等核心优势。其核心功能包括&#xff1a;全平台覆盖&#xff1a;一站式聚合多平台直播资源&#xff0c;无需切…

第十天:Java反射

反射 反射就是&#xff1a;加载类&#xff0c;并编写代码获取类中的成员变量&#xff0c;方法&#xff0c;构造器等。 注意&#xff1a;反射&#xff0c;注解&#xff0c;动态代理就是用来学习框架做框架的&#xff0c;在平时业务开发需求上很少用到。 1 反射学什么&#xf…

整数有约 | 刘乾专访:继续预训练策略与数据优化之道

人工智能多语言处理近年来得到了极大的关注&#xff0c;尤其是在以东南亚为代表的小语种环境中&#xff0c;其特殊的语言多样性和语料库稀缺性使得研究挑战和机遇并存。在现有的自然语言处理模型中&#xff0c;英语和中文因为有海量高质量数据的支持&#xff0c;常被作为核心语…

Google 发布的全新导航库:Jetpack Navigation 3

前言 多年来&#xff0c;Jetpack Navigation 库一直是开发者的重要工具&#xff0c;但随着 Android 用户界面领域的发展&#xff0c;特别是大屏设备的出现和 Jetpack Compose 的兴起&#xff0c;Navigation 的功能也需要与时俱进。 今年的 Google I/O 上重点介绍了 Jetpack Na…

抖音商城抓包 分析

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 抓包展示 总结 1.出于安全考虑,本章未…

uniapp-商城-77-shop(8.2-商品列表,地址信息添加,级联选择器picker)

地址信息,在我们支付订单上有这样一个接口,就是物流方式,一个自提,我们就显示商家地址。一个是外送,就是用户自己填写的地址。 这里先说说用户的地址添加。需要使用到的一些方式方法,主要有关于地址选择器,就是uni-data-picker级联选择。 该文介绍了电商应用中地址信息处…

AlmaLinux OS 10 正式发布:兼容 RHEL 10 带来多项技术革新

AlmaLinux OS 基金会日前宣布推出 AlmaLinux OS 10&#xff0c;该版本代号代号紫色的狮子 (Purple Lion)&#xff0c;新版本带来多项新功能和技术更新&#xff0c;旨在为用户提供更强大的企业级 Linux 体验。 该系统使用与 RHEL 10 相同的源代码构建并于 RHEL 10 保持完全兼…

深入理解C# MVVM模式:从理论到实践

在现代软件开发中&#xff0c;良好的架构设计对于构建可维护、可测试和可扩展的应用程序至关重要。Model-View-ViewModel (MVVM) 是一种特别适合XAML-based应用程序&#xff08;如WPF、Xamarin和UWP&#xff09;的架构模式。本文将全面探讨MVVM模式的概念、实现细节、最佳实践以…

Git GitHub Gitee

一、Git 是一个免费、开源的分布式版本控制系统。 版本控制&#xff1a;一种记录文件内容变化&#xff0c;以便将来查阅特定版本修订情况的系统。它最重要的就是可以记录文件修改历史记录&#xff0c;从而让用户可以看历史版本&#xff0c;方便版本切换。 1.和集中式版本控制…

数据库管理-第332期 大数据已死,那什么当立?(20250602)

数据库管理332期 2025-06-02 数据库管理-第332期 大数据已死&#xff0c;那什么当立&#xff1f;&#xff08;20250602&#xff09;1 概念还是技术2 必然的大数据量3 离线到实时4 未来总结 数据库管理-第332期 大数据已死&#xff0c;那什么当立&#xff1f;&#xff08;202506…

Java Netty 中处理粘包和半包问题的解决方案 | TCP消息完整性校验(XOR )

文章目录 引言I 处理TCP粘包和半包问题背景粘包问题的产生原因解决方案WebSocket中的粘包和半包问题及解决方案II Java Netty 中处理粘包和半包问题粘包和半包问题可以通过以下几种方式解决:使用分隔符解码器基于长度字段的解码器实现自定义解码器III TCP常见封装处理消息接收…

鸿蒙next系统以后会取代安卓吗?

点击上方关注 “终端研发部” 设为“星标”&#xff0c;和你一起掌握更多数据库知识 官方可没说过取代谁谁&#xff0c;三足鼎立不好吗&#xff1f;三分天下&#xff0c;并立共存。 鸿蒙基于Linux&#xff0c;有人说套壳&#xff1b;ios/macos基于Unix&#xff0c;说它ios开源了…

排便不是一件可以随意“延后”的事:长期便秘->直肠敏感性降低->功能性便秘->大便失禁

文章目录 引言知识扩展: 快乐排便的黄金姿势I 便秘并不是一种单一成因的疾病便秘成因临床治疗II 总是压抑排便,身体会发生的变化III 排便不是一件可以随意“延后”的事引言 排便是一种复杂的反射行为: 由“直肠充盈—产生便意—括约肌协调—排出”的完整生理链条完成的。 …

基于Spring Boot 电商书城平台系统设计与实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…

Golang——5、函数详解、time包及日期函数

函数详解、time包及日期函数 1、函数1.1、函数定义1.2、函数参数1.3、函数返回值1.4、函数类型与变量1.5、函数作参数和返回值1.6、匿名函数、函数递归和闭包1.7、defer语句1.8、panic和recover 2、time包以及日期函数2.1、time.Now()获取当前时间2.2、Format方法格式化输出日期…

HTTP详解

使用的工具&#xff1a;fiddler 一、请求和响应报文的结构 1.请求 ⾸⾏: [⽅法] [url] [版本]Header: 请求的属性, 冒号分割的键值对;每组属性之间使⽤\n分隔;遇到空⾏表⽰Header部分结束Body: 空⾏后⾯的内容都是Body. Body允许为空字符串. 如果Body存在, 则在Header中会有…

解决:install via Git URL失败的问题

为解决install via Git URL失败的问题&#xff0c;修改安全等级security_level的config.ini文件&#xff0c;路径如下&#xff1a; 还要重启&#xff1a; 1.reset 2.F5刷新页面 3.关机服务器&#xff0c;再开机&#xff08;你也可以省略&#xff0c;试试&#xff09; 4.Wind…