【C语言】C语言经典小游戏:贪吃蛇(下)
文章目录
- 一、游戏前准备
- 二、游戏开始
- 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;
}
运行结果:
点击查看:贪吃蛇源代码
相关文章:

【C语言】C语言经典小游戏:贪吃蛇(下)
文章目录 一、游戏前准备二、游戏开始1、游戏开始函数(GameStart)1)打印欢迎界⾯(WelcomeToGame)2)创建地图(CreateMap)3)初始化蛇⾝(InitSnake)4…...

NTT印地赛车:数字孪生技术重构赛事体验范式,驱动观众参与度革命
引言:数字孪生技术赋能体育赛事,开启沉浸式观赛新纪元 在传统体育赛事观赛模式遭遇体验天花板之际,NTT与印地赛车系列赛(NTT INDYCAR SERIES)的深度合作,通过数字孪生(Digital Twin)…...

30.【新型数据架构】-区块链数据架构
30.【新型数据架构】-区块链数据架构:分布式账本,不可篡改性,用于数据溯源 一、区块链数据架构的本质:分布式账本的革新 区块链的核心是分布式账本技术(Distributed Ledger Technology, DLT),它颠覆了传统中心化数据库的架构模式: 去中心化存储: 账本数据不再集中存储…...
使用docker 安装Redis 带配置文件(x86和arm)版本
一、安装redis 1.1 拉去ARM镜像(7.4.2) docker pull registry.cn-hangzhou.aliyuncs.com/qiluo-images/linux_arm64_redis:latest1.2 拉去x86镜像(8.0.1)版本 docker pull registry.cn-hangzhou.aliyuncs.com/qiluo-images/redis:latest新建文件夹 mkd…...

在CSDN发布AWS Proton解决方案:实现云原生应用的标准化部署
引言:云原生时代的部署挑战 在云原生应用开发中,基础设施管理的复杂性已成为团队面临的核心挑战。随着微服务架构的普及,每个服务可能包含数十个AWS资源(如Lambda、API Gateway、ECS集群等),传统的手动配置…...
小白的进阶之路系列之十----人工智能从初步到精通pytorch综合运用的讲解第三部分
本文将介绍Autograd基础。 PyTorch的Autograd特性是PyTorch灵活和快速构建机器学习项目的一部分。它允许在一个复杂的计算中快速而简单地计算多个偏导数(也称为梯度)。这个操作是基于反向传播的神经网络学习的核心。 autograd的强大之处在于它在运行时动态地跟踪你的计算,…...
[蓝桥杯]整理玩具
整理玩具 题目描述 小明有一套玩具,一共包含 NMNM 个部件。这些部件摆放在一个包含 NMNM 个小格子的玩具盒中,每个小格子中恰好摆放一个部件。 每一个部件上标记有一个 0 ~ 9 的整数,有可能有多个部件标记相同的整数。 小明对玩具的摆放有…...

C++11 Move Constructors and Move Assignment Operators 从入门到精通
文章目录 一、引言二、基本概念2.1 右值引用(Rvalue References)2.2 移动语义(Move Semantics) 三、移动构造函数(Move Constructors)3.1 定义和语法3.2 示例代码3.3 使用场景 四、移动赋值运算符ÿ…...
JavaScript 中的单例内置对象:Global 与 Math 的深度解析
JavaScript 中的单例内置对象:Global 与 Math 的深度解析 在 JavaScript 的世界中,单例内置对象是开发者必须了解的核心概念之一。它们是语言规范中预定义的对象,无需显式创建即可直接使用。本文将深入解析 JavaScript 中最重要的两个单例内…...

11 - ArcGIS For JavaScript -- 高程分析
这里写自定义目录标题 描述代码实现结果 描述 高程分析是地理信息系统(GIS)中的核心功能之一,主要涉及对地表高度数据(数字高程模型, DEM)的处理和分析。 ArcGIS For JavaScript4.32版本的发布,提供了Web端的针对高程分析的功能。 代码实现 <!doct…...

通道注意力
一、 什么是注意力 其中注意力机制是一种让模型学会「选择性关注重要信息」的特征提取器,就像人类视觉会自动忽略背景,聚焦于图片中的主体(如猫、汽车)。 transformer中的叫做自注意力机制,他是一种自己学习自己的机制…...

2048游戏的技术实现分析-完全Java和Processing版
目录 简介Processing库基础项目构建指南项目结构核心数据结构游戏核心机制图形界面实现性能优化代码详解设计模式分析测试策略总结与展望简介 2048是一款由Gabriele Cirulli开发的经典益智游戏。本文将深入分析其Java实现版本的技术细节。该实现使用了Processing库来创建图形界…...

全国县域统计年鉴PDF-Excel电子版-2022年
全国县域统计年鉴PDF-Excel电子版-2022年.ziphttps://download.csdn.net/download/2401_84585615/89784662 https://download.csdn.net/download/2401_84585615/89784662 《中国县域统计年鉴》是一部全面反映中国县域社会经济发展状况的资料性年鉴。自2014年起,该年…...
平滑技术(数据处理,持续更新...)
一.介绍 “平滑”是一种用于减少数据中的短期波动、噪声或者异常值的技术,从而更清晰地揭示数据的长期趋势或周期性特征。 平滑的主要作用: 1.减少噪声。数据中常常包含各种随机噪声或误差,这些误差可能会掩盖数据的真实趋势。平滑可以降低…...
App 上线后还能加固吗?iOS 应用的动态安全补强方案实战分享(含 Ipa Guard 等工具组合)
很多开发者以为 App 一旦上线,安全策略也就定型了。但现实是,App 上线只是攻击者的起点——从黑产扫描符号表、静态分析资源文件、注入调试逻辑,到篡改功能模块,这些行为都可能在你“以为很安全”的上线版本里悄然发生。 本篇文章…...

gitlab CI/CD本地部署配置
背景: 代码管理平台切换为公司本地服务器的gitlab server。为了保证commit的代码至少编译ok,也为了以后能拓展test cases,现在先搭建本地gitlab server的CI/CD基本的编译job pipeline。 配置步骤: 先安装gitlab-runner: curl -L "ht…...

AI大模型在测试领域应用案例拆解:AI赋能的软件测试效能跃迁的四大核心引擎(顺丰科技)
导语 5月份QECon深圳大会已经结束,继续更新一下案例拆解,本期是来自顺丰科技。 文末附完整版材料获取方式。 首先来看一下这个案例的核心内容,涵盖了测四用例设计、CI/CD辅助、测试执行、监控预警四大方面,也是算大家比较熟悉的…...

从零搭建uniapp项目
目录 创建uni-app项目 基础架构 安装 uni-ui 组件库 安装sass依赖 easycom配置组件自动导入 配置view等标签高亮声明 配置uni-ui组件类型声明 解决 标签 错误 关于tsconfig.json中提示报错 关于非原生标签错误(看运气) 安装 uview-plus 组件库…...
数据库密码加密
数据库密码加密 添加jar包构建工具类具体使用优缺点 添加jar包 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId> </dependency>构建工具类 public class PasswordUtil …...
GaLore:基于梯度低秩投影的大语言模型高效训练方法详解一
📘 GaLore:基于梯度低秩投影的大语言模型高效训练方法详解 一、论文背景与动机 随着大语言模型(LLM)参数规模的不断增长,例如 GPT-3(175B)、LLaMA(65B)、Qwenÿ…...

OpenCV CUDA模块图像处理------图像融合函数blendLinear()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 该函数执行 线性融合(加权平均) 两个图像 img1 和 img2,使用对应的权重图 weights1 和 weights2。 融合公式…...
Linux服务器如何安装wps?
1.到wps官网 https://www.wps.cn/product/wpslinux 2.到安装目录上执行命令 sudo dpkg -i wps-office*.deb 3.启动wps 在终端中输入 wps 命令即可启动 WPS...

图片压缩工具 | 图片生成PDF文档
OPEN-IMAGE-TINY,一个基于 Electron VUE3 的图片压缩工具,项目开源地址:https://github.com/0604hx/open-image-tiny ℹ️ 需求描述 上一版本发布后,有用户提出想要将图片转换(或者说生成更为贴切)PDF文档…...
Python的浅拷贝与深拷贝
一、浅拷贝 浅拷贝,指的是重新分配一块内存,创建一个新的对象,但里面的元素是原对象中各个子对象的引用。 浅拷贝有几种方法: 1、 使用数据类型本身的构造器 list1[1,2,3]list2 list(list1) # 使用了数据类型本身的构造器 list…...

VSCode - VSCode 放大与缩小代码
VSCode 放大与缩小代码 1、放大 点击顶部菜单栏【查看】 -> 点击外观 -> 点击【放大】 或者,使用快捷键:Ctrl # 操作方式先按住 Ctrl 键,再按 键2、缩小 点击顶部菜单栏【查看】 -> 点击外观 -> 点击【缩小】 或者&#x…...
消息队列处理模式:流式与批处理的艺术
🌊 消息队列处理模式:流式与批处理的艺术 📌 深入解析现代分布式系统中的数据处理范式 一、流式处理:实时数据的"活水" 在大数据时代,流式处理已成为实时分析的核心技术。它将数据视为无限的流,…...

11-Oracle 23ai Vector Embbeding和ONNX
Embedding (模型嵌入)是 AI 领域的一个核心概念 一、Embedding(嵌入)的含义 Embedding 是一种将 非结构化数据(如文本、图像、音频、视频)转换为 数值向量的技术。 其核心是通过 嵌入模型(…...
Build a Large Language Model (From Scratch) 序章
关于本书 《从零构建大型语言模型》旨在帮助读者全面理解并从头创建类似GPT的大型语言模型(LLMs)。 全书首先聚焦于文本数据处理的基础知识和注意力机制的编码,随后指导读者逐步实现一个完整的GPT模型。书中还涵盖了预训练机制以及针对文本…...
【HarmonyOS 5】教育开发实践详解以及详细代码案例
以下是基于 HarmonyOS 5 的教育应用开发实践详解及核心代码案例,结合分布式能力与教育场景需求设计: 一、教育应用核心开发技术 ArkTS声明式UI 使用 State 管理学习进度状态,LocalStorageProp 实现跨页面数据同步(如课程…...
NoSQL 之Redis哨兵
目录 一、Redis 哨兵模式概述 (一)背景与核心目标 (二)基本架构组成 (三)核心功能 二、哨兵模式实现原理 (一)配置关键参数 (二)哨兵节点的定时任务 …...