当前位置: 首页 > news >正文

独立游戏《星尘异变》UE5 C++程序开发日志5——实现物流系统

目录

一、进出口清单

二、路径计算

 三、包裹

1.包裹的数据结构

 2.包裹在场景中的运动

四、道路

1.道路的数据结构

2.道路的建造

3.道路的销毁

4.某个有道路连接的建筑被删除


        作为一个工厂类模拟经营游戏,各个工厂之间的运输必不可少,本游戏采用的是按需进口的模式,工厂之间可以建立类似于传送带一样的直连道路,每个工厂根据自身当前缺少的所需物品,按照从近到远的顺序依次访问能够生产该物品的工厂,然后收到出口订单的工厂会发出包裹,沿着玩家建设的道路送达发出进口需求的工厂,玩家可以手动配置进出口清单,也就是工厂仓库中某类物品少于多少个就要进口,以及某类物品多于多少个才可以出口,效果如下:

一、进出口清单

         玩家可以编辑每一个建筑的进出口清单实现对进出口的调控,即库存少于多少进口,多于多少出口。清单是一个数组,包括物品的种类和数量,同时还有自动和手动计算的功能切换,在自动模式下,清单中的数值即为生产时实际需求的原料数量,在改为手动模式后,对应物品的数量等于上次手动设置过的数量,清单数组中的数据结构如下:

USTRUCT(BlueprintType)
struct FImportStardust
{FImportStardust(const FName& StardustId, const int Quantity): StardustId(StardustId),Quantity(Quantity){}GENERATED_BODY()UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Import")FName StardustId{ "Empty" };UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Import")int Quantity{ 0 };//是否手动更新数量UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Import")bool IsAuto{true};//上一次手动设定的值UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Import")int LastManualSet{0};FImportStardust()=default;
};

        设置清单中某类星尘的数量:

bool ABP_Asters::SetElementInImportingStardust(const int& Index, const int& Amount)
{//检查索引是否合法if(Index<0||Index>=ImportingStardust.Num()){UE_LOG(LogTemp,Error,TEXT("SetElementInImportingStardust failed,invalid index:%d"),Index);return false;}ImportingStardust[Index].Quantity=Amount;//维护上一次手动设置的值if(!ImportingStardust[Index].IsAuto){ImportingStardust[Index].LastManualSet=Amount;}return true;
}

设置某类星尘的计算是否手动:

void ABP_Asters::SetIsAutoInImportingStardust(const int& Index, const bool& IsAuto)
{//检查索引是否合法if(Index<0||Index>=ImportingStardust.Num()){UE_LOG(LogTemp,Error,TEXT("SetIsAutoInImportingStardust failed,invalid index:%d"),Index);return;}ImportingStardust[Index].IsAuto=IsAuto;if(IsAuto){ImportingStardust[Index].LastManualSet=ImportingStardust[Index].Quantity;//计算某类星尘的需求量
ImportingStardust[Index].Quantity=CalCulateReactionConsumption(ImportingStardust[Index].StardustId);}else{ImportingStardust[Index].Quantity=ImportingStardust[Index].LastManualSet;}
}

二、路径计算

        我们的物流是由进口需求引导的,所以寻路也是由某一个建筑出发,依次遍历连通的最近的建筑来尝试从其进口需要的物品,路径为从出口天体到该天体的路径

