贪吃蛇实现
1.资料来源
https://learn.microsoft.com/zh-cn/windows/console/getstdhandle
2.前言
简介
贪吃蛇是久负盛名的游戏,和俄罗斯方块、扫雷等游戏位列于经典游戏的行列。
《贪食蛇》中玩家控制一条不断移动的蛇,在屏幕上吃掉出现的食物。每吃掉一个食物,蛇的身体就会变长。游戏的目标是尽可能长时间地生存下去,同时避免蛇头撞到自己的身体或屏幕边缘。游戏最初是像素风格,后来发展出了3D版本和多人对战模式。玩家需要灵活操作,利用策略在有限的空间内避免碰撞,挑战高分。
实现基本功能
- 贪吃蛇地图绘制
- 蛇吃食物的功能(上下左右方向键控制蛇的动作)
- 蛇撞墙死亡
- 蛇撞自身死亡
- 计算得分
- 蛇身加速、减速
- 暂停游戏
技术要点
C语言函数、枚举、结构体、动态内存管理、预处理指令、链表、Win2API等。
WIN32API
Win32 API是Windows操作系统的核心编程接口,用于与操作系统内核直接交互。
Windows这个多作业系统除了协调应用程序的执行、分配内存、管理资源之外,它同时也是一个很大的服务中心,调用这个服务中心的各种服务(每一种服务就是一种函数),可以帮应用程序达到开启视窗、描绘图形、使用周边设备等目的,由于这些函数的服务的对象是应用程序(Application),所以称之为Application Programming Interface,简称API函数, WIN32API也就是Microsoft Windows 32位平台的应用程序编辑接口。
控制台程序(Console)
平常运行起来的黑框其实就是控制台程序
win + R输入cmd打开控制台窗口
可以使用cmd命令来设置控制台窗口的长宽:设置控制台窗口的大小,30行,100列
mode con cols=100 lines=30
也可以通过命令命令设置控制台窗口的名字
title 贪吃蛇
这些能在控制台窗口执行的命令,也可以调用C语言函数system来执行,例如:
#include <stdlib.h>
//system函数可以执行系统命令
int main()
{//设置控制台相关属性system("mode con cols=100 lines=30");system("title 贪吃蛇");//暂停//getchar(); system("pause");return 0;
}
3.相关win32API函数
控制台屏幕上的坐标 COORSD
COORD 是Windows API上定义的一个结构体,表示一个字符在控制台屏幕缓冲区上的坐标,坐标系(0, 0)的原点位于缓冲区的顶部左侧单元格。
typedef struct _COORD {SHORT X;SHORT Y;
} COORD, *PCOORD;
示例
#include <windows.h>
int main()
{COORD pos1 = { 0, 0 };COORD pos2 = { 10, 20 };system("pause");return 0;
}
GetStdHandle 获取句柄
GetStdHandle是一个Windows API函数,它用于从一个特定的标准设备(标准输入、标准输出或标准错误)中获取一个句柄(用来标识不同设备的数值),使用这个句柄可以操作设备。
HANDLE WINAPI GetStdHandle(_In_ DWORD nStdHandle
);
HANDLE GetStdHandle(DWORD nStdHandle);
typedef void* HANDLE
CONSOLE_CURSOR_INFO 结构
包含有关控制台游标的信息。
typedef struct _CONSOLE_CURSOR_INFO {DWORD dwSize;BOOL bVisible;
} CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO;
GetConsoleCursorInfo 检索游标信息
检索有关指定控制台屏幕缓冲区的游标大小和可见性的信息。
BOOL WINAPI GetConsoleCursorInfo(_In_ HANDLE hConsoleOutput, //句柄_Out_ PCONSOLE_CURSOR_INFO lpConsoleCursorInfo //指针
);PCONSOLE_CURSOR_INFO 是指向 CONSOLE_CURSOR_INFO 结构的指针,该结构接收有关
主机游标(光标)的信息。
SetConsoleCursorInfo 设置游标信息
为指定的控制台屏幕缓冲区设置光标的大小和可见性。
BOOL WINAPI SetConsoleCursorInfo(_In_ HANDLE hConsoleOutput,_In_ const CONSOLE_CURSOR_INFO *lpConsoleCursorInfo
);
示例1
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int main()
{//获得标准输出设备的句柄HANDLE houtput = NULL;houtput = GetStdHandle(STD_OUTPUT_HANDLE);//定义一个光标信息的结构体CONSOLE_CURSOR_INFO cursor_info = { 0 };//获取和houtput句柄相关的控制台上的光标信息,存储在cursor_info中GetConsoleCursorInfo(houtput, &cursor_info);printf("%d\n", cursor_info.dwSize);system("pause"); //暂停//修改光标的占比cursor_info.dwSize = 50;//设置和houtput句柄相关的控制台上的光标信息SetConsoleCursorInfo(houtput, &cursor_info);system("pause");return 0;
}
SetConsoleCursorPosition 设置控制台光标位置
设置指定控制台屏幕缓冲区中的光标位置。将要设置的坐标信息存储在COORD类型的pos中,调用SetConsoleCursorPosition函数将光标位置设置到指定的位置。
BOOL WINAPI SetConsoleCursorPosition(_In_ HANDLE hConsoleOutput,_In_ COORD dwCursorPosition
);
示例:
void set_pos(short x, short y)
{//获得标准输出设备的句柄HANDLE houtput = NULL;houtput = GetStdHandle(STD_OUTPUT_HANDLE);//定位光标的位置COORD pos = { x, y };SetConsoleCursorPosition(houtput, pos);
}
int main()
{//直接定位光标位置set_pos(10, 20);system("pause");return 0;
}
GetAsyncKeyState 获取按键情况
确定调用函数时键是向上还是向下,以及上次调用 GetAsyncKeyState 后是否按下了该键。
SHORT GetAsyncKeyState([in] int vKey
);
将键盘上每个键的虚拟键值传给函数,函数通过返回值来分辨键的状态。
GetAsyncKeyState的返回值是short类型,在上一次调用GetAsyncKeyState函数后,如果返回的16位的short数据中,最高位是1,说明按键的状态是按下,如果最高位是0,说明按键的状态是抬起;如果最低位被置为1则说明,该按键按过,否则为0。
参考:虚拟键代码 https://learn.microsoft.com/zh-cn/windows/win32/inputdev/virtual-key-codes
分装宏函数
#define KEY_PRESS(vk) ((GetAsyncKeyState(vk)&1) ? 1 : 0)
//结果是1表示按过,结果是0表示没按过
示例:
#define KEY_PRESS(vk) ((GetAsyncKeyState(vk)&1) ? 1 : 0)
int main()
{//按哪个数字打印哪个数字while (1){if (KEY_PRESS(0x30))printf("0\n");else if (KEY_PRESS(0x31))printf("1\n");else if (KEY_PRESS(0x32))printf("2\n");else if (KEY_PRESS(0x33))printf("3\n");else if (KEY_PRESS(0x34))printf("4\n");else if (KEY_PRESS(0x35))printf("5\n");else if (KEY_PRESS(0x36))printf("6\n");else if (KEY_PRESS(0x37))printf("7\n");else if (KEY_PRESS(0x38))printf("8\n");else if (KEY_PRESS(0x39))printf("9\n");}return 0;
}
4.贪吃蛇游戏设计与分析
4.1地图
在游戏地图上,打印宽字符。普通的字符是占一个字节的,这类宽字符是占2个字节。
汉字本质上也是宽字符。
这里再简单的讲一下C语言的国际化特性相关的知识,过去C语言并不适合非英语国家(地区)使用。C语言最初假定地址都是单字节的,但是这些假定并不是在世界的任何地方都适用。
后来为了使C语言适应国际化,C语言的标准中不断加入了国际化的支持。比如:加入了宽字符的类型 wchar_t 和宽字符的输入输出函数,加入了 <locale.h> 头文件,其中提供了允许程序员针对特定地区(通常是国家或者说某种特定语言的地理区域)调整程序行为的函数。
4.1.1<locale.h>本地化
<locale.h>提供的函数用于控制C标准库中对于不同的地区会产生不一样行为的部分。
在标准库中,依赖地区的部分有以下几项:
- 数字量的格式
- 货币量的格式
- 字符集
- 日期和时间的表示形式
4.1.2类项
通过修改地区,程序可以改变它的行为来适应世界的不同区域。但地区的改变可能会影响库的许多部分,其中一部分可能是我们不希望修改的。所以C语言支持针对不同的类项进行修改。下面的一个宏,指定一个类项:
参考资料:https://learn.microsoft.com/zh-cn/cpp/text/locales-and-code-pages
https://learn.microsoft.com/zh-cn/cpp/c-runtime-library/reference/setlocale-wsetlocale?view=msvc-170
4.1.3 setlocale函数
char *setlocale(int category,const char *locale
);wchar_t *_wsetlocale(int category,const wchar_t *locale
);
setlocale函数用于修改当前地区,可以针对一个类项修改,也可以针对所有类项。
setlocale的第一个参数可以是前面说明的类项中的一个,那么每次只会影响一个类项,如果第一个参数是LC_ALL,就会影响所有的类项。
C标准给第二个参数仅定义了2种可能取值: “C”(正常模式)和 “”(本地模式)。
在任意程序执行开始,都会隐藏式执行调用:
setlocale(LC_ALL, "C");
调用setlocale函数就可以切换到本地模式,这种模式下程序会适应本地环境。
比如:切换到我们的本地模式后就支持宽字符(汉字)的输出等。
setlocale(LC_ALL, "");
setlocale的返回值是一个字符串指针,表示已经设置好的格式,如果调用失败,则返回空指针NULL。
setlocale()可以用来查询当前的地区,这时第二个参数设为NULL就可以了。
示例:
#include <locale.h>
int main()
{char* ret = setlocale(LC_ALL, NULL);printf("%s\n", ret);ret = setlocale(LC_ALL, "");printf("%s\n", ret);return 0;
}
参考资料:https://legacy.cplusplus.com/reference/clocale/setlocale/?kw=setlocale
/* setlocale example */
#include <stdio.h> /* printf */
#include <time.h> /* time_t, struct tm, time, localtime, strftime */
#include <locale.h> /* struct lconv, setlocale, localeconv */int main ()
{time_t rawtime;struct tm * timeinfo;char buffer [80];struct lconv * lc;time ( &rawtime );timeinfo = localtime ( &rawtime );int twice=0;do {printf ("Locale is: %s\n", setlocale(LC_ALL,NULL) );strftime (buffer,80,"%c",timeinfo);printf ("Date is: %s\n",buffer);lc = localeconv ();printf ("Currency symbol is: %s\n-\n",lc->currency_symbol);setlocale (LC_ALL,"");} while (!twice++);return 0;
}
4.1.3 宽字符的打印
宽字符的字面量必须叫上前缀L,否则C语言会把字面量当作窄字符类型处理。前缀L在单引号前面,表示宽字符。宽字符的打印使用wprintf,对应wprintf()的占位符为 %lc;在双引号前面,表示宽字符串,对应wprintf()的占位符为 %ls。
int main()
{//设置本地化setlocale(LC_ALL, "");//宽字符字面量前加 Lwchar_t ch1 = L'你';wchar_t ch2 = L'好';wchar_t ch3 = L'世';wchar_t ch4 = L'界';printf("%c%c\n", 'a', 'b');//格式串前面也要加 Lwprintf(L"%lc\n", ch1);wprintf(L"%lc\n", ch2);wprintf(L"%lc\n", ch3);wprintf(L"%lc\n", ch4);return 0;
}
代码
snake.h
#pragma once#include <stdio.h>
#include <locale.h>
#include <stdbool.h>
#include <windows.h>
#include <stdlib.h>
#include <time.h>#define POS_X 24
#define POS_Y 5
#define WALL L'□'
#define BOOY L'●'
#define FOOD L'★'//类型的声明//蛇的方向
enum DIRECTION
{UP = 1,DOWN,LEFT,RIGHT
};//蛇的状态
enum GAME_STATUS
{OK,//正常KILL_BY_WALL,//撞墙KILL_BY_SELF,//撞到自己END_NORMAL//正常退出
};//蛇身的节点类型
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 CreateFood(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
#define _CRT_SECURE_NO_WARNINGS 1#include "snake.h"//设置光标位置
void SetPos(short x, short y)
{//获取标准输出设备的句柄HANDLE houtput = NULL;houtput = GetStdHandle(STD_OUTPUT_HANDLE);//定位光标的位置COORD pos = { x, y };SetConsoleCursorPosition(houtput, pos);
}//欢迎界面的打印
void WelcomeToGame()
{SetPos(38, 14);wprintf(L"欢迎来到贪吃蛇小游戏\n");SetPos(40, 20);system("pause");system("cls");SetPos(30, 14);wprintf(L"用↑.↓.→.←来控制蛇的移动,按z加速,按x减速\n");SetPos(30, 15);wprintf(L"加速能够获得更高的分数\n");SetPos(40, 20);system("pause");system("cls");
}//绘制地图
void CreateMap()
{int i = 0;//上for (i = 0; i < 29; i++)wprintf(L"%lc", WALL);//左右for (i = 1; i <= 25; i++){SetPos(0, i);wprintf(L"%lc", WALL);SetPos(56, i);wprintf(L"%lc", WALL);}//下SetPos(0, 26);for (i = 0; i < 29; i++)wprintf(L"%lc", WALL);
}//初始化蛇身
void InitSnake(pSnake ps)
{int i = 0;pSnakeNode cur = NULL;//创建蛇身节点for (i = 0; i < 5; i++){cur = (pSnakeNode)malloc(sizeof(SnakeNode));if (cur == NULL){perror("InitSnake():malloc()");exit(1);}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", BOOY);cur = cur->next;}//设置贪吃蛇属性ps->_dir = RIGHT;//默认向右ps->_score = 0;ps->_food_weight = 10;ps->_sleep_time = 200;//单位是毫秒ps->_status = OK;
}//创建食物
void CreateFood(pSnake ps)
{int x = 0;int y = 0;//生成x是2的倍数// x: 2-54// y: 1-25//x = 2 * (rand() % 27) + 2;
again:do{x = rand() % 53 + 2;y = rand() % 25 + 1;} while (x % 2 != 0);//x和y的坐标不能和设的身体坐标冲突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;
}//1.游戏初始化
void GameStart(pSnake ps)
{//0.先设置窗口信息,再光标隐藏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);//设置控制台光标状态//1.打印环境界面和功能介绍WelcomeToGame();//2.绘制地图CreateMap();//3.初始化蛇身InitSnake(ps);//4.创建食物CreateFood(ps);
}//打印帮助信息
void printHelpInfo()
{SetPos(64, 14);wprintf(L"%ls", L"不能穿墙,不能咬到自己");SetPos(64, 15);wprintf(L"%ls", L"用↑.↓.→.←来控制蛇的移动");SetPos(64, 16);wprintf(L"%ls", L"按z加速,按x减速");SetPos(64, 17);wprintf(L"%ls", L"按ESC退出游戏,按空格暂停游戏");
}
//检测虚拟键值
#define KEY_PRESS(vk) ((GetAsyncKeyState(vk)&1) ? 1 : 0)
//暂停
void Pause()
{while (1){Sleep(200);if (KEY_PRESS(VK_SPACE)){break;}}
}
//判断下一个坐标是否是食物
int NextIsFood(pSnakeNode pn, pSnake ps)
{//是食物返回1,不是食物返回0//return (ps->_pFood->x == pn->x && ps->_pFood->y == pn->y);if (ps->_pFood->x == pn->x && ps->_pFood->y == pn->y)return 1;elsereturn 0;
}
//下一个位置是食物,吃掉食物
void EatFood(pSnakeNode pn, pSnake ps)
{//在CreateFood()里创建了pFood和SnakeMove()里创建了pNextNode两个食物节点,需要连接一个,释放一个//头插法ps->_pFood->next = ps->_pSnake;ps->_pSnake = ps->_pFood;//释放下一个位置的节点free(pn);pn = NULL;//打印pSnakeNode cur = ps->_pSnake;while (cur){SetPos(cur->x, cur->y);wprintf(L"%lc", BOOY);cur = cur->next;}ps->_score += ps->_food_weight;//重新创建食物CreateFood(ps);
}
//下一个位置不是食物
void NoFood(pSnakeNode pn, pSnake ps)
{//头插法pn->next = ps->_pSnake;ps->_pSnake = pn;pSnakeNode cur = ps->_pSnake;while (cur->next->next != NULL){SetPos(cur->x, cur->y);wprintf(L"%lc", BOOY);cur = cur->next;}//最后一个节点要打印空白字符(两个空格)覆盖原来的蛇身节点BOOYSetPos(cur->next->x, cur->next->y);printf(" ");//释放最后一个节点free(cur->next);cur->next = NULL;
}
//检查是否撞墙
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;}
}
//检查是否撞到自己
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;}
}
//蛇的移动-走一步
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);
}//2.运行游戏
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();}else if (KEY_PRESS(VK_ESCAPE)){//正常退出游戏ps->_status = END_NORMAL;}else if (KEY_PRESS(0x5A)){//加速if (ps->_sleep_time > 80)//分四档{ps->_sleep_time -= 30;ps->_food_weight += 2;}}else if (KEY_PRESS(0x58)){//减速if (ps->_food_weight > 2){ps->_sleep_time += 30;ps->_food_weight -= 2;}}//蛇的移动-走一步SnakeMove(ps);Sleep(ps->_sleep_time);} while (ps->_status == OK);
}//3.结束运行-善后工作
void GameEnd(pSnake ps)
{SetPos(24, 12);switch (ps->_status){case END_NORMAL:printf("正常退出游戏\n");break;case KILL_BY_WALL:printf("撞到墙上,游戏结束\n");break;case KILL_BY_SELF:printf("撞到自己,游戏结束\n");break;}//释放蛇身链表pSnakeNode cur = ps->_pSnake;while (cur){pSnakeNode del = cur;cur = cur->next;free(del);}
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1#include "snake.h"//游戏的测试逻辑
void test()
{int ch = 0;do{system("cls");//清屏//创建贪吃蛇Snake snake = { 0 };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.资料来源 https://learn.microsoft.com/zh-cn/windows/console/getstdhandle 2.前言 简介 贪吃蛇是久负盛名的游戏,和俄罗斯方块、扫雷等游戏位列于经典游戏的行列。 《贪食蛇》中玩家控制一条不断移动的蛇,在屏幕上吃掉出现的食物。每吃掉一个食物…...
Windows电脑本地部署运行DeepSeek R1大模型(基于Ollama和Chatbox)
文章目录 一、环境准备二、安装Ollama2.1 访问Ollama官方网站2.2 下载适用于Windows的安装包2.3 安装Ollama安装包2.4 指定Ollama安装目录2.5 指定Ollama的大模型的存储目录 三、选择DeepSeek R1模型四、下载并运行DeepSeek R1模型五、使用Chatbox进行交互5.1 下载Chatbox安装包…...
在C++中,成员变量必须在对象构造完成前初始化,但初始化的方式有多种...
在C中,成员变量必须在对象构造完成前初始化,但初始化的方式可以有多种,具体取决于成员变量的类型和设计需求。以下是C中成员变量初始化的规则和相关机制: 1. 成员变量必须初始化 如果成员变量是基本类型(如 int、doub…...
maven mysql jdk nvm node npm 环境安装
安装JDK 1.8 11 环境 maven环境安装 打开网站 下载 下载zip格式 解压 自己创建一个maven库 以后在idea 使用maven时候重新设置一下 这三个地方分别设置 这时候maven才算设置好 nvm 管理 npm nodejs nvm下载 安装 Releases coreybutler/nvm-windows GitHub 一键安装且若有…...
算法随笔_37: 交替合并字符串
上一篇:算法随笔_36: 复写零-CSDN博客 题目描述如下: 给你两个字符串 word1 和 word2 。请你从 word1 开始,通过交替添加字母来合并字符串。如果一个字符串比另一个字符串长,就将多出来的字母追加到合并后字符串的末尾。 返回 合并后的字符串 。 示例…...
w188校园商铺管理系统设计与实现
🙊作者简介:多年一线开发工作经验,原创团队,分享技术代码帮助学生学习,独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹赠送计算机毕业设计600个选题excel文…...
(2025 年最新)MacOS Redis Desktop Manager中文版下载,附详细图文
MacOS Redis Desktop Manager中文版下载 大家好,今天给大家带来一款非常实用的 Redis 可视化工具——Redis Desktop Manager(简称 RDM)。相信很多开发者都用过 Redis 数据库,但如果你想要更高效、更方便地管理 Redis 数据&#x…...
【Block总结】Shuffle Attention,新型的Shuffle注意力|即插即用
一、论文信息 标题: SA-Net: Shuffle Attention for Deep Convolutional Neural Networks 论文链接: arXiv 代码链接: GitHub 二、创新点 Shuffle Attention(SA)模块的主要创新在于高效结合了通道注意力和空间注意力,同时通过通道重排技…...
解锁豆瓣高清海报(一) 深度爬虫与requests进阶之路
前瞻 PosterBandit 这个脚本能够根据用户指定的日期,爬取你看过的影视最高清的海报,然后使用 PixelWeaver.py 自动拼接成指定大小的长图。 你是否发现直接从豆瓣爬取下来的海报清晰度很低? 使用 .pic .nbg img CSS 选择器,在 我…...
【机器学习与数据挖掘实战】案例11:基于灰色预测和SVR的企业所得税预测分析
【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈机器学习与数据挖掘实战 ⌋ ⌋ ⌋ 机器学习是人工智能的一个分支,专注于让计算机系统通过数据学习和改进。它利用统计和计算方法,使模型能够从数据中自动提取特征并做出预测或决策。数据挖掘则是从大型数据集中发现模式、关联…...
聚簇索引、哈希索引、覆盖索引、索引分类、最左前缀原则、判断索引使用情况、索引失效条件、优化查询性能
聚簇索引 聚簇索引像一本按目录排版的书,用空间换时间,适合读多写少的场景。设计数据库时,主键的选择(如自增ID vs 随机UUID)会直接影响聚簇索引的性能。 什么是聚簇索引? 数据即索引:聚簇索引…...
克隆OpenAI(基于openai API和streamlit)
utils.py: from langchain_openai import ChatOpenAI from langchain.memory import ConversationBufferMemory from langchain.chains import ConversationChain import osdef get_chat_response(api_key,prompt,memory): # memory不能是函数的内部局部变量&…...
DeepSeek技术深度解析:从不同技术角度的全面探讨
DeepSeek技术深度解析:从不同技术角度的全面探讨 引言 DeepSeek是一个集成了多种先进技术的平台,旨在通过深度学习和其他前沿技术来解决复杂的问题。本文将从算法、架构、数据处理以及应用等不同技术角度对DeepSeek进行详细分析。 一、算法层面 深度学…...
完全卸载mysql server步骤
1. 在控制面板中卸载mysql 2. 打开注册表,运行regedit, 删除mysql信息 HKEY_LOCAL_MACHINE-> SYSTEM->CurrentContolSet->Services->EventLog->Application->Mysql HKEY_LOCAL_MACHINE-> SYSTEM->CurrentContolSet->Services->Mysql …...
2025年大年初一篇,C#调用GPU并行计算推荐
C#调用GPU库的主要目的是利用GPU的并行计算能力,加速计算密集型任务,提高程序性能,支持大规模数据处理,优化资源利用,满足特定应用场景的需求,并提升用户体验。在需要处理大量并行数据或进行复杂计算的场景…...
机器学习优化算法:从梯度下降到Adam及其实验改进
机器学习优化算法:从梯度下降到Adam及其实验改进 在机器学习和深度学习领域,模型的训练过程本质上是一个优化问题。优化算法的作用是通过调整模型参数,使得模型在给定的数据 集上实现最优性能。而优化算法的效率和效果直接决定了模型的收敛速…...
在 Ubuntu 中使用 Conda 创建和管理虚拟环境
Conda 是一个广泛使用的包管理和环境管理系统,尤其适用于数据科学和 Python 开发。本文将指导你如何在 Ubuntu 系统中安装 Conda 并创建基于 python3.11 的虚拟环境。 1. 安装 Miniconda 或 Anaconda 方法 1:下载并安装 Miniconda Miniconda 是一个轻量…...
【深度学习】搭建卷积神经网络并进行参数解读
第一步 导包 import torch import torch.nn as nn import torch.optim as optim import torch.nn.functional as F from torchvision import datasets,transforms import matplotlib.pyplot as plt import numpy as np %matplotlib inline transforms 模块是 torchvision 库的…...
稀疏进化训练:机器学习优化算法中的高效解决方案
稀疏进化训练:机器学习优化算法中的高效解决方案 稀疏进化训练:机器学习优化算法中的高效解决方案引言第一部分:背景与动机1.1 传统优化算法的局限性1.2 进化策略的优势1.3 稀疏性的重要性 第二部分:稀疏进化训练的核心思想2.1 稀…...
Vue - Suspense的使用
在 Vue 3 中,Suspense 是一个用于处理异步组件的 API。它允许在加载异步组件时提供一个后备内容(例如加载指示器),从而改善用户体验。在加载期间,可以在页面上显示一个占位符,而不是让用户看到一个空白或错…...
在K8S中,pending状态一般由什么原因导致的?
在Kubernetes中,资源或Pod处于Pending状态可能有多种原因引起。以下是一些常见的原因和详细解释: 资源不足 概述:当集群中的资源不足以满足Pod或服务的需求时,它们可能会被至于Pending状态。这通常涉及到CPU、内存、存储或其他资…...
【算法】回溯算法专题② ——组合型回溯 + 剪枝 python
目录 前置知识进入正题小试牛刀实战演练总结 前置知识 【算法】回溯算法专题① ——子集型回溯 python 进入正题 组合https://leetcode.cn/problems/combinations/submissions/596357179/ 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以…...
理解红黑树
简介:红黑树是一种自平衡二叉查找树,由鲁道夫贝尔(Rudolf Bayer)在1972年发明,最初称为“对称二叉B树”。它的设计旨在解决普通二叉查找树在频繁插入和删除操作时可能退化为链表的问题,从而保持高效的查找、…...
从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架(OLED设备层封装)
目录 OLED设备层驱动开发 如何抽象一个OLED 完成OLED的功能 初始化OLED 清空屏幕 刷新屏幕与光标设置1 刷新屏幕与光标设置2 刷新屏幕与光标设置3 绘制一个点 反色 区域化操作 区域置位 区域反色 区域更新 区域清空 测试我们的抽象 整理一下,我们应…...
大模型能力评估数据集都有哪些?
大模型能力的评估数据集种类繁多,涵盖了语言理解、推理、生成、代码能力、安全性和鲁棒性等多个方面。以下是一些主要的评估数据集及其特点: 通用能力评估数据集: MMLU:多模态大规模多语言任务理解数据集,覆盖从基础教育到高级专业水平的57个科目,用于评估模型的知识储备…...
论文阅读(二):理解概率图模型的两个要点:关于推理和学习的知识
1.论文链接:Essentials to Understand Probabilistic Graphical Models: A Tutorial about Inference and Learning 摘要: 本章的目的是为没有概率图形模型背景或没有深入背景的科学家提供一个高级教程。对于更熟悉这些模型的读者,本章将作为…...
《OpenCV》——图像透视转换
图像透视转换简介 在 OpenCV 里,图像透视转换属于重要的几何变换,也被叫做投影变换。下面从原理、实现步骤、相关函数和应用场景几个方面为你详细介绍。 原理 实现步骤 选取对应点:要在源图像和目标图像上分别找出至少四个对应的点。这些对…...
【16届蓝桥杯寒假刷题营】第2期DAY4
【16届蓝桥杯寒假刷题营】第2期DAY4 - 蓝桥云课 问题描述 幼儿园小班的浩楠同学有一个序列 a。 他想知道有多少个整数三元组 (i,j,k) 满足 1≤i,j,k≤n 且 aiajak。 输入格式 共2行,第一行一个整数 n,表示序列的长度。 第二行 n 个整数&#x…...
用 HTML、CSS 和 JavaScript 实现抽奖转盘效果
顺序抽奖 前言 这段代码实现了一个简单的抽奖转盘效果。页面上有一个九宫格布局的抽奖区域,周围八个格子分别放置了不同的奖品名称,中间是一个 “开始抽奖” 的按钮。点击按钮后,抽奖区域的格子会快速滚动,颜色不断变化…...
【人工智能学习笔记 一】 AI分层架构、基本概念分类与产品技术架构
新的一年2025要对AI以及LLM有个强化的学习,所以第一篇先对整体有个大概的认知,一直分不清LLM和AI的关系,在整个体系里的位置,以及AIGC是什么东西,AI AGENT类似豆包等和大语言模型的具体关系是什么,整个AI的…...
windows10 配置使用json server作为图片服务器
步骤1:在vs code中安装json server, npm i -g json-server 注意:需要安装对应版本的json server,不然可能会报错,比如: npm i -g json-server 0.16.3 步骤2:出现如下报错: json-server 不是…...
【Elasticsearch 基础入门】Centos7下Elasticsearch 7.x安装与配置(单机)
Elasticsearch系列文章目录 【Elasticsearch 基础入门】一文带你了解Elasticsearch!!!【Elasticsearch 基础入门】Centos7下Elasticsearch 7.x安装与配置(单机) 目录 Elasticsearch系列文章目录前言单机模式1. 安装 J…...
【MySQL】语言连接
语言连接 一、下载二、mysql_get_client_info1、函数2、介绍3、示例 三、其他函数1、mysql_init2、mysql_real_connect3、mysql_query4、mysql_store_result5、mysql_free_result6、mysql_num_fields7、mysql_num_rows8、mysql_fetch_fields9、mysql_fetch_row10、mysql_close …...
【零拷贝】
目录 一:了解IO基础概念 二:数据流动的层次结构 三:零拷贝 1.传统IO文件读写 2.mmap 零拷贝技术 3.sendFile 零拷贝技术 一:了解IO基础概念 理解CPU拷贝和DMA拷贝 我们知道,操作系统对于内存空间&…...
四、GPIO中断实现按键功能
4.1 GPIO简介 输入输出(I/O)是一个非常重要的概念。I/O泛指所有类型的输入输出端口,包括单向的端口如逻辑门电路的输入输出管脚和双向的GPIO端口。而GPIO(General-Purpose Input/Output)则是一个常见的术语,…...
qt-Quick3D笔记之官方例程Runtimeloader Example运行笔记
qt-Quick3D笔记之官方例程Runtimeloader Example运行笔记 文章目录 qt-Quick3D笔记之官方例程Runtimeloader Example运行笔记1.例程运行效果2.例程缩略图3.项目文件列表4.main.qml5.main.cpp6.CMakeLists.txt 1.例程运行效果 运行该项目需要自己准备一个模型文件 2.例程缩略图…...
IM 即时通讯系统-01-概览
前言 有时候希望有一个 IM 工具,比如日常聊天,或者接受报警信息。 其实主要是工作使用,如果是接收报警等场景,其实DD这种比较符合场景。 那么有没有必要再创造一个DD呢? 答案是如果处于个人的私有化使用࿰…...
二叉树——429,515,116
今天继续做关于二叉树层序遍历的相关题目,一共有三道题,思路都借鉴于最基础的二叉树的层序遍历。 LeetCode429.N叉树的层序遍历 这道题不再是二叉树了,变成了N叉树,也就是该树每一个节点的子节点数量不确定,可能为2&a…...
Baklib构建高效协同的基于云的内容中台解决方案
内容概要 随着云计算技术的飞速发展,内容管理的方式也在不断演变。企业面临着如何在数字化转型过程中高效管理和协同处理内容的新挑战。为应对这些挑战,引入基于云的内容中台解决方案显得尤为重要。 Baklib作为创新型解决方案提供商,致力于…...
MP4基础
一、什么是MP4? MP4是一套用于音频、视频信息的压缩编码标准,由国际标准化组织(ISO)和国际电工委员会(IEC)下属的“动态图像专家组”(Moving Picture Experts Group,即MPEGÿ…...
年化18%-39.3%的策略集 | backtrader通过xtquant连接qmt实战
原创内容第785篇,专注量化投资、个人成长与财富自由。 大年初五,年很快就过完了。 其实就是本身也只是休假一周,但是我们赋予了它太多意义。 周五咱们发布发aitrader v4.1,带了backtraderctp期货的实盘接口: aitra…...
通过Redisson构建延时队列并实现注解式消费
目录 一、序言二、延迟队列实现1、Redisson延时消息监听注解和消息体2、Redisson延时消息发布器3、Redisson延时消息监听处理器 三、测试用例四、结语 一、序言 两个月前接了一个4万的私活,做一个线上商城小程序,在交易过程中不可避免的一个问题就是用户…...
RAG是否被取代(缓存增强生成-CAG)吗?
引言: 本文深入研究一种名为缓存增强生成(CAG)的新技术如何工作并减少/消除检索增强生成(RAG)弱点和瓶颈。 LLMs 可以根据输入给他的信息给出对应的输出,但是这样的工作方式很快就不能满足应用的需要: 因…...
MiniMax:人工智能领域的创新先锋
MiniMax:人工智能领域的创新先锋 在人工智能领域,MiniMax正以其强大的技术实力和创新的模型架构,成为全球关注的焦点。作为一家成立于2021年12月的通用人工智能科技公司,MiniMax专注于开发多模态、万亿参数的MoE(Mixt…...
pytorch基于GloVe实现的词嵌入
PyTorch 实现 GloVe(Global Vectors for Word Representation) 的完整代码,使用 中文语料 进行训练,包括 共现矩阵构建、模型定义、训练和测试。 1. GloVe 介绍 基于词的共现信息(不像 Word2Vec 使用滑动窗口预测&…...
Unity实现按键设置功能代码
一、前言 最近在学习unity2D,想做一个横版过关游戏,需要按键设置功能,让用户可以自定义方向键与攻击键等。 自己写了一个,总结如下。 二、界面效果图 这个是一个csv文件,准备第一列是中文按键说明,第二列…...
C++ 入门速通-第3章【黑马】
内容来源于:黑马 集成开发环境:CLion 先前学习完了C第1章的内容: C 入门速通-第1章【黑马】-CSDN博客 C 入门速通-第2章【黑马】-CSDN博客 下面继续学习第3章: 数组: 字符数组: 多维数组: …...
JavaScript 中的 CSS 与页面响应式设计
JavaScript 中的 CSS 与页面响应式设计 JavaScript 中的 CSS 与页面响应式设计1. 引言2. JavaScript 与 CSS 的基本概念2.1 CSS 的作用2.2 JavaScript 的作用3. 动态控制样式:JavaScript 修改 CSS 的方法3.1 使用 `document.styleSheets` API3.2 使用 `classList` 修改类3.3 使…...
100.3 AI量化面试题:解释配对交易(Pairs Trading)的原理,并说明如何选择配对股票以及设计交易信号
目录 0. 承前1. 配对交易基本原理1.1 什么是配对交易1.2 基本假设 2. 配对选择方法2.1 相关性分析2.2 协整性检验 3. 价差计算方法3.1 简单价格比率3.2 回归系数法 4. 交易信号设计4.1 标准差方法4.2 动态阈值方法 5. 风险管理5.1 止损设计5.2 仓位管理 6. 策略评估6.1 回测框架…...
[SAP ABAP] Debug Skill
SAP ABAP Debug相关资料 [SAP ABAP] DEBUG ABAP程序中的循环语句 [SAP ABAP] 静态断点的使用 [SAP ABAP] 在ABAP Debugger调试器中设置断点 [SAP ABAP] SE11 / SE16N 修改标准表(慎用)...