C语言——贪吃蛇
一. 游戏效果
贪吃蛇
二. 游戏背景
起源。1977年,投币式墙壁游戏生产商Gremlin推出了经典的街机游戏《Blockade》,两名玩家要分别控制角色移动,角色会不停长大,而且走过的地方会变成围栏,谁先碰到围栏或碰到自己的身体就算输。
三、游戏开发日志

四、知识准备
4.1 Win32 API
Windows 这个多作业系统除了协调应⽤程序的执⾏、分配内存、管理资源之外, 它同时也是⼀个很⼤的服务中⼼,调⽤这个服务中⼼的各种服务(每⼀种服务就是⼀个函数),可以帮应⽤程式达到开启 视窗、描绘图形、使⽤周边设备等⽬的,由于这些函数服务的对象是应⽤程序(Application), 所以便 称之为 Application Programming Interface, 简称 API 函数。 WIN32 API也就是Microsoft Windows 32位平台的应⽤程序编程接⼝。
4.2 控制台程序
//控制台窗口设置
system("mode con cols=100 lines=35");
system("title 贪吃蛇"); 4.3 控制台屏幕上的坐标COORD
COORD 是Windows API中定义的⼀种结构,表⽰⼀个字符在控制台屏幕上的坐标
typedef struct _COORD {
SHORT X;
SHORT Y;
} COORD, *PCOORD; 4.4 GetStdHandle
GetStdHandle是⼀个Windows API函数。它⽤于从⼀个特定的标准设备(标准输⼊、标准输出或标准错误)中取得⼀个句柄(⽤来标识不同设备的数值),使⽤这个句柄可以操作设备。
HANDLE hOutput = NULL;
//获取标准输出的句柄(⽤来标识不同设备的数值)
hOutput = GetStdHandle(STD_OUTPUT_HANDLE); 4.5 GetConsoleCursorInfo
检索有关指定控制台屏幕缓冲区的光标⼤⼩和可⻅性的信息
HANDLE hOutput = NULL;
//获取标准输出的句柄(⽤来标识不同设备的数值)
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(hOutput, &CursorInfo);//获取控制台光标信息 4.5.1 CONSOLE_CURSOR_INFO
typedef struct _CONSOLE_CURSOR_INFO {
DWORD dwSize;
BOOL bVisible;
} CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO; (1) dwSize,由光标填充的字符单元格的百分⽐。 此值介于1到100之间。 光标外观会变化,范围从完全填充单元格到单元底部的⽔平线条。(2) bVisible,游标的可⻅性。 如果光标可⻅,则此成员为 TRUE。
CursorInfo.bVisible = false; //隐藏控制台光标 5.6 SetConsoleCursorInfo
设置指定控制台屏幕缓冲区的光标的⼤⼩和可⻅性。
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
//影藏光标操作
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(hOutput, &CursorInfo);//获取控制台光标信息
CursorInfo.bVisible = false; //隐藏控制台光标
SetConsoleCursorInfo(hOutput, &CursorInfo);//设置控制台光标状态 5.7 SetConsoleCursorPosition
设置指定控制台屏幕缓冲区中的光标位置,我们将想要设置的坐标信息放在COORD类型的pos中,调 ⽤SetConsoleCursorPosition函数将光标位置设置到指定的位置。COORD pos = { 10, 5}; HANDLE hOutput = NULL; //获取标准输出的句柄(⽤来标识不同设备的数值) hOutput = GetStdHandle(STD_OUTPUT_HANDLE); //设置标准输出上光标的位置为pos SetConsoleCursorPosition(hOutput, pos);
这里我们可以将SetPos:封装⼀个设置光标位置的函数
//设置光标的坐标
void SetPos(short x, short y)
{
COORD pos = { x, y };
HANDLE hOutput = NULL;
//获取标准输出的句柄(⽤来标识不同设备的数值)
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
//设置标准输出上光标的位置为pos
SetConsoleCursorPosition(hOutput, pos);
} 5.8 GetAsyncKeyState
获取按键情况,将键盘上每个键的虚拟键值传递给函数,函数通过返回值来分辨按键的状态。返回值是short类型,在上⼀次调⽤ GetAsyncKeyState 函数后,如果 返回的16位的short数据中,最⾼位是1,说明按键的状态是按下,如果最⾼是0,说明按键的状态是抬起;如果最低位被置为1则说明,该按键被按过,否则为0。
#define KEY_PRESS(VK) ( (GetAsyncKeyState(VK) & 0x1) ? 1 : 0 ) 5.9 宽字符打印
5.9.1 setlocale函数
char* setlocale (int category, const char* locale); setlocale 函数⽤于修改当前地区,可以针对⼀个类项修改,也可以针对所有类项。 setlocale 的第⼀个参数如果是LC_ALL,就会影响所有的类项。
setlocale(LC_ALL, "C"); 当地区设置为"C"时,库函数按正常⽅式执⾏.
setlocale(LC_ALL, " ");//切换到本地环境 宽字符的打印如下:
#include <stdio.h>
#include<locale.h>
int main() {
setlocale(LC_ALL, "");
wchar_t ch1 = L'●';
wprintf(L"%c\n", ch1);
return 0;
} 五、游戏实现
5.1 游戏逻辑主体
#define _CRT_SECURE_NO_WARNINGS
#include"snake.h"
#include<locale.h>
#include<stdio.h>
int main()
{char ch;setlocale(LC_ALL, "");//切换到本地环境,支持宽字符srand((unsigned int)time(NULL));do{Snake snake = { 0 };GameInit(&snake);GameRun(&snake);GameOver(&snake);printf("小垃圾还要再来吗?是:Y,否:N\n");ch = getchar();getchar();} while (ch == 'y' || ch == 'Y');return 0;
}
5.2 游戏初始化实现
#define _CRT_SECURE_NO_WARNINGS
#include"snake.h"#define WALL L'□'
#define BODY L'●'
#define FOOD L'█'
void SetPos(short x, short y)
{COORD pos = { x, y };HANDLE hOutput = NULL;//获取标准输出的句柄(⽤来标识不同设备的数值)hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//设置标准输出上光标的位置为posSetConsoleCursorPosition(hOutput, pos);
}
void WelcomeToGame()
{SetPos(40, 13);printf("欢迎来到贪吃蛇小游戏");SetPos(42, 22);system("pause");//会显示按任意键继续的信息,按任意键后继续执行下一步system("cls");SetPos(25, 12);printf("↑ . ↓ . ← . → 分别控制蛇的移动, F3为加速,F4为减速\n");SetPos(42, 22);system("pause");//会显示按任意键继续的信息,按任意键后继续执行下一步system("cls");/*getchar();*/}
void CreateMap()
{SetPos(0,0);int i = 0;for(i=0;i<58;i=i+2){wprintf(L"%c", WALL);}SetPos(0, 26);for (i = 0; i < 58; i = i + 2){wprintf(L"%c", WALL);}for (i = 1; i <26; i++){SetPos(0, i);wprintf(L"%c", WALL);}for (i = 1; i < 26; i++){SetPos(56, i);wprintf(L"%c", WALL);}/*getchar();*/
}void InitSnake(Snake* snake)
{//初始化蛇身for (int i = 0; i < 5; i++){SnakeNode* node = (SnakeNode*)malloc(sizeof(SnakeNode));node->x = 24 + 2 * i;node->y = 15;node->next = NULL;if (snake->pSnake== NULL){snake->pSnake= node;}else{node->next = snake->pSnake;snake->pSnake = node;}}SnakeNode* cur = snake->pSnake;while (cur){int x = cur->x;int y = cur->y;SetPos(x, y);wprintf(L"%c", BODY);cur = cur->next;}snake->status = RUN;snake->dir = RIGHT;snake->FoodWeight = 10;snake->pFood = NULL;snake->score = 0;snake->SleepTime = 200;
}
void CreateFood(Snake* snake)
{int x = 0;int y = 0;again:do{x = rand() % 53 + 2;y = rand() % 24 + 1;} while (x % 2 != 0);SnakeNode* cur = snake->pSnake;do{if (x == cur->x && y == cur->y){goto again;}cur = cur->next;} while (cur);SnakeNode* food = (SnakeNode*)malloc(sizeof(SnakeNode));food->x = x;food->y = y;snake->pFood = food;SetPos(x, y);wprintf(L"%c", FOOD);/*getchar();*/}void GameInit(Snake* snake)
{//控制台窗口设置system("mode con cols=100 lines=35");system("title 贪吃蛇");//隐藏光标HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);CONSOLE_CURSOR_INFO CursorInfo;GetConsoleCursorInfo(hOutput, &CursorInfo);//获取控制台光标信息CursorInfo.bVisible = false; //隐藏控制台光标SetConsoleCursorInfo(hOutput, &CursorInfo);//设置控制台光标状态//打印欢迎界面WelcomeToGame();//创建地图CreateMap();//初始化贪吃蛇InitSnake(snake);//创建食物CreateFood(snake);
}
5.3 游戏运行实现
void PrintHelpInfo()
{SetPos(60, 13);printf("1. 不能穿墙不能咬到自己\n");SetPos(60, 14);printf("2.↑.↓.←.→分别控制蛇的移动\n");SetPos(60, 15);printf("3. F3为加速,F4为减速\n");SetPos(60, 16);printf("4. ESC-退出,空格-暂停\n");
}void Pause()
{while (1){Sleep(200);if (KEY_PRESS(VK_SPACE) == 1){break;}}}
void EatFood(Snake* snake, SnakeNode* snakenext)
{snakenext->next = snake->pSnake;snake->pSnake = snakenext;SnakeNode* cur = snake->pSnake;while (cur){SetPos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}free(snake->pFood);snake->pFood = NULL;CreateFood(snake);}
void NoEatFood(Snake* snake, SnakeNode* snakenext)
{snakenext->next = snake->pSnake;snake->pSnake = snakenext;SnakeNode* cur = snake->pSnake;while (cur->next->next){SetPos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}SetPos(cur->x, cur->y);wprintf(L"%lc", BODY);SetPos(cur->next->x, cur->next->y);printf(" ");free(cur->next);cur->next = NULL;
}void SnakeMove(Snake* snake)
{SnakeNode* snakenext = (SnakeNode*)malloc(sizeof(SnakeNode));if (snake->dir == UP){snakenext->x = snake->pSnake->x;snakenext->y = snake->pSnake->y -1;snakenext->next = NULL;}else if (snake->dir == DOWN){snakenext->x = snake->pSnake->x;snakenext->y = snake->pSnake->y +1;snakenext->next = NULL;}if (snake->dir == LEFT){snakenext->x = snake->pSnake->x-2;snakenext->y = snake->pSnake->y ;snakenext->next = NULL;}if (snake->dir == RIGHT){snakenext->x = snake->pSnake->x + 2;snakenext->y = snake->pSnake->y;snakenext->next = NULL;}//判断下一个节点是否为食物if (snakenext->x == snake->pFood->x && snakenext->y == snake->pFood->y){EatFood(snake,snakenext);//吃食物snake->score += snake->FoodWeight;}else{NoEatFood(snake,snakenext);//不吃食物}//碰撞检测if (snake->pSnake->x == 0 || snake->pSnake->x == 56 || snake->pSnake->y == 0 || snake->pSnake->y == 26){snake->status = KILL_BY_WALL;}SnakeNode* cur = snake->pSnake->next;while (cur){if (cur->x == snake->pSnake->x && cur->y == snake->pSnake->y){snake->status = KILL_BY_SELF;}cur = cur->next;}
}void GameRun(Snake* snake)
{//打印帮助信息PrintHelpInfo();do{SetPos(60, 8);printf("游戏总得分:%5d ", snake->score);SetPos(60, 9);printf("每个食物的分数:%2d ", snake->FoodWeight);if (KEY_PRESS(VK_UP) == 1&&snake->dir!=DOWN){snake->dir = UP;}else if (KEY_PRESS(VK_DOWN) == 1 && snake->dir != UP){snake->dir = DOWN;}else if (KEY_PRESS(VK_RIGHT) == 1 && snake->dir != LEFT){snake->dir = RIGHT;}else if (KEY_PRESS(VK_LEFT) == 1 && snake->dir != RIGHT){snake->dir =LEFT;}else if (KEY_PRESS(VK_F3) == 1){if (snake->SleepTime>=80){snake->SleepTime -= 30;snake->FoodWeight += 2;}}else if (KEY_PRESS(VK_F4) == 1){if (snake->SleepTime<=320){snake->SleepTime += 30;snake->FoodWeight -= 2;}}else if (KEY_PRESS(VK_ESCAPE) == 1){snake->status = OVER;break;}else if (KEY_PRESS(VK_SPACE) == 1){Pause();}SnakeMove(snake);Sleep(snake->SleepTime);//每一帧停0.2s} while (snake->status==RUN);
}
5.4 游戏结束实现
void GameOver(Snake* snake)
{switch (snake->status){case KILL_BY_WALL:SetPos(20, 15);printf("你已经撞墙了,小垃圾!\n");break;case KILL_BY_SELF:SetPos(20, 15);printf("你已经自杀了,小垃圾!\n");break;case OVER:SetPos(20, 15);printf("你退出游戏了,小垃圾!\n");break;}SetPos(0, 29);} 六、 完整代码
6.1 snake.h
#define _CRT_SECURE_NO_WARNINGS
#include<stdbool.h>
#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
#include<time.h>
#define KEY_PRESS(VK) ( (GetAsyncKeyState(VK) & 0x1) ? 1 : 0 )
enum direction{UP = 1, DOWN, LEFT, RIGHT};//蛇的方向
enum game_status{RUN,KILL_BY_WALL,KILL_BY_SELF,OVER};typedef struct SnakeNode
{int x;int y;struct SnakeNode* next;
}SnakeNode;typedef struct Snake
{SnakeNode* pSnake;//指向贪吃蛇头节点SnakeNode* pFood;//指向食物的节点int score;int FoodWeight;int SleepTime;enum direction dir;//蛇的方向enum game_status status;//游戏状态
}Snake;
void GameInit(Snake*snake);
void WelcomeToGame();
void CreateMap();
void InitSnake(Snake* snake);
void CreateFood(Snake* snake);
void GameRun(Snake* snake);
void PrintHelpInfo();
void Pause();
void SnakeMove(Snake* snake);void EatFood(Snake* snake,SnakeNode*snakenext);
void NoEatFood(Snake* snake, SnakeNode* snakenext);
void GameOver(Snake* snake); 6.2 snake.c
#define _CRT_SECURE_NO_WARNINGS
#include"snake.h"#define WALL L'□'
#define BODY L'●'
#define FOOD L'█'
void SetPos(short x, short y)
{COORD pos = { x, y };HANDLE hOutput = NULL;//获取标准输出的句柄(⽤来标识不同设备的数值)hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//设置标准输出上光标的位置为posSetConsoleCursorPosition(hOutput, pos);
}
void WelcomeToGame()
{SetPos(40, 13);printf("欢迎来到贪吃蛇小游戏");SetPos(42, 22);system("pause");//会显示按任意键继续的信息,按任意键后继续执行下一步system("cls");SetPos(25, 12);printf("↑ . ↓ . ← . → 分别控制蛇的移动, F3为加速,F4为减速\n");SetPos(42, 22);system("pause");//会显示按任意键继续的信息,按任意键后继续执行下一步system("cls");/*getchar();*/}
void CreateMap()
{SetPos(0,0);int i = 0;for(i=0;i<58;i=i+2){wprintf(L"%c", WALL);}SetPos(0, 26);for (i = 0; i < 58; i = i + 2){wprintf(L"%c", WALL);}for (i = 1; i <26; i++){SetPos(0, i);wprintf(L"%c", WALL);}for (i = 1; i < 26; i++){SetPos(56, i);wprintf(L"%c", WALL);}/*getchar();*/
}void InitSnake(Snake* snake)
{//初始化蛇身for (int i = 0; i < 5; i++){SnakeNode* node = (SnakeNode*)malloc(sizeof(SnakeNode));node->x = 24 + 2 * i;node->y = 15;node->next = NULL;if (snake->pSnake== NULL){snake->pSnake= node;}else{node->next = snake->pSnake;snake->pSnake = node;}}SnakeNode* cur = snake->pSnake;while (cur){int x = cur->x;int y = cur->y;SetPos(x, y);wprintf(L"%c", BODY);cur = cur->next;}snake->status = RUN;snake->dir = RIGHT;snake->FoodWeight = 10;snake->pFood = NULL;snake->score = 0;snake->SleepTime = 200;
}
void CreateFood(Snake* snake)
{int x = 0;int y = 0;again:do{x = rand() % 53 + 2;y = rand() % 24 + 1;} while (x % 2 != 0);SnakeNode* cur = snake->pSnake;do{if (x == cur->x && y == cur->y){goto again;}cur = cur->next;} while (cur);SnakeNode* food = (SnakeNode*)malloc(sizeof(SnakeNode));food->x = x;food->y = y;snake->pFood = food;SetPos(x, y);wprintf(L"%c", FOOD);/*getchar();*/}void GameInit(Snake* snake)
{//控制台窗口设置system("mode con cols=100 lines=35");system("title 贪吃蛇");//隐藏光标HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);CONSOLE_CURSOR_INFO CursorInfo;GetConsoleCursorInfo(hOutput, &CursorInfo);//获取控制台光标信息CursorInfo.bVisible = false; //隐藏控制台光标SetConsoleCursorInfo(hOutput, &CursorInfo);//设置控制台光标状态//打印欢迎界面WelcomeToGame();//创建地图CreateMap();//初始化贪吃蛇InitSnake(snake);//创建食物CreateFood(snake);
}void PrintHelpInfo()
{SetPos(60, 13);printf("1. 不能穿墙不能咬到自己\n");SetPos(60, 14);printf("2.↑.↓.←.→分别控制蛇的移动\n");SetPos(60, 15);printf("3. F3为加速,F4为减速\n");SetPos(60, 16);printf("4. ESC-退出,空格-暂停\n");
}void Pause()
{while (1){Sleep(200);if (KEY_PRESS(VK_SPACE) == 1){break;}}}
void EatFood(Snake* snake, SnakeNode* snakenext)
{snakenext->next = snake->pSnake;snake->pSnake = snakenext;SnakeNode* cur = snake->pSnake;while (cur){SetPos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}free(snake->pFood);snake->pFood = NULL;CreateFood(snake);}
void NoEatFood(Snake* snake, SnakeNode* snakenext)
{snakenext->next = snake->pSnake;snake->pSnake = snakenext;SnakeNode* cur = snake->pSnake;while (cur->next->next){SetPos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}SetPos(cur->x, cur->y);wprintf(L"%lc", BODY);SetPos(cur->next->x, cur->next->y);printf(" ");free(cur->next);cur->next = NULL;
}void SnakeMove(Snake* snake)
{SnakeNode* snakenext = (SnakeNode*)malloc(sizeof(SnakeNode));if (snake->dir == UP){snakenext->x = snake->pSnake->x;snakenext->y = snake->pSnake->y -1;snakenext->next = NULL;}else if (snake->dir == DOWN){snakenext->x = snake->pSnake->x;snakenext->y = snake->pSnake->y +1;snakenext->next = NULL;}if (snake->dir == LEFT){snakenext->x = snake->pSnake->x-2;snakenext->y = snake->pSnake->y ;snakenext->next = NULL;}if (snake->dir == RIGHT){snakenext->x = snake->pSnake->x + 2;snakenext->y = snake->pSnake->y;snakenext->next = NULL;}//判断下一个节点是否为食物if (snakenext->x == snake->pFood->x && snakenext->y == snake->pFood->y){EatFood(snake,snakenext);//吃食物snake->score += snake->FoodWeight;}else{NoEatFood(snake,snakenext);//不吃食物}//碰撞检测if (snake->pSnake->x == 0 || snake->pSnake->x == 56 || snake->pSnake->y == 0 || snake->pSnake->y == 26){snake->status = KILL_BY_WALL;}SnakeNode* cur = snake->pSnake->next;while (cur){if (cur->x == snake->pSnake->x && cur->y == snake->pSnake->y){snake->status = KILL_BY_SELF;}cur = cur->next;}
}void GameRun(Snake* snake)
{//打印帮助信息PrintHelpInfo();do{SetPos(60, 8);printf("游戏总得分:%5d ", snake->score);SetPos(60, 9);printf("每个食物的分数:%2d ", snake->FoodWeight);if (KEY_PRESS(VK_UP) == 1&&snake->dir!=DOWN){snake->dir = UP;}else if (KEY_PRESS(VK_DOWN) == 1 && snake->dir != UP){snake->dir = DOWN;}else if (KEY_PRESS(VK_RIGHT) == 1 && snake->dir != LEFT){snake->dir = RIGHT;}else if (KEY_PRESS(VK_LEFT) == 1 && snake->dir != RIGHT){snake->dir =LEFT;}else if (KEY_PRESS(VK_F3) == 1){if (snake->SleepTime>=80){snake->SleepTime -= 30;snake->FoodWeight += 2;}}else if (KEY_PRESS(VK_F4) == 1){if (snake->SleepTime<=320){snake->SleepTime += 30;snake->FoodWeight -= 2;}}else if (KEY_PRESS(VK_ESCAPE) == 1){snake->status = OVER;break;}else if (KEY_PRESS(VK_SPACE) == 1){Pause();}SnakeMove(snake);Sleep(snake->SleepTime);//每一帧停0.2s} while (snake->status==RUN);
}void GameOver(Snake* snake)
{switch (snake->status){case KILL_BY_WALL:SetPos(20, 15);printf("你已经撞墙了,小垃圾!\n");break;case KILL_BY_SELF:SetPos(20, 15);printf("你已经自杀了,小垃圾!\n");break;case OVER:SetPos(20, 15);printf("你退出游戏了,小垃圾!\n");break;}SetPos(0, 29);}
6.3 text.c
#define _CRT_SECURE_NO_WARNINGS
#include"snake.h"
#include<locale.h>
#include<stdio.h>
int main()
{char ch;setlocale(LC_ALL, "");//切换到本地环境,支持宽字符srand((unsigned int)time(NULL));do{Snake snake = { 0 };GameInit(&snake);GameRun(&snake);GameOver(&snake);printf("小垃圾还要再来吗?是:Y,否:N\n");ch = getchar();getchar();} while (ch == 'y' || ch == 'Y');return 0;
}
相关文章:
C语言——贪吃蛇
一. 游戏效果 贪吃蛇 二. 游戏背景 贪吃蛇是久负盛名的游戏,它也和俄罗斯⽅块,扫雷等游戏位列经典游戏的⾏列。 贪吃蛇起源于1977年的投币式墙壁游戏《Blockade》,后移植到各种平台上。具体如下: 起源。1977年,投币式…...
Android sqlite 使用简介
进行Android应用开发时经常会用到数据库。Android系统支持sqlite数据库,在app开发过程中很容易通过SQLiteOpenHelper使用数据库,SQLiteOpenHelper依赖于Context对象,但是基于uiatomator1.0和Java程序等无法获取Context的应用如何使用数据库呢…...
UE地形系统材质混合实现和Shader生成分析(UE5 5.2)
前言 随着电脑和手机硬件性能越来越高,游戏越来越追求大世界,而大世界非常核心的一环是地形系统,地形系统两大构成因素:高度和多材质混合,此篇文章介绍下UE4/UE5 地形的材质混合方案----基于WeightMap混合。 材质层 …...
Git分支与Git标签的介绍及其场景应用
目录 一、Git分支 1.1 定义 1.2 基本概念 1.3 特点与优势 1.4 Git分支操作命令 1.4.1 查看分支 1.4.2 创建分支 1.4.3 删除分支 1.4.4 切换分支 1.4.5 创建并切换到新建分支 1.5 场景应用 1.5.1 前期准备 1.5.2 具体操作 二、Git标签 2.1 定义 2.2 类型 2.3 标…...
Three.js——基于原生WebGL封装运行的三维引擎
文章目录 前言一、什么是WebGL?二、Three.js 特性 前言 Three.js中文官网 Three.js是基于原生WebGL封装运行的三维引擎,在所有WebGL引擎中,Three.js是国内文资料最多、使用最广泛的三维引擎。既然Threejs是一款WebGL三维引擎,那么…...
第八章认识Express框架
目录 Express模块化路由 基本概述 基本使用 基本构建 案例项目 Express接收请求参数 基本概述 基本类别 Express接收GET请求参数 Express接收POST请求参数 Express接收路由参数 Express模块化路由 基本概述 在Express中,路由是指确定应用程序如何响应对…...
【K8s集群离线安装-kubeadm】
1、kubeadm概述 kubeadm是官方社区推出的一个用于快速部署kubernetes集群的工具。这个工具能通过两条指令快速完成一个kubernetes集群的部署。 2、环境准备 2.1 软件环境 软件版本操作系统CentOS 7Docker19.03.13K8s1.23 2.2 服务器 最小硬件配置:2核CPU、2G内存…...
python工具CISCO ASA设备任意文件读取
python漏洞利用 构造payload: /CSCOT/translation-table?typemst&textdomain/%2bCSCOE%2b/portal_inc.lua&default-language&lang../漏洞证明: 文笔生疏,措辞浅薄,望各位大佬不吝赐教,万分感谢。 免…...
TCP关闭的两种方法概述
一个TCP需要经过四次挥手才可以关闭连接,能够开启四次挥手的函数有两个: int close(int sockfd) int shutdown(int sockfd,int howto) 接下来就分别讲解一下这两个函数。 close()函数 函数原型 #include<unistd.h> int close(int sockfd)这个函…...
Git的Hooks机制
参考文章:详解如何在项目中使用git Hooks(husky、yorkie) git hooks钩子 git hooks是一些自定义的脚本,用于控制git工作的流程,分为客户端钩子和服务端钩子。 ~/work/step-time/ [master*] ll .git/hooks total…...
代码随想录算法训练营第四十九天|121. 买卖股票的最佳时机、122. 买卖股票的最佳时机 II
第九章 动态规划part10 121. 买卖股票的最佳时机 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最…...
Rust教程6:并发编程和线程通信
文章目录 线程初步join方法线程通信 Rust系列:初步⚙所有权⚙结构体和枚举类⚙函数进阶⚙泛型和特征 线程初步 在Rust中,开启多线程进行并发编程,只需调用thread::spawn,但这里有一个坑点,即spawn函数只有一个传入参…...
JVM在线分析-监控工具(jps, jstat, jstatd)
参考官方文档(jdk11) https://docs.oracle.com/en/java/javase/11/tools/troubleshooting-tools-and-commands.html#GUID-CB44BFBA-E5F9-4D80-8EE8-28E9F16BC451 1. 监控工具(jps, jstat, jstatd) jps -q Suppresses the output of the class name, J…...
Console LDAP 配置解密
之前通过短视频向大家介绍了 Console 如何集成 LDAP,但很多小伙伴反映按照视频里的配置后不成功。今天就结合小伙伴们反映的问题来跟大家详细介绍一下。 Console LDAP 完整的配置参数如下: 名称类型说明hoststringLDAP 服务器地址portintLDAP 服务器端口…...
node插件MongoDB(三)—— 库mongoose 的使用和数据类型(一)
前言 提示:使用mongoose 的前提是你安装了node和 MongoDB。 mongoose 官网文档:http://mongoosejs.net/docs/index.html 文章目录 前言一、安装二、基本使用1. 打开bin目录的mongod.exe文件2. 基本使用的代码(连接mongodb 服务)3.…...
基础(二)
基础(二) 字符串型 C风格:char 变量名[] “字符串值”; C风格:string 变量名 “字符串值” #include <iostream> using namespace std; #include <string>int main() {// C风格char str1[] "h…...
思维模型 目标效应
本系列文章 主要是 分享 思维模型,涉及各个领域,重在提升认知。明确目标,激发内在动机。 1 目标效应的应用 1.1 目标效应在教育领域的应用-棉花糖实验 美国斯坦福大学心理学系的教授米歇尔(Walter Mischel)曾经进行了…...
【从0到1设计一个网关】性能优化---Netty线程数配置与JVM参数配置
文章目录 Netty线程介绍Netty实战配置JVM参数与ZGCJVM与ZGC调优Netty线程介绍 在Netty中有两个比较重要的线程概念,一个是BOSS线程,一个是Woker线程。 Boss线程组: Boss线程组通常负责处理接受客户端连接的工作,即处理ServerSocketChannel的连接事件。 Boss线程会监听并接…...
node插件MongoDB(五)—— 库mongoose 的模块化(五)
文章目录 一、使用mongoose 模块化的原因二、准备工作2. 启动mongo.exe 和mongod.exe 两个程序连接数据库 三、基本模块的拆分1、基本逻辑2、代码3、代码图示说明 四、在index.js 中进一步的拆分1.拆分原因2.新建model文件夹存储文档的结构对象3.代码4.代码实际演示和注意点 一…...
Windows server 2008 R2 IIS搭建ASP网站教程
一、安装应用程序服务器 提示安装成功 二、添加角色服务asp 三、asp网站配置 放入源码 设置网站首页为index.asp: 设置应用程序池 四、设置网站目录属性 五、access数据库连接配置 Cd c:\Windows\System32\inetsrv appcmd list apppool /xml | appcmd set apppool /…...
Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...
Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...
Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?
Pod IP 的本质与特性 Pod IP 的定位 纯端点地址:Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址(如 10.244.1.2)无特殊名称:在 Kubernetes 中,它通常被称为 “Pod IP” 或 “容器 IP”生命周期:与 Pod …...
鸿蒙HarmonyOS 5军旗小游戏实现指南
1. 项目概述 本军旗小游戏基于鸿蒙HarmonyOS 5开发,采用DevEco Studio实现,包含完整的游戏逻辑和UI界面。 2. 项目结构 /src/main/java/com/example/militarychess/├── MainAbilitySlice.java // 主界面├── GameView.java // 游戏核…...
密码学基础——SM4算法
博客主页:christine-rr-CSDN博客 专栏主页:密码学 📌 【今日更新】📌 对称密码算法——SM4 目录 一、国密SM系列算法概述 二、SM4算法 2.1算法背景 2.2算法特点 2.3 基本部件 2.3.1 S盒 2.3.2 非线性变换 编辑…...
EasyRTC音视频实时通话功能在WebRTC与智能硬件整合中的应用与优势
一、WebRTC与智能硬件整合趋势 随着物联网和实时通信需求的爆发式增长,WebRTC作为开源实时通信技术,为浏览器与移动应用提供免插件的音视频通信能力,在智能硬件领域的融合应用已成必然趋势。智能硬件不再局限于单一功能,对实时…...