TArray<FStardustBasic> ATradingSystemActor::TriggerImport(const int& SourceAsterIndex, const TArray<FStardustBasic> ImportingStardust)
{//输入进口源天体的索引和需求的星尘,返回有哪些进口需求未被满足//检查输入索引是否合法if(!DebugActor->AllAster.Find(SourceAsterIndex)){UE_LOG(LogTemp,Error,TEXT("TriggerImport failed,invalid index:%d"),SourceAsterIndex);return TArray<FStardustBasic>();}std::unordered_map<std::string,int>StardustNeed;for(const auto& it:ImportingStardust){StardustNeed[TCHAR_TO_UTF8(*it.StardustId.ToString())]=it.Quantity;}//建立一个dijkstra算法使用的节点结构,包含点的ID和到起点距离struct Node{Node(const int& ID, const long long& DIstance): ID(ID),DIstance(DIstance){}Node(const Node& Other):ID(Other.ID),DIstance(Other.DIstance){}int ID;long long DIstance;};//重载优先队列排序规则auto cmp{[](const TSharedPtr<Node>&a,const TSharedPtr<Node>& b){return a->DIstance>b->DIstance;}};//储存当前待遍历的点的优先队列,按到起点路径长度从小到大排序
std::priority_queue<TSharedPtr<Node>,std::vector<TSharedPtr<Node>>,decltype(cmp)>Queue(cmp);//放入起点Queue.push(MakeShared<Node>(SourceAsterIndex, 0));//起点到每一个点的最短距离std::map<int,long long>MinimumDistance;//每个点是否被处理完毕std::map<int,bool>Done;//储存最短路径中每个点的父节点std::map<int,int>Path;for(auto& it:DebugActor->AllAster){//初始化最短距离为极大值MinimumDistance[it.Key]=1e18;Done[it.Key]=false;}MinimumDistance[SourceAsterIndex]=0;while(!Queue.empty()){auto Current{Queue.top()};Queue.pop();if(Done[Current->ID]){continue;}if(Current->ID!=SourceAsterIndex){if(!DebugActor->AllAster.Find(Current->ID)){continue;}//当前遍历到的天体auto FoundedAster{DebugActor->AllAster[Current->ID]};TArray<FStardustBasic>PackgingStardust;//遍历出口清单for(const auto&it:FoundedAster->GetExportingStardust()){std::string IDString{TCHAR_TO_UTF8(*it.StardustId.ToString())};if(StardustNeed.find(IDString)==StardustNeed.end()||!StardustNeed[IDString]){continue;}//找到的天体可出口的星尘数量int Available{FoundedAster->OutputInventory->CheckStardust(it.StardustId)-it.Quantity};//实际出口的数量if(int Transfered{std::max(0,std::min(StardustNeed[IDString],Available))}){//维护当前包裹中的星尘和天体仓库中的星尘PackgingStardust.Add(FStardustBasic(it.StardustId,Transfered));FoundedAster->OutputInventory->RemoveStardust(it.StardustId,Transfered);StardustNeed[IDString]-=Transfered;if(!StardustNeed[IDString]){StardustNeed.erase(IDString);}}}//该天体进行了出口if(!PackgingStardust.IsEmpty()){TArray<int>PassedAsters;int CurrentPosition{Current->ID};//记录该天体到进口需求发出天体的路径while (CurrentPosition!=SourceAsterIndex){CurrentPosition=Path[CurrentPosition];PassedAsters.Add(CurrentPosition);}TArray<int>PassedAsters2;//使路径从后往前为包裹要走过的天体for(int i=PassedAsters.Num()-1;i>=0;i--){PassedAsters2.Add(PassedAsters[i]);}//令目标天体发送包裹SendPackage(FPackageInformation(Current->ID,PassedAsters2,PackgingStardust));//所有进口需求都被满足,提前终止if(StardustNeed.empty()){return TArray<FStardustBasic>();}}}//该天体处理完毕,防止被再次处理Done[Current->ID]=true;//遍历该天体所有联通的天体for(const auto&it:AsterGraph[Current->ID]){if(Done[it->TerminalIndex])continue;//这条路是最短路if(MinimumDistance[it->TerminalIndex]>it->distance+Current->DIstance){Path[it->TerminalIndex]=Current->ID;//更新最短路径MinimumDistance[it->TerminalIndex]=it->distance+Current->DIstance;Queue.push(MakeShared<Node>(it->TerminalIndex,MinimumDistance[it->TerminalIndex]));}}}//返回未满足的进口需求TArray<FStardustBasic> Result;if(!StardustNeed.empty()){for(const auto&it:StardustNeed){Result.Add(FStardustBasic(FName(UTF8_TO_TCHAR(it.first.c_str())),it.second));}}return Result;
}

重新寻路的逻辑与之类似,区别在于只是搜索确定的两点之间的最短路,不会发送包裹:

TArray<int> ATradingSystemActor::ReRoute(const int& Start, const int& end)
{TArray<int>Result;struct Node{Node(const int ID, const int DIstance): ID(ID),DIstance(DIstance){}int ID;long long DIstance;};auto cmp{[](const TSharedPtr<Node>&a,const TSharedPtr<Node>& b){return a->DIstance>b->DIstance;}};std::priority_queue<TSharedPtr<Node>,std::vector<TSharedPtr<Node>>,decltype(cmp)>Queue(cmp);Queue.push(MakeShared<Node>(Start,0));std::unordered_map<int,long long>MinimumDistance;std::unordered_map<int,bool>Done;std::map<int,int>Path;for(auto& it:DebugActor->AllAster){MinimumDistance[it.Key]=1e18;Done[it.Key]=false;}MinimumDistance[0]=0;while(!Queue.empty()){auto Current{Queue.top()};Queue.pop();if(Done[Current->ID]){continue;}Done[Current->ID]=true;for(const auto&it:AsterGraph[Current->ID]){//找到终点立刻终止运算if(it->TerminalIndex==end){TArray<int>PassedAsters;int CurrentPosition{Current->ID};while (CurrentPosition!=Start){CurrentPosition=Path[CurrentPosition];PassedAsters.Add(CurrentPosition);}TArray<int>PassedAsters2;for(int i=PassedAsters.Num()-1;i>=0;i--){PassedAsters2.Add(PassedAsters[i]);}return PassedAsters2;}if(Done[it->TerminalIndex])continue;if(MinimumDistance[it->TerminalIndex]>it->distance+Current->DIstance){Path[it->TerminalIndex]=Current->ID;MinimumDistance[it->TerminalIndex]=it->distance+Current->DIstance;Queue.push(MakeShared<Node>(it->TerminalIndex,MinimumDistance[it->TerminalIndex]));}}}//没找到路径返回的是空数组return Result;
}

 三、包裹

1.包裹的数据结构

        包裹的数据包裹发出该包裹的建筑的索引,计划要经过的所有建筑的索引,和携带的星尘

USTRUCT(BlueprintType)
struct FPackageInformation
{explicit  FPackageInformation(const int SourceAsterIndex, const TArray<int>& ExpectedPath,const TArray<FStardustBasic>&ExpectedStardusts): SourceAsterIndex(SourceAsterIndex),ExpectedPath(ExpectedPath),Stardusts(ExpectedStardusts){}FPackageInformation() = default;GENERATED_BODY()//发出包裹的源天体UPROPERTY(VisibleAnywhere,BlueprintReadWrite,Category="Package")int SourceAsterIndex{0};//计划的路径,从后到前依次为即将走过的天体索引UPROPERTY(VisibleAnywhere,BlueprintReadWrite,Category="Package")TArray<int> ExpectedPath;//包裹携带的星尘UPROPERTY(VisibleAnywhere,BlueprintReadWrite,Category="Package")TArray<FStardustBasic>Stardusts;
};

 2.包裹在场景中的运动

            每个包裹的路径是在其生成时就计算好的,数组中从后到前依次是其计划经过的建筑的索引,每到达一个建筑后将末尾的元素弹出,直到全部弹出即到达终点

bool APackageActor::AsterReached(const int& AsterIndex)
{//检查输入的天体索引是否真实存在if(!TradingSystem->DebugActor->AllAster.Find(AsterIndex)){UE_LOG(LogTemp,Error,TEXT("AsterReached failed,invalid index:%d"),AsterIndex);return false;}//即将到达终点if(PackgeInfo.ExpectedPath.Num()==1){//送达包裹中的星尘for(auto&it:PackgeInfo.Stardusts){TradingSystem->DebugActor->AllAster[AsterIndex]->InputInventory->AddStardust(it.StardustId,it.Quantity);it.Quantity-=std::min(it.Quantity,TradingSystem->DebugActor->AllAster[AsterIndex]->InputInventory->CheckAddable(it.StardustId));}//更新库存UITradingSystem->DebugActor->AllAster[AsterIndex]->MCUpdateEvent();TArray<FStardustBasic>LostStardust;//统计因终点库存已满而丢包的星尘for(const auto&it:PackgeInfo.Stardusts){if(it.Quantity){LostStardust.Add(FStardustBasic(it.StardustId,it.Quantity));UE_LOG(LogTemp,Error,TEXT("%d %s can't put in target aster"),it.Quantity,*it.StardustId.ToString());}}return true;}//弹出路径中队尾的元素PackgeInfo.ExpectedPath.Pop();//更新包裹的路径UpdatePathEvent(PackgeInfo.ExpectedPath);return false;
}

        我们使用时间轴和设置actor变换的方式来使包裹在场景中移动,也可以实现游戏暂停时停止移动和恢复移动

四、道路

1.道路的数据结构

        在本游戏中,玩家可以建造多种道路,每种道路有不同的传输速度,最大建造距离和消耗,首先是数据表格的数据结构,这里和DataTable的互动可以看开发日志2(独立游戏《星尘异变》UE5 C++程序开发日志2——实现一个存储物品数据的c++类-CSDN博客)

USTRUCT(BlueprintType)
struct FRoadDataTable:public FTableRowBase
{FRoadDataTable() = default;FRoadDataTable(const FString& RoadName, ERoadType RoadType, int TransferSpeed, double MaximumLength): RoadName(RoadName),RoadType(RoadType),TransferSpeed(TransferSpeed),MaximumLength(MaximumLength){}GENERATED_USTRUCT_BODY()//道路名称UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="RoadInfo")FString RoadName{"Empty"};//道路种类UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="RoadInfo")ERoadType RoadType{ERoadType::Empty};//传输速度,单位距离/秒UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="RoadInfo")int TransferSpeed{1};//最大长度UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="RoadInfo")double MaximumLength{1};//道路建造消耗UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="RoadInfo")TMap<FString,int>RoadConsumption;};

        然后是每条建造出来的道路的数据结构,包括道路的起点和终点,用的是所连建筑物的全局索引,以及这条路建成的长度和表格数据。我们有一个数组维护着所有场上的建筑物的指针,通过这两个索引就可以访问到道路两端的建筑

USTRUCT(BlueprintType)
struct FRoadInformation
{friend bool operator<(const FRoadInformation& Lhs, const FRoadInformation& RHS){return Lhs.distance > RHS.distance;}friend bool operator<=(const FRoadInformation& Lhs, const FRoadInformation& RHS){return !(RHS < Lhs);}friend bool operator>(const FRoadInformation& Lhs, const FRoadInformation& RHS){return RHS < Lhs;}friend bool operator>=(const FRoadInformation& Lhs, const FRoadInformation& RHS){return !(Lhs < RHS);}friend bool operator==(const FRoadInformation& Lhs, const FRoadInformation& RHS){return Lhs.TerminalIndex == RHS.TerminalIndex && Lhs.StartIndex==RHS.StartIndex;}friend bool operator!=(const FRoadInformation& Lhs, const FRoadInformation& RHS){return !(Lhs == RHS);}FRoadInformation() = default;explicit FRoadInformation(const int& StartIndex,const int& TerminalIndex,const FVector&StartLocation,const FVector&EndLocation,const FRoadDataTable& Road):StartIndex(StartIndex), TerminalIndex(TerminalIndex),distance(StartLocation.Distance(StartLocation,EndLocation)),RoadInfo(Road){}GENERATED_USTRUCT_BODY()UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Road")int StartIndex{0};//起点天体的索引UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Road")int TerminalIndex{0};//终点天体的索引UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Road")int distance{0};//两个天体之间的距离,取整//道路的数据UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Road")FRoadDataTable RoadInfo;};

2.道路的建造

        我们用一个红黑树来储存每个建筑都分别链接了哪些建筑

	std::map<int,TArray<TSharedPtr<FRoadInformation>>> AsterGraph;//所有天体构成的图

        在建造道路时传入起点和终点索引,以及道路类型的名称,将建造的道路存入上面存图的容器中

bool ATradingSystemActor::RoadBuilt(const int& Aster1, const int& Aster2,const FString& RoadName)
{if(!DebugActor->IsValidLowLevel()){UE_LOG(LogTemp,Error,TEXT("RoadBuild failed,invalid pointer:DebugActor"));return false;}//这两个建筑之间已存在道路,不可重复建造if(AsterGraph[Aster1].FindByPredicate([Aster2](const TSharedPtr<FRoadInformation>& Road){return Road->TerminalIndex==Aster2;})){return false;}//对应索引的天体不存在if(!DebugActor->AllAster.Find(Aster1)||!DebugActor->AllAster.Find(Aster2)){UE_LOG(LogTemp,Error,TEXT("RoadBuilt failed,invalid index :%d %d"),Aster1,Aster2);return false;}//数据表中存储的道路信息auto RoadInfo{*Instance->RoadDataMap[TCHAR_TO_UTF8(*RoadName)]};//存双向边AsterGraph[Aster1].Add(MakeShared<FRoadInformation>(Aster1,Aster2,DebugActor->AllAster[Aster1]->AsterPosition,DebugActor->AllAster[Aster2]->AsterPosition,RoadInfo));AsterGraph[Aster2].Add(MakeShared<FRoadInformation>(Aster2,Aster1,DebugActor->AllAster[Aster2]->AsterPosition,DebugActor->AllAster[Aster1]->AsterPosition,RoadInfo));return true;
}

3.道路的销毁

        在销毁道路时,我们需要将存的图中的该道路删除,同时对于所有传输中的包裹,如果其原本的路径中包含这条道路,则重新计算路径,如果计算路径失败则将包裹送到下一个到达的建筑物处

void ATradingSystemActor::RoadDestructed(const int& Aster1, const int& Aster2)
{if(!DebugActor->IsValidLowLevel()){UE_LOG(LogTemp,Error,TEXT("RoadDestructed failed,invalid pointer:DebugActor"));return;}//两个方向都要删除AsterGraph[Aster1].RemoveAll([Aster2](const TSharedPtr<FRoadInformation>& Road){return Road->TerminalIndex==Aster2;});AsterGraph[Aster2].RemoveAll([Aster1](const TSharedPtr<FRoadInformation>& Road){return Road->TerminalIndex==Aster1;});//遍历所有在路上的包裹for(auto&it:TransferingPackage){auto Temp{it->GetPackageInfo()};//遍历其计划经过的天体for(int i=Temp.ExpectedPath.Num()-1;i>=1;i--){//是否经过该条道路if(Temp.ExpectedPath[i]==Aster1&&Temp.ExpectedPath[i-1]==Aster2||Temp.ExpectedPath[i]==Aster2&&Temp.ExpectedPath[i-1]==Aster1){//尝试重新计算路径auto TempArray{ReRoute(Temp.ExpectedPath[Temp.ExpectedPath.Num()-1],Temp.ExpectedPath[0])};//没有能到终点的道路了if(TempArray.IsEmpty()){UE_LOG(LogTemp,Error,TEXT("RerouteFailed"));//将终点改为下一个天体TArray<int>Result;Result.Add(Temp.ExpectedPath[Temp.ExpectedPath.Num()-1]);Temp.ExpectedPath=Result;it->SetPackageInfo(Temp);it->UpdatePathEvent(Temp.ExpectedPath);break;}//应用新的路径Temp.ExpectedPath=TempArray;it->SetPackageInfo(Temp);it->UpdatePathEvent(Temp.ExpectedPath);break;}}}
}

4.某个有道路连接的建筑被删除

        在有道路连接的建筑被删除后,所有路径中包含该建筑的包裹要重新寻路,如果不能到达终点,同样送到下一个建筑为止

void ABP_Asters::AsterDestructed()
{ //这里展示的仅是该函数中关于物流系统的部分//删除以该天体为起点的道路TradingSystem->AsterGraph.erase(AsterIndex);for(auto&it:TradingSystem->AsterGraph){//删除以该天体为终点的道路auto temp{AsterIndex};it.second.RemoveAll([temp](const TSharedPtr<FRoadInformation>& Road){return Road->TerminalIndex==temp;});}for(int i=0;i<TradingSystem->TransferingPackage.Num();i++){auto it{TradingSystem->TransferingPackage[i]};if(!IsValid(it)){TradingSystem->TransferingPackage.RemoveAt(i);i--;continue;}auto Temp{it->GetPackageInfo()};bool NeedReroute{false};//计划路径中有该天体就需要重新寻路for(auto& it2:Temp.ExpectedPath){if(it2==AsterIndex){NeedReroute=true;}}if(NeedReroute){        //下一个目的地就是该天体,直接删除if(Temp.ExpectedPath.Num()==1){it->Destroy();continue;}//终点是该天体,那肯定找不到路了if(Temp.ExpectedPath[0]==AsterIndex){UE_LOG(LogTemp,Error,TEXT("Reroute failed"));TArray<int>Result;Result.Add(Temp.ExpectedPath[Temp.ExpectedPath.Num()-1]);Temp.ExpectedPath=Result;it->SetPackageInfo(Temp);it->UpdatePathEvent(Temp.ExpectedPath);continue;}//尝试重新寻路auto TempArray{TradingSystem->ReRoute(Temp.ExpectedPath[Temp.ExpectedPath.Num()-1],Temp.ExpectedPath[0])};//没找到合适的道路if(TempArray.IsEmpty()){UE_LOG(LogTemp,Error,TEXT("Reroute failed"));TArray<int>Result;Result.Add(Temp.ExpectedPath[Temp.ExpectedPath.Num()-1]);Temp.ExpectedPath=Result;it->SetPackageInfo(Temp);it->UpdatePathEvent(Temp.ExpectedPath);continue;}//应用新的路径Temp.ExpectedPath=TempArray;it->SetPackageInfo(Temp);it->UpdatePathEvent(Temp.ExpectedPath);}}//蓝图实现的事件,因为道路的指针存在蓝图里,所以交给蓝图来删除对象AsterDestructedEvent(this);
}


 

相关文章:

独立游戏《星尘异变》UE5 C++程序开发日志5——实现物流系统

目录 一、进出口清单 二、路径计算 三、包裹 1.包裹的数据结构 2.包裹在场景中的运动 四、道路 1.道路的数据结构 2.道路的建造 3.道路的销毁 4.某个有道路连接的建筑被删除 作为一个工厂类模拟经营游戏&#xff0c;各个工厂之间的运输必不可少&#xff0c;本游戏采用的…...

Web开发:<br>标签的作用

br作用 介绍基本用法常见用途注意事项使用CSS替代 介绍 在Web开发中&#xff0c;<br> 标签是一个用于插入换行符的HTML标签。它是“break”的缩写&#xff0c;常用于需要在文本中强制换行的地方。<br> 标签是一个空标签&#xff0c;这意味着它没有结束标签。 基本…...

DVC+Minio

由于参数文件比较大&#xff0c;因此onnx、engine等大文件弃用LFS管理&#xff0c;改用dvc管理&#xff1a; minio就是存储用的 启动miniosudo netstat -ntpl#查看端口号 sudo kill -9 $(sudo lsof -i:5061 -t) 关闭端口对应进程 ./minio server --console-address ":6570…...

C++内存管理(区别C语言)深度对比

欢迎来到我的Blog&#xff0c;点击关注哦&#x1f495; 前言 前面已经介绍了类和对象&#xff0c;对C面向对象编程已经有了全面认识&#xff0c;接下来要学习对语言学习比较重要的是对内存的管理。 一、内存的分区 代码区&#xff1a;存放程序的机器指令&#xff0c;通常是可…...

手把手带你写一个精简版 HashMap 的 put 方法

&#x1f446;&#x1f3fb;&#x1f446;&#x1f3fb;&#x1f446;&#x1f3fb;关注博主&#xff0c;让你的代码变得更加优雅。 前言 HashMap 大家工作中遇到的太多了&#xff0c;已经成了必须使用的类了&#xff0c; 在面试的时候 HashMap 基本是必问题&#xff0c;但是…...

【面试题】数据结构:堆排序的排序思想?

堆排序的排序思想&#xff1f; 堆排序是一种高效的排序算法&#xff0c;其基本思想是利用堆这种数据结构来实现排序。堆是一种特殊的完全二叉树&#xff0c;通常用数组来表示。堆排序的基本步骤如下&#xff1a; 1. 构建初始堆&#xff1a; 将待排序的数组转换成一个最大堆&a…...

PyTorch 深度学习实践-循环神经网络基础篇

视频指路 参考博客笔记 参考笔记二 文章目录 上课笔记基于RNNCell实现总代码 基于RNN实现总代码 含嵌入层的RNN网络嵌入层的作用含嵌入层的RNN网络架构总代码 其他RNN扩展基本注意力机制自注意力机制&#xff08;Self-Attention&#xff09;自注意力计算多头注意力机制&#xf…...

vue实现可拖拽dialog封装

一、实现modal弹窗组件 <template><divv-if"visible"class"customer-dialog"id"customer-dialog":style"dialogStyles"v-dialogDrag:[dialogDrag]><div class"dialog-container"><divclass"dial…...

本地多模态看图说话-llava

其中图片为bast64转码&#xff0c;方便json序列化。 其中模型llava为本地ollama运行的模型&#xff0c;如&#xff1a;ollama run llava 还有其它的模型如&#xff1a;llava-phi3&#xff0c;通过phi3微调过的版本。 实际测试下来&#xff0c;发现本地多模型的性能不佳&…...

人工智能算法工程师(中级)课程14-神经网络的优化与设计之拟合问题及优化与代码详解

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能算法工程师(中级)课程14-神经网络的优化与设计之拟合问题及优化与代码详解。在机器学习和深度学习领域&#xff0c;模型的训练目标是找到一组参数&#xff0c;使得模型能够从训练数据中学习到有用的模式&am…...

Java异常抛出与处理方法

在Java编程中,异常处理是一个非常重要的部分。通过正确的异常处理,我们可以提高程序的健壮性和可靠性,避免程序在运行过程中出现意外的崩溃。本文将详细讲述Java异常的抛出与处理方法,并通过示例代码进行说明。 一、Java异常的分类 Java中的异常体系结构可以分为三类: 检…...

兼容性测试主要有什么类型?

兼容性测试的类型 有两种类型的兼容性测试。这是一个快速细分。 1、前向兼容性测试 向前兼容性测试或向上兼容性测试可确保当前软件版本在相关组件(例如操作系统、浏览器和第三方库)的未来版本中保持功能。此类测试对于在系统升级期间保持稳定性和用户体验至关重要。 例如&…...

设计模式--组合模式

组合模式&#xff08;Composite Pattern&#xff09;详解 组合模式是一种结构型设计模式&#xff0c;它允许你将对象组合成树形结构来表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。 适用场景 需要表示对象的部分-整体层次结构时&am…...

ArduPilot开源代码之AP_DAL_RangeFinder

ArduPilot开源代码之AP_DAL_RangeFinder 1. 源由2. 框架设计2.1 枚举 Status2.2 公有方法2.3 私有成员变量 3. 重要例程3.1 应用函数3.1.1 ground_clearance_cm_orient3.1.2 max_distance_cm_orient3.1.3 has_orientation3.1.4 get_backend 3.2 其他函数3.2.1 AP_DAL_RangeFind…...

SpringCloud教程 | 第九篇: 使用API Gateway

1、参考资料 SpringCloud基础篇-10-服务网关-Gateway_springcloud gateway-CSDN博客 2、先学习路由&#xff0c;参考了5.1 2.1、建了一个cloudGatewayDemo&#xff0c;这是用来配置网关的工程&#xff0c;配置如下&#xff1a; http://localhost:18080/aaa/name 该接口代码如…...

数据结构——hash(hashmap源码探究)

hash是什么&#xff1f; hash也称为散列&#xff0c;就是把任意长度的输入&#xff0c;通过散列算法&#xff0c;变成固定长度的输出&#xff0c;这个输出值就是散列值。 举例来说明一下什么是hash&#xff1a; 假设我们要把1~12存入到一个大小是5的hash表中&#xff0c;我们…...

国产麒麟、UOS在线打开pdf加盖印章

PageOffice支持两种电子印章方案&#xff0c;可实现对Word、Excel、PDF文档加盖PageOffice自带印章或ZoomSeal电子印章&#xff08;全方位保护、防篡改、防伪造&#xff09;。Word和Excel的盖章功能请参考&#xff1a;Word和Excel加盖印章和签字功能 &#xff08;目前只支持win…...

破解反爬虫策略 /_guard/auto.js(二)实战

这次我们用上篇文章讲到的方法来真正破解一下反爬虫策略&#xff0c;这两个案例是两个不同的网站&#xff0c;一个用的是 /_guard/auto.js&#xff0c;另一个用的是/_guard/delay_jump.js。经过解析发现这两个网站用的反爬虫策略基本是一模一样&#xff0c;只不过在js混淆和生成…...

同样是人工智能 客户在哪儿AI和GPT等大模型有什么不同

书接上回。为了统一回答朋友们的疑惑&#xff0c;此前的两篇文章&#xff0c;着重讲述了客户在哪儿AI的企业全历史行为数据和企业信息查询平台上的数据的区别&#xff0c;以及客户在哪儿AI的ToB获客服务和AI外呼机器人的获客服务的不同。本期接着讲——客户在哪儿AI VS 大模型&…...

AES Android IOS H5 加密方案

前景&#xff1a; 1、本项目原有功能RSA客户端对敏感信息进行加密 2、本次漏洞说是服务端返回值有敏感信息&#xff0c;需要密文返回 3、最初只跟H5联调成功&#xff0c;后续APP联调失败(H5和APP的需求排期不一致)&#xff0c;没关注到通用性 方案&#xff1a; 本次方案不…...

一文了解变阻器和电位器的定义、原理、应用及其对比

变阻器的定义 两端可变电阻器&#xff08;称为变阻器&#xff09;利用电阻来调节电流。电阻丝环绕在陶瓷或瓷器等绝缘芯上。当刮水器沿着电阻丝移动时&#xff0c;电路的有效电阻会发生变化。因此&#xff0c;它提供了精确的电流控制。调光器、电机速度控制器和加热元件使用变…...

WPF实现一个带旋转动画的菜单栏

WPF实现一个带旋转动画的菜单栏 一、创建WPF项目及文件1、创建项目2、创建文件夹及文件3、添加引用 二、代码实现2.ControlAttachProperty类 一、创建WPF项目及文件 1、创建项目 打开VS2022,创建一个WPF项目&#xff0c;如下所示 2、创建文件夹及文件 创建资源文件夹&…...

使用Dockerfile构建镜像

目录 1.使用Dockerfile构建tomcat镜像 1.1 通过ARG传参构建不同版本的tomcat 2.缩小镜像的体积大小 2.1 使用较小体积的基础镜像 2.2 多级构建减少体积 1.使用Dockerfile构建tomcat镜像 cd /opt mkdir tomcat cd tomcat/ 上传tomcat所需的依赖包 使用tar xf 解压三个压缩…...

概率论原理精解【3】

文章目录 向量值向量值函数导数对称矩阵定义性质例子应用 向量值理论基础定义性质应用示例 向量值函数的导数定义性质应用 向量值 向量值函数导数 D n ⊂ R n , 向量值函数 f : D n → R m D^n \subset R^n,向量值函数f:D^n\rightarrow R^m Dn⊂Rn,向量值函数f:Dn→Rm 1. 向量…...

[C/C++入门][循环]14、计算2的幂(2的n次方)

计算2的幂&#xff08;即2的n次方&#xff09;非常经典。你懂几种方法呢&#xff1f;很多人只会一种&#xff0c;我们来分析一下。 可以通过多种方式实现&#xff1a; 1、最简单的方法之一是使用位运算符<<&#xff0c;它本质上是在二进制表示下对2进行左移操作&#x…...

RPC与服务的注册发现

文章目录 1. 什么是远程过程调用(RPC)?2. RPC的流程3. RPC实践4. RPC与REST的区别4.1 RPC与REST的相似之处4.2 RPC与REST的架构原则4.3 RPC与REST的主要区别 5. RPC与服务发现5.1 以zookeeper为服务注册中心5.2 以etcd为服务注册中心 6. 小结参考 1. 什么是远程过程调用(RPC)?…...

3112. 访问消失节点的最少时间 Medium

给你一个二维数组 edges 表示一个 n 个点的无向图&#xff0c;其中 edges[i] [ui, vi, lengthi] 表示节点 ui 和节点 vi 之间有一条需要 lengthi 单位时间通过的无向边。 同时给你一个数组 disappear &#xff0c;其中 disappear[i] 表示节点 i 从图中消失的时间点&#xff0…...

FastAPI 学习之路(五十二)WebSockets(八)接受/发送json格式消息

前面我们发送的大多数都是text类型的消息&#xff0c;对于text消息来说&#xff0c;后端处理出来要麻烦的多&#xff0c;那么我们可以不可以传递json格式的数据&#xff0c;对于前后端来说都比较友好&#xff0c;答案是肯定的&#xff0c;我们需要做下处理。 首先&#xff0c;…...

Go语言并发编程-案例_3

案例 并发目录大小统计 业务逻辑 统计目录的文件数量和大小&#xff08;或其他信息&#xff09;。示例输出&#xff1a; // 某个目录&#xff1a;2637 files 1149.87 MB 实现思路 给定一个或多个目录&#xff0c;并发的统计每个目录的size&#xff0c;最后累加到一起。 当…...

pikachu之跨站脚本攻击(x‘s‘s)

1get型 输入a看一下 接着输入<a> 发现<>没有被过滤当做标签处理了 尝试在表单提交的框里面&#xff0c;输入xss语句 尝试输入<script>alert(1)</script> 发现有长度限制 因为这里是get请求 get请求的特点是&#xff1a;传参是在url中的 所以我们可以在…...

做网上推广/seo关键词优化的技巧

最短Hamilton路径 给定一张 n 个点的带权无向图&#xff0c;点从 0~n-1 标号&#xff0c;求起点 0 到终点 n-1 的最短Hamilton路径。 Hamilton路径的定义是从 0 到 n-1 不重不漏地经过每个点恰好一次。 输入格式 第一行输入整数n。 接下来n行每行n个整数&#xff0c;其中第i…...

网站设计建设趋势/苏州网站开发公司

互联网的兴起现在已经成为当今世界的主流媒体和信息传播媒介&#xff0c;做为互联网的应用各个终端用户是组成这一互联网世界的主体。如何行之有效的进行互联网的接入和应用成为了一个主要的问题。 小区宽带运营就此出现&#xff0c;做为新兴的网络接入运营模式。小区宽带运营在…...

校园服装网站建设演示文稿/aso优化平台有哪些

在编码时禁止使用goto语句&#xff1b;进行面向对象编程时要尽可能的面向对象&#xff0c;最好引入各种设计模式&#xff1b;设计关系数据库时要遵从范式&#xff1b;多线程程序可以提高程序性能&#xff1b;C语言的效率要比c效率高&#xff1b;......请问这些条率款正确吗&…...

附近做网站/网络推广项目外包公司

神经网络的结构设计有3个主流的高级技巧&#xff1a;1&#xff0c;高低融合 (将高层次特征与低层次特征融合&#xff0c;提升特征维度的丰富性和多样性&#xff0c;像人一样同时考虑整体和细节)2&#xff0c;权值共享 (一个权值矩阵参与多个不同的计算&#xff0c;降低参数规模…...

免费男人做那个的视频网站/行业关键词分类

主要的内容 REUSEADDR 处理多客户链接 P2P对点传输 主要问题: 服务器关闭的同时&#xff0c;客户端的父进程(读取数据的进程)和子进程(发送数据的进程)必须关闭 同理: 客户端关闭的时候&#xff0c;服务器父进程(读取数据的进程)和子进程(发送数据的进程)必须关闭 ser…...

做网购的有哪几个网站/东莞seo管理

用JQuery Validate框架&#xff0c;在IE8下验证报错问题解决参考文章&#xff1a; &#xff08;1&#xff09;用JQuery Validate框架&#xff0c;在IE8下验证报错问题解决 &#xff08;2&#xff09;https://www.cnblogs.com/destimarve/p/5511257.html 备忘一下。...