贪吃蛇项目:GameRun与GameEnd部分:游戏的主体运行与善后部分
准备工作:打印得分信息
在进行GameStart之前,我们需要在地图的右侧打印帮助信息,以及目前玩家的得分情况和一个食物在当前速度下的得分情况(加速的状态下按比例增加食物的分数,减速的状态下则相反),至于打印的方法,在上两篇文章中已经介绍完毕,这里我们直接给出实现代码:
void GameIntroduction()
{Set_Pos(65, 10);wprintf(L"↑ ↓ ← →进行移动\n");Set_Pos(65, 11);wprintf(L"退出游戏请按Esc\n");Set_Pos(65, 12);wprintf(L"暂停请按空格\n");Set_Pos(65, 13);wprintf(L"小键盘1,2键加减速\n");
}void ScoreStat(pSnake ps)
{REPOSITION(63, 8);wprintf(L"当前总分数%d", ps->_Socre);REPOSITION(63, 7);wprintf(L"当前速度一个食物分数为%d", ps->_foodWeight);
}void GameRun(pSnake ps)
{GameIntroduction();do{ScoreStat(ps);} while (ps->_Status == OK);
}
打印获得的成绩放在循环里面,则是因为每次玩家按完加减速之后,得分的权重都会改变,要实时更新。而我们的介绍信息则只需要打印一遍。
一,键位检测的实现
在此之前,我们要先定义一个宏:
#define KEY_PRESS(VK) ((GetAsyncKeyState(VK)&0x1) ? 1 : 0)
这里我们只需要知道它能检测键位是否被按过即可,不做过多介绍,如果想更为细节的了解,可以参考官网的解释:getAsyncKeyState 函数 (winuser.h) - Win32 apps | Microsoft Learn
接下来我们用多个if-else语句来实现玩家按下不同键位时的检测:
void GameRun(pSnake ps)
{GameIntroduction();do{ScoreStat(ps);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_NUMPAD1)){if (ps->_SleepTime > 100){ps->_SleepTime -= 50;ps->_foodWeight += 2;}}else if (KEY_PRESS(VK_NUMPAD2)){if (ps->_SleepTime < 500){ps->_SleepTime += 50;ps->_foodWeight -= 2;}}else if (KEY_PRESS(VK_SPACE)){Pause();}else if (KEY_PRESS(VK_ESCAPE)){ps->_Status = END_NOMAL;break;}} while (ps->_Status == OK);
}
这里当玩家按上键时调整蛇的方向为上,但如果此时方向朝下调整方向为上,就会使蛇自己咬住自己。左右方向也是同理。下面为实现的暂停函数(Pause):
void Pause()
{while (!KEY_PRESS(VK_SPACE)){Sleep(200);}
}
当玩家在此按下空格键时,我们结束暂停的状态。
当然,在每次检测完后,用Sleep函数暂停一下,至于暂停的时间,其实就是根据蛇的移动速度来设置:
Sleep(ps->_SleepTime);
二,蛇的移动函数的实现
2.1下一个位置节点的初始化
我们这里使用SnakeMove来命名我们的移动函数。由于我们的链表需要使用malloc开辟,所以我们需要用malloc来开辟蛇的下一个位置的节点,当然在开辟完成后,我们还需要检验开辟是否成功:
pSnakeNode NextNode = (pSnakeNode)malloc(sizeof(SnakeNode));if (NextNode == NULL){perror("malloc():SnakeMove:NextNode");return;}
我们已经知道,控制台的长宽之比为1 :2,所以,如果接下来蛇往左移动,则他的x坐标则需要增加两个字符位置,向上向下则只需要移动y一个字符位置即可:
NextNode->x = ps->_pSnake->x;
NextNode->y = ps->_pSnake->y;
NextNode->next = NULL;
switch (ps->_Dir)
{case RIGHT:{NextNode->x += 2;NextNode->y += 0;break;}case LEFT:{NextNode->x -= 2;NextNode->y += 0;break;}case UP:{NextNode->x += 0;NextNode->y += 1;break;}case DOWN:{NextNode->x += 0;NextNode->y -= 1;break;}
}
2.2判断下一个位置是否为食物
接下来如果下一个位置为食物,或不为食物,我们也需要检测,首先我们设置一个函数NestIsFood来检验下一个位置是否为食物:
int NextIsFood(pSnakeNode psn, pSnake ps)
{return(psn->x == ps->_pFood->x && psn->y == ps->_pFood->y);
}
直接返回值即可,如果下一个位置为食物,我们用EatFood函数将蛇的长度加一,否则我们使用NoFood来让蛇移动一格:
void EatFood(pSnake ps, pSnakeNode psn)
{psn->next = ps->_pSnake;ps->_pSnake = psn;pSnakeNode cur = ps->_pSnake;while (cur){Set_Pos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}ps->_Socre += ps->_foodWeight;free(ps->_pFood);FoodInit(ps);
}
void NoFood(pSnake ps, pSnakeNode psn)
{psn->next = ps->_pSnake;ps->_pSnake = psn;pSnakeNode cur = ps->_pSnake;while (cur->next->next){Set_Pos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}REPOSITION(cur->next->x, cur->next->y);printf(" ");free(cur->next);cur->next = NULL;
}
这里我们说明一下NoFood函数中打印两个空格的原因,因为我们的蛇是通过打印移动的,所以当我们把NextNode节点接到蛇头上时,我们需要把最后一个节点删除,但仔细思考一下,上回打印蛇身的字符是否还会保留,这会使它遗留在屏幕上。所以我们要打印两个空格(因为我们的蛇身为宽字符占两个字节)将其从屏幕上抹除。
2.3判断蛇是否咬住自身或撞墙
这里我们用两个函数KillByWall,KillBySelf来分别表示蛇是否撞墙,蛇是否咬住自己。是否撞墙我们只需要判断蛇头位置是否与墙体位置重合,而是否咬住自己只需要判断蛇头位置是否与自身的其他部分重合:
int KillBySelf(pSnake ps)
{pSnakeNode cur = ps->_pSnake->next;while (cur){if ((ps->_pSnake->x == cur->x) && (ps->_pSnake->y == cur->y)){ps->_Status = KILL_BY_SELF;return 1;}cur = cur->next;}return 0;
}int 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;return 1;}return 0;
}
其实设置为void类型也可以,不过为了区分情况,方便起见,我用返回1或0来区分是否撞墙(咬自己)。
2.4GameRun部分代码
void GameRun(pSnake ps)
{GameIntroduction();do{ScoreStat(ps);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_NUMPAD1)){if (ps->_SleepTime > 100){ps->_SleepTime -= 50;ps->_foodWeight += 2;}}else if (KEY_PRESS(VK_NUMPAD2)){if (ps->_SleepTime < 500){ps->_SleepTime += 50;ps->_foodWeight -= 2;}}else if (KEY_PRESS(VK_SPACE)){Pause();}else if (KEY_PRESS(VK_ESCAPE)){ps->_Status = END_NOMAL;break;}Sleep(ps->_SleepTime);SnakeMove(ps);} while (ps->_Status == OK);
}
2.5SnakeMove部分代码
void SnakeMove(pSnake ps)
{pSnakeNode NextNode = (pSnakeNode)malloc(sizeof(SnakeNode));if (NextNode == NULL){perror("malloc():SnakeMove:NextNode");return;}NextNode->x = ps->_pSnake->x;NextNode->y = ps->_pSnake->y;NextNode->next = NULL;switch (ps->_Dir){case RIGHT:{NextNode->x += 2;NextNode->y += 0;break;}case LEFT:{NextNode->x -= 2;NextNode->y += 0;break;}case UP:{NextNode->x += 0;NextNode->y += 1;break;}case DOWN:{NextNode->x += 0;NextNode->y -= 1;break;}}if (NextIsFood(NextNode,ps)){EatFood(ps, NextNode);}else{NoFood(NextNode,ps);}KillByWall(ps);KillBySelf(ps);
}
三,GameEnd部分
这一部分其实没有什么好说的,因为我们上面的代码已经将蛇的状态信息设置好了,所以我们这里只需要根据上面储存进去的信息来打印我们目前的游戏状态即可:
void GameEnd(pSnake ps)
{pSnakeNode cur = ps->_pSnake;Set_Pos(24, 12);switch (ps->_Status){case END_NOMAL:printf("你主动退出游戏\n");break;case KILL_BY_SELF:printf("你咬到自己了 ,游戏结束!\n");break;case KILL_BY_WALL:printf("你撞墙了,游戏结束!\n");break;}while (cur){pSnakeNode del = cur;cur = cur->next;free(del);}
}
四,完整游戏代码
4.1Snake.h
#pragma once
#include <stdio.h>
#include <stdbool.h>
#include <windows.h>
#include <stdlib.h>
#include <locale.h>
#include <time.h>#define WALL L'□'
#define FOOD L'★'
#define BODY L'●'
#define POS_X 24
#define POS_Y 5#define KEY_PRESS(VK) ((GetAsyncKeyState(VK)&0x1) ? 1 : 0)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 _Socre;//游戏当前获得分数int _foodWeight;//默认每个⻝物10分int _SleepTime;//每⾛⼀步休眠时间
}Snake, * pSnake;enum DIRECTION
{UP = 1,DOWN,LEFT,RIGHT
};enum GAME_STATUS
{OK,//正常运⾏KILL_BY_WALL,//撞墙KILL_BY_SELF,//咬到⾃⼰END_NOMAL//正常结束
};void REPOSITION(short x, short y);//调整输入的光标位置void WelcomeMenu();//设置欢迎与介绍菜单void GameMap();//设置游戏地图void GameIntroduction();//设置在游戏过程中的提醒void GameStart(pSnake ps);//游戏的初始化void SnakeInit(pSnake ps);//蛇身的初始化void FoodInit(pSnake ps);//初始化食物void GameRun(pSnake ps);//游戏主体运行部分void ScoreStat(pSnake ps);//分数统计void Pause();//空格暂停void SnakeMove(pSnake ps);//控制蛇移动的函数int NextIsFood(pSnakeNode psn, pSnake ps);//判断下一个位置是否为食物void EatFood(pSnake ps, pSnakeNode psn);//是食物的情况下吃掉食物void NoFood(pSnakeNode psn, pSnake ps);//非食物的情况下进行移动int KillBySelf(pSnake ps);int KillByWall(pSnake ps);void GameEnd(pSnake ps);
4.2Snake.c
这里面的设置位置函数是REPOSITION(这是我第一遍做成功的代码,至于文章里面Set_Pos是我为了写文章又重新写了一遍代码)。
#include "snake.h"void REPOSITION(short x, short y)
{HANDLE houtput = NULL;houtput = GetStdHandle(STD_OUTPUT_HANDLE);COORD pos = { x,y };SetConsoleCursorPosition(houtput,pos);
}void WelcomeMenu()
{REPOSITION(35, 10);wprintf(L"欢迎来到贪吃蛇小游戏");REPOSITION(35, 20);system("pause");system("cls");REPOSITION(35, 10);wprintf(L"按 ↑ ↓ ← →键操控贪吃蛇移动\n");REPOSITION(35, 11);wprintf(L"按小键盘‘1’或‘2’键加速或减速\n");REPOSITION(35, 12);wprintf(L"Tips:加速吃食物有额外分数加成");REPOSITION(35, 20);system("pause");system("cls");
}void GameMap()
{REPOSITION(0, 0);int i = 0;for (; i < 58; i += 2){wprintf(L"%lc", WALL);}REPOSITION(0, 26);for (i = 0; i < 58; i += 2){wprintf(L"%lc", WALL);}for (i = 1; i < 26; i++){REPOSITION(0, i);wprintf(L"%lc", WALL);}for (i = 1; i < 26; i++){REPOSITION(56, i);wprintf(L"%lc", WALL);}
}void GameIntroduction()
{REPOSITION(65, 10);wprintf(L"↑ ↓ ← →进行移动\n");REPOSITION(65, 11);wprintf(L"退出游戏请按Esc\n");REPOSITION(65, 12);wprintf(L"暂停请按空格\n");REPOSITION(65, 13);wprintf(L"小键盘1,2键加减速\n");
}void GameStart(pSnake ps)
{srand((unsigned int)time(NULL));system("mode con cols=100 lines=30");system("title 贪吃蛇");HANDLE houtput = NULL;houtput = GetStdHandle(STD_OUTPUT_HANDLE);CONSOLE_CURSOR_INFO CursorInfo = { 25,false };SetConsoleCursorInfo(houtput, &CursorInfo);WelcomeMenu();GameMap();SnakeInit(ps);FoodInit(ps);
}void SnakeInit(pSnake ps)
{int i = 0;pSnakeNode cur = NULL;for (i = 0; i < 5; i++){cur = (pSnakeNode)malloc(sizeof(SnakeNode));if (cur == NULL){perror("SnakeInit():malloc()cur:");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){REPOSITION(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}ps->_Dir = RIGHT;ps->_foodWeight = 10;ps->_SleepTime = 300;ps->_Socre = 0;ps->_Status = OK;
}void FoodInit(pSnake ps)
{int x = 0;int y = 0;again:do{x = rand()%53 + 2;y = rand()%24 + 1;} while (x % 2 != 0);pSnakeNode cur = ps->_pSnake;while (cur){if (cur->x == x && cur->y == y)goto again;cur = cur->next;}pSnakeNode cur2 = (pSnakeNode)malloc(sizeof(SnakeNode));if (cur2 == NULL){perror("malloc():FoofInit:cur2:");return;}cur2->next = NULL;cur2->x = x;cur2->y = y;REPOSITION(x, y);wprintf(L"%lc", FOOD);ps->_pFood = cur2;cur2 = NULL;
}void ScoreStat(pSnake ps)
{REPOSITION(63, 8);wprintf(L"当前总分数%d", ps->_Socre);REPOSITION(63, 7);wprintf(L"当前速度一个食物分数为%d", ps->_foodWeight);
}void Pause()
{while (!KEY_PRESS(VK_SPACE)){Sleep(200);}
}int NextIsFood(pSnakeNode psn, pSnake ps)
{return(psn->x == ps->_pFood->x && psn->y == ps->_pFood->y);
}void EatFood(pSnake ps,pSnakeNode psn)
{psn->next = ps->_pSnake;ps->_pSnake = psn;pSnakeNode cur = ps->_pSnake;while (cur){REPOSITION(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}ps->_Socre += ps->_foodWeight;free(ps->_pFood);FoodInit(ps);
}void NoFood(pSnakeNode psn,pSnake ps)
{psn->next = ps->_pSnake;ps->_pSnake = psn;pSnakeNode cur = ps->_pSnake;while (cur->next->next){REPOSITION(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}REPOSITION(cur->next->x, cur->next->y);printf(" ");free(cur->next);cur->next = NULL;
}int 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;return 1;}return 0;
}int KillBySelf(pSnake ps)
{pSnakeNode cur = ps->_pSnake->next;while (cur){if ((ps->_pSnake->x == cur->x)&& (ps->_pSnake->y == cur->y)){ps->_Status = KILL_BY_SELF;return 1;}cur = cur->next;}return 0;
}void SnakeMove(pSnake ps)
{pSnakeNode NextNode = (pSnakeNode)malloc(sizeof(SnakeNode));if (NextNode == NULL){perror("malloc():SnakeMove:NextNode");return;}NextNode->x = ps->_pSnake->x;NextNode->y = ps->_pSnake->y;NextNode->next = NULL;switch (ps->_Dir){case RIGHT:{NextNode->x += 2;NextNode->y += 0;break;}case LEFT:{NextNode->x -= 2;NextNode->y += 0;break;}case UP:{NextNode->x += 0;NextNode->y += 1;break;}case DOWN:{NextNode->x += 0;NextNode->y -= 1;break;}}if (NextIsFood(NextNode,ps)){EatFood(ps, NextNode);}else{NoFood(NextNode,ps);}KillByWall(ps);KillBySelf(ps);
}void GameRun(pSnake ps)
{GameIntroduction();do{ScoreStat(ps);if (KEY_PRESS(VK_UP) && ps->_Dir != DOWN){ps->_Dir = DOWN;}else if (KEY_PRESS(VK_DOWN) && ps->_Dir != UP){ps->_Dir = UP;}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_NUMPAD1)){if (ps->_SleepTime > 100){ps->_SleepTime -= 50;ps->_foodWeight += 2;}}else if (KEY_PRESS(VK_NUMPAD2)){if (ps->_SleepTime < 500){ps->_SleepTime += 50;ps->_foodWeight -= 2;}}else if (KEY_PRESS(VK_SPACE)){Pause();}else if (KEY_PRESS(VK_ESCAPE)){ps->_Status = END_NOMAL;break;}Sleep(ps->_SleepTime);SnakeMove(ps);} while (ps->_Status == OK);
}void GameEnd(pSnake ps)
{pSnakeNode cur = ps->_pSnake;REPOSITION(24, 12);switch (ps->_Status){case END_NOMAL:printf("你主动退出游戏\n");break;case KILL_BY_SELF:printf("你咬到自己了 ,游戏结束!\n");break;case KILL_BY_WALL:printf("你撞墙了,游戏结束!\n");break;}while (cur){pSnakeNode del = cur;cur = cur->next;free(del);}
}
4.3test.c
#include "snake.h"void test()
{int ch = 0;do{Snake snake = { 0 };GameStart(&snake);//游戏初始化GameRun(&snake);//游戏运行GameEnd(&snake);//游戏的善后处理REPOSITION(20, 15);printf("再来一局吗?(y/n):");ch = getchar();getchar();} while (ch == 'y');system("cls");
}int main()
{setlocale(LC_ALL, "");test();return 0;
}
贪吃蛇的内容到这里就完结了,至于下一次更新要到7月10号左右了(一是过暑假了想摸会鱼,二是在c语言准备开数据结构的新坑),我们下篇文章见。

相关文章:
贪吃蛇项目:GameRun与GameEnd部分:游戏的主体运行与善后部分
准备工作:打印得分信息 在进行GameStart之前,我们需要在地图的右侧打印帮助信息,以及目前玩家的得分情况和一个食物在当前速度下的得分情况(加速的状态下按比例增加食物的分数,减速的状态下则相反)…...
mysql索引、事务以及存储引擎
目录 一、索引 1)索引定义 2)工作方式 3)创建索引的依据 4)索引类型 1、index普通索引 2、unique唯一索引 3、主键索引 4、多列组合索引 5、全文索引 5)删除索引 6)查看索引 7)索…...
idea添加文档注释
一、easy javadoc插件 在settings的plugins中下载easy javadoc插件。 安装完成后重启idea,再次打开settings界面。会出现easyDoc相关配置。 二、设置模版以及使用 类描述模版参考设置: /** * 类描述 -> * * Author: ywz * Date: $Date$ */ 方法描述…...
python函数练习
1、编写函数,传入N,求123…N的和 def s_sum(num):i 1sum1 0while i < num:sum1 ii 1return sum1num int(input(请输入一个整数:)) print(和为:,s_sum(num))2、编写一个函数,定义一个列表,求列表中的最大值 d…...
基于PHP的奶茶商城系统
有需要请加文章底部Q哦 可远程调试 基于PHP的奶茶商城系统 一 介绍 此奶茶商城系统基于原生PHP开发,数据库mysql,ajax实现数据交换。系统角色分为用户和管理员。系统在原有基础上添加了糖度的选择。 技术栈 phpmysqlajaxphpstudyvscode 二 功能 用户…...
物联网“此用户无权修改接入点名称设置”解决方案
根本原因apns-conf.xml里面没有 符合 物理网卡 的配置 可以先加一个APN试一下,看看默认的MCC和MNC是什么 然后在”命令行“查询一下 adb shell sqlite3 /data/user_de/0/com.android.providers.telephony/databases/telephony.db "select * from carriers wh…...
网工常见面试题
1-10题 1.介绍TCP/IP四层、五层模型作用及每层包含的协议 TCP/IP四层模型 应用层: 作用:直接与应用程序交互,定义了应用程序如何通过网络发送数据。包含协议:HTTP(网页浏览)、FTP(文件传输&…...
SQL实现UUIDv7
当我们选择数据库的主键类型时,通常会考虑自增数字或者 UUID。但是这两种类型都有优缺点,自增字段简单有序,性能良好,最大的问题是无法保证全局唯一性,分布式场景受限;UUID 具有全局唯一性,适合…...
2024期权交易佣金手续费最低是多少?期权交易有哪些成本?
显性成本 期权交易的显性成本包含期权交易的佣金和交易所费用,分别支付给券商和交易所,统一由券商代收。 佣金 期权佣金是期权交易时支付给券商的费用,佣金通常以交易金额的一定比例计算,可以是固定费用,也可以是滑…...
合合信息智能文档抽取:赋能不良资产管理行业的数字化转型
官.网地址:合合TextIn - 合合信息旗下OCR云服务产品 随着数字化浪潮的汹涌澎湃,全球各行各业正经历着前所未有的变革。人工智能技术的快速发展,以其独特的创新能力和应用潜力,正在深刻地改变着业务模式,推动产业效率的…...
【别再用Excel了!】这款免费可视化工具能帮你轻松提升效率
现代数据分析和展示的需求已经远远超出了传统工具的能力,尤其是在需要快速、直观和高效地处理复杂数据的情况下。山海鲸可视化通过其强大的功能和易用性,成为了设计师以及各类新手用户的理想选择。下面我就以一个可视化设计师的角度,和大家简…...
python holidays获取中国节日
在Python中,holidays库是一个流行的库,用于处理各种国家和地区的公共假期。然而,需要注意的是,截至2024年,holidays库的官方版本可能并不直接支持中国的所有节日。不过,我们可以通过扩展或自定义该类库来添…...
Jenkins流水线发布,一篇就解决你的所有疑惑
这次搭建的项目比较常规,前端是react写的,后端是springboot,并且由于是全栈开发,所以是在同一个项目中。接下来我演示下怎么用jenkins进行自动化发布。 1.jenkins必装插件 这里用到的是jenkinsFile主要是基于Groovy这个沙盒,有些前置插件。这里使用maven进行打包,所以需…...
安装zabbix时报错Could not resolve host: mirrors.huaweicloud.com;Unknown error解决办法
目录 1、问题原因 2、解决办法 3、知识拓展 DNS的区别 DNS配置文件解析 域名解析过程 4、书籍推荐 当安装Zabbix server,Web前端,agent时出现: [rootsc-zabbix-server ~]# yum install zabbix-server-mysql zabbix-agent安装过程中会出…...
【Linux】CentOS 7 安装配置 postfix 邮件服务器随笔
本文并不是完整配置教程,只是配置过程中零散代码随笔,不成系统 记录配置 PostFix 邮件服务器过程,由于经常用到,会不定时更新完善 yum install -y postfix dovecot cyrus-sasl-plain cyrus-sasl mailx# 设置hostname hostnamect…...
vue3 使用JsMind的方法,以及引入提示报错,无法找到模块“jsmind”的声明文件
最终结果: 一、使用:使用yarn或者npm 安装 yarn add jsmind npm install vue-jsmind 二、引入 两种方法:(如果这样引入没问题按照这样引入) import "jsmind/style/jsmind.css"; import JsMind from &quo…...
狗都能看懂的DBSCAN算法详解
文章目录 DBSCAN简介DBSCAN算法流程运行机制举个实例 DBSCAN算法特点DBSCAN参数选取技巧 ϵ \epsilon ϵ的选取:找突变点MinPts的选取 DBSCAN简介 DBSCAN(Density-Based Spatial Clustering of Applications with Noise,具有噪声的基于密度的…...
运维岗高危操作
序号 高危操作指令 可能存在风险 维护操作要求 1 rm –rf rm –rf是删除文件夹和里面附带内容的一种最快捷的方法,可能会文件误删,导致数据丢失 使用rm –rf命令时千万要小心,可以在.bashrc里面添加: alias rm ‘rm -i’ ,…...
【ajax基础02】URL详解
目录 一:什么是URL 二:URL组成 协议 编辑 域名(在url中必须写) 资源路径 三:URL查询参数 定义: 语法格式: 如何利用axios实现特定数据查询: 语法格式: 案例:…...
MySQL 7种Join的定义图解示范结果(所有join类型)
文章目录 MySQL 7种Join的定义&图解&示范&结果(所有join类型)基本知识笛卡尔积 建表&填充数据1-Join不带条件account筛选 1-Inner Join 内连接不带条件account相同where筛选玩点特殊的 2-Left Join 左连接不带条件account筛选 3-Right J…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...
FFmpeg avformat_open_input函数分析
函数内部的总体流程如下: avformat_open_input 精简后的代码如下: int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...
