人工智慧學習總結——專案實戰:西部世界——訊息(程式碼篇)
先來搭建底層模組:
角色實體基類和角色管理類:
#pragma once
#include "stdafx.h"
#include "message.h"
#include <map>
class CEntityBase
{
private:
int m_iID;
public:
CEntityBase(int id){m_iID=id;}
virtual ~CEntityBase(){}
virtual void Update()=0;
virtual bool HandleMessage(const MESSAGE&msg)=0;
int GetID(){return m_iID;}
};
class CEntityManager
{
private:
map<int,CEntityBase*> m_mapEntity;
private:
CEntityManager(){}
CEntityManager(const CEntityManager&){}
CEntityManager& operator=(const CEntityManager&){}
~CEntityManager(){};
public:
static CEntityManager* GetInstance()
{
static CEntityManager em;
return &em;
}
void EntityRegister(int id,CEntityBase* pEntity)
{
m_mapEntity.insert(pair<int,CEntityBase*>(id,pEntity));
}
void EntityRemove(int id)
{
m_mapEntity.erase(id);
}
CEntityBase* GetEntityFromID(int id)
{
return m_mapEntity.find(id)->second;
}
};
狀態模板基類:
#pragma once
#include "message.h"
template<class entity_type>
class CState
{
public:
virtual ~CState(void)
{
}
public:
virtual void Enter(entity_type*)=0;
virtual void Execute(entity_type*)=0;
virtual void Exit(entity_type*)=0;
virtual bool OnMessage(entity_type*,const MESSAGE& msg)=0;
};
狀態機模板類:
#pragma once
#include "State.h"
#include "message.h"
template<class entity_type>
class CStateMachine
{
private:
CState<entity_type>* m_pCurrentState;
CState<entity_type>* m_pGlobalState;
CState<entity_type>* m_pPreviousState;
entity_type* m_pOwner;
public:
CStateMachine(entity_type*pOwner)
{
m_pOwner=pOwner;
m_pCurrentState=NULL;
m_pGlobalState=NULL;
m_pPreviousState=NULL;
}
virtual ~CStateMachine(void)
{
}
void SetCurrentState(CState<entity_type>*);
void SetGlobalState(CState<entity_type>*);
void SetPreviousState(CState<entity_type>*);
void Update();
void ChangeState(CState<entity_type>* pNewState);
void RevertToPreviousState();
bool HandleMessage(const MESSAGE& msg);
};
template<class entity_type>
bool CStateMachine<entity_type>::HandleMessage(const MESSAGE& msg)
{
if (m_pCurrentState&&m_pCurrentState->OnMessage(m_pOwner,msg) )
{
return true;
}
if (m_pGlobalState && m_pGlobalState->OnMessage(m_pOwner,msg))
{
return true;
}
return false;
}
template<class entity_type>
void CStateMachine<entity_type>::RevertToPreviousState()
{
m_pCurrentState->Exit(m_pOwner);
m_pCurrentState=m_pPreviousState;
m_pPreviousState=NULL;
m_pCurrentState->Enter(m_pOwner);
}
template<class entity_type>
void CStateMachine<entity_type>::ChangeState(CState<entity_type>* pNewState)
{
m_pCurrentState->Exit(m_pOwner);
m_pPreviousState=m_pCurrentState;
m_pCurrentState=pNewState;
m_pCurrentState->Enter(m_pOwner);
}
template<class entity_type>
void CStateMachine<entity_type>::SetGlobalState(CState<entity_type>*pState)
{
m_pGlobalState=pState;
}
template<class entity_type>
void CStateMachine<entity_type>::SetCurrentState(CState<entity_type>*pState)
{
m_pCurrentState=pState;
}
template<class entity_type>
void CStateMachine<entity_type>::Update()
{
if (m_pCurrentState)
{
m_pCurrentState->Execute(m_pOwner);
}
if (m_pGlobalState!=NULL)
{
m_pGlobalState->Enter(m_pOwner);
m_pGlobalState->Execute(m_pOwner);
}
}
訊息類:
#pragma once
#include <math.h>
enum MessageType
{
msgHiIGoHome,
msgCook,
msgCookOk
};
const float SMALLESTDELAY=0.25;
struct MESSAGE
{
float delay;
int sender;
int recievier;
int msg;
void* extra;
bool operator==(const MESSAGE& message)const
{
return(fabs(delay-message.delay)<SMALLESTDELAY)&& sender==message.sender&& recievier==message.recievier;
}
bool operator<(const MESSAGE& message)const
{
if (*this==message)
{
return false;
}
return (this->delay<message.delay);
}
};
訊息處理類:
#pragma once
#include "message.h"
#include "EntityBase.h"
#include <set>
class CDispatchMessage
{
private:
set<MESSAGE>m_PriorityQ;
private:
void Transmit(CEntityBase*pReceiver,const MESSAGE&msg);
private:
CDispatchMessage(void);
CDispatchMessage(const CDispatchMessage&){};
CDispatchMessage& operator=(CDispatchMessage&){}
~CDispatchMessage(void);
public:
static CDispatchMessage* GetInstance();
void SendMessage(float delay,int sender,int receiver,int msg,void* extra);
void SendDelayMessage();
};
然後請Bob先生和Ellsa女士登場:
#pragma once
#include "entitybase.h"
#include "StateMachine.h"
#include "stdafx.h"
const int MAXCARRYGOLD=5;
const int MAXTHIRST=3;
const int MAXFATIGUE=5;
class CMiner :public CEntityBase
{
private:
CStateMachine<CMiner>* m_pStateMachine;
LocationType m_location;
int m_iCarryGold;
int m_iThirst;
int m_iFatigue;
int m_iMoney;
public:
CMiner(int id);
~CMiner(void);
virtual void Update();
virtual bool HandleMessage(const MESSAGE&msg);
public:
LocationType GetLocation(){return m_location;}
void ChangeLocation(LocationType loc){m_location=loc;}
bool GetCarryGold(){return m_iCarryGold>MAXCARRYGOLD;}
bool GetThirst(){return m_iThirst>MAXTHIRST;}
bool GetFatigue(){return m_iFatigue>MAXFATIGUE;}
bool FeelComfort(){return m_iFatigue<=0;}
bool FeelWaterEnough(){return m_iThirst<=0;}
int GetMoney(){return m_iMoney;}
void SetCarryGold(int g){m_iCarryGold+=g;}
void EmptyGold(){m_iCarryGold=0;}
void SetThirst(int t){m_iThirst+=t;}
void SetFatigue(int f){m_iFatigue+=f;}
void SetMoney(int m){m_iMoney+=m*m_iCarryGold;}
void Pay(int p){m_iMoney-=p;}
CStateMachine<CMiner>* GetStateMachine(){return m_pStateMachine;}
};
#pragma once
#include "entitybase.h"
#include "StateMachine.h"
class CWife :public CEntityBase
{
private:
CStateMachine<CWife>* m_pStateMachine;
public:
CWife(int id);
~CWife(void);
virtual void Update();
virtual bool HandleMessage(const MESSAGE&msg);
public:
CStateMachine<CWife>* GetStateMachine(){return m_pStateMachine;}
};
下面設計Bob的狀態:
#pragma once
#include "state.h"
#include "Miner.h"
class CGoMineAndDig :public CState<CMiner>
{
private:
CGoMineAndDig(void){};
CGoMineAndDig(const CGoMineAndDig&);
CGoMineAndDig& operator=(const CGoMineAndDig&);
//~CGoMineAndDig(void);
public:
static CGoMineAndDig* GetInstance();
void Enter(CMiner*pMiner);
void Execute(CMiner*pMiner);
void Exit(CMiner*pMiner);
bool OnMessage(CMiner* pMiner,const MESSAGE& msg);
};
class CGoHome :public CState<CMiner>
{
private:
CGoHome(void){};
CGoHome(const CGoHome&);
CGoHome& operator=(const CGoHome&);
//~CGoHome(void);
public:
static CGoHome* GetInstance();
virtual void Enter(CMiner*pMiner);
virtual void Execute(CMiner*pMiner);
virtual void Exit(CMiner*pMiner);
virtual bool OnMessage(CMiner*pMiner,const MESSAGE& msg);
};
class CVistBank :public CState<CMiner>
{
private:
CVistBank(void){};
CVistBank(const CVistBank&);
CVistBank& operator=(const CVistBank&);
//~CVistBank(void);
public:
static CVistBank* GetInstance();
virtual void Enter(CMiner*pMiner);
virtual void Execute(CMiner*pMiner);
virtual void Exit(CMiner*pMiner);
virtual bool OnMessage(CMiner*pMiner,const MESSAGE& msg);
};
class CGoToBar :public CState<CMiner>
{
private:
CGoToBar(void){};
CGoToBar(const CGoToBar&);
CGoToBar& operator=(const CGoToBar&);
//~CGoToBar(void);
public:
static CGoToBar* GetInstance();
virtual void Enter(CMiner*pMiner);
virtual void Execute(CMiner*pMiner);
virtual void Exit(CMiner*pMiner);
virtual bool OnMessage(CMiner*pMiner,const MESSAGE& msg);
};
class CEat :public CState<CMiner>
{
private:
CEat(void){};
CEat(const CEat&);
CEat& operator=(const CEat&);
//~CEat(void);
public:
static CEat* GetInstance();
virtual void Enter(CMiner*pMiner);
virtual void Execute(CMiner*pMiner);
virtual void Exit(CMiner*pMiner);
virtual bool OnMessage(CMiner*pMiner,const MESSAGE& msg);
};
Ellsa的狀態:
#pragma once
#include "state.h"
#include "Wife.h"
class CGlobalState :public CState<CWife>
{
private:
CGlobalState(void){};
CGlobalState(const CGlobalState&);
CGlobalState& operator=(const CGlobalState&);
//~CGlobalState(void);
public:
static CGlobalState* GetInstance();
void Enter(CWife*pWife);
void Execute(CWife*pWife);
void Exit(CWife*pWife);
bool OnMessage(CWife*pWife,const MESSAGE& msg);
};
class CDoHouseWork :public CState<CWife>
{
private:
CDoHouseWork(void){};
CDoHouseWork(const CDoHouseWork&);
CDoHouseWork& operator=(const CDoHouseWork&);
//~CDoHouseWork(void);
public:
static CDoHouseWork* GetInstance();
virtual void Enter(CWife*pWife);
virtual void Execute(CWife*pWife);
virtual void Exit(CWife*pWife);
virtual bool OnMessage(CWife*pWife,const MESSAGE& msg);
};
class CGoToilet :public CState<CWife>
{
private:
CGoToilet(void){};
CGoToilet(const CGoToilet&);
CGoToilet& operator=(const CGoToilet&);
//~CGoToilet(void);
public:
static CGoToilet* GetInstance();
virtual void Enter(CWife*pWife);
virtual void Execute(CWife*pWife);
virtual void Exit(CWife*pWife);
virtual bool OnMessage(CWife*pWife,const MESSAGE& msg);
};
class CCook :public CState<CWife>
{
private:
CCook(void){};
CCook(const CCook&);
CCook& operator=(const CCook&);
//~CCook(void);
public:
static CCook* GetInstance();
virtual void Enter(CWife*pWife);
virtual void Execute(CWife*pWife);
virtual void Exit(CWife*pWife);
virtual bool OnMessage(CWife*pWife,const MESSAGE& msg);
};
ok,設計完畢,下面開始實現:
先實現訊息處理器:
#include "DispatchMessage.h"
#include <time.h>
void CDispatchMessage::Transmit(CEntityBase*pReceiver,const MESSAGE&msg)
{
pReceiver->HandleMessage(msg);
}
CDispatchMessage::CDispatchMessage(void)
{
}
CDispatchMessage::~CDispatchMessage(void)
{
}
CDispatchMessage* CDispatchMessage::GetInstance()
{
static CDispatchMessage dm;
return &dm;
}
void CDispatchMessage::SendMessage(float delay,int sender,int receiver,int msg,void*extra)
{
MESSAGE message;
message.delay=0;
message.sender=sender;
message.recievier=receiver;
message.msg=msg;
message.extra=extra;
CEntityBase* pEntity;
pEntity=CEntityManager::GetInstance()->GetEntityFromID(receiver);
if (delay<=0)
{
Transmit(pEntity,message);
}else
{
message.delay=(float)time(NULL)+delay;
m_PriorityQ.insert(message);
}
}
void CDispatchMessage::SendDelayMessage()
{
float currenttime=(float)time(NULL);
set<MESSAGE>::iterator iter=m_PriorityQ.begin();
while(!m_PriorityQ.empty() && iter->delay<currenttime && iter->delay>0)
{
CEntityBase* pReceiver=CEntityManager::GetInstance()->GetEntityFromID(iter->recievier);
Transmit(pReceiver,*iter);
m_PriorityQ.erase(iter);
}
}
再把Bob實現出來:
#include "Miner.h"
#include "MinerState.h"
CMiner::CMiner(int id):CEntityBase(id)
{
m_pStateMachine=new CStateMachine<CMiner>(this);
m_location=shack;
m_iCarryGold=0;
m_iFatigue=0;
m_iMoney=0;
m_iThirst=0;
m_pStateMachine->SetCurrentState(CGoMineAndDig::GetInstance());
}
CMiner::~CMiner(void)
{
delete m_pStateMachine;
}
void CMiner::Update()
{
m_pStateMachine->Update();
}
bool CMiner::HandleMessage(const MESSAGE&msg)
{
return m_pStateMachine->HandleMessage(msg);
}
再實現Ellsa:
#include "Wife.h"
#include "WifeState.h"
CWife::CWife(int id):CEntityBase(id)
{
m_pStateMachine=new CStateMachine<CWife>(this);
m_pStateMachine->SetCurrentState(CDoHouseWork::GetInstance());
m_pStateMachine->SetGlobalState(CGlobalState::GetInstance());
}
CWife::~CWife(void)
{
delete m_pStateMachine;
}
void CWife::Update()
{
m_pStateMachine->Update();
}
bool CWife::HandleMessage(const MESSAGE&msg)
{
return m_pStateMachine->HandleMessage(msg);
}
實現Bob的狀態:
#include "MinerState.h"
#include "DispatchMessage.h"
CGoMineAndDig* CGoMineAndDig::GetInstance()
{
static CGoMineAndDig dig;
return &dig;
}
void CGoMineAndDig::Enter(CMiner*pMiner)
{
if (pMiner->GetLocation()!=GoldMine)
{
pMiner->ChangeLocation(GoldMine);
}
cout<<GetNameOfEntity(entMiner)<<"I will go to mine and dig gold"<<endl;
}
void CGoMineAndDig::Execute(CMiner*pMiner)
{
pMiner->SetCarryGold(1);
pMiner->SetFatigue(2);
pMiner->SetThirst(1);
cout<<GetNameOfEntity(entMiner)<<"I am digging."<<endl;
if (pMiner->GetThirst())
{
pMiner->GetStateMachine()->ChangeState(CGoToBar::GetInstance());
}
if (pMiner->GetCarryGold())
{
pMiner->GetStateMachine()->ChangeState(CVistBank::GetInstance());
}
if (pMiner->GetFatigue())
{
pMiner->GetStateMachine()->ChangeState(CGoHome::GetInstance());
}
}
void CGoMineAndDig::Exit(CMiner*pMiner)
{
cout<<GetNameOfEntity(entMiner)<<"Leave Mine"<<endl;
}
bool CGoMineAndDig::OnMessage(CMiner*pMiner,const MESSAGE& msg)
{
return false;
}
CGoHome* CGoHome::GetInstance()
{
static CGoHome h;
return &h;
}
void CGoHome::Enter(CMiner*pMiner)
{
if (pMiner->GetLocation()!=shack)
{
pMiner->ChangeLocation(shack);
}
CDispatchMessage::GetInstance()->SendMessage(0,entMiner,entWife,msgHiIGoHome,NULL);
cout<<GetNameOfEntity(entMiner)<<"I will go home"<<endl;
}
void CGoHome::Execute(CMiner*pMiner)
{
pMiner->SetFatigue(-1);
cout<<GetNameOfEntity(entMiner)<<"warm home"<<endl;
if (pMiner->FeelComfort())
{
pMiner->GetStateMachine()->ChangeState(CGoMineAndDig::GetInstance());
}
}
void CGoHome::Exit(CMiner*pMiner)
{
cout<<GetNameOfEntity(entMiner)<<"ByeBye honey"<<endl;
}
bool CGoHome::OnMessage(CMiner*pMiner,const MESSAGE& msg)
{
switch (msg.msg)
{
case msgCookOk:
cout<<GetNameOfEntity(entMiner)<<"ok,come here"<<endl;
pMiner->GetStateMachine()->ChangeState(CEat::GetInstance());
return true;
default:
return false;
}
}
CVistBank* CVistBank::GetInstance()
{
static CVistBank b;
return &b;
}
void CVistBank::Enter(CMiner*pMiner)
{
if (pMiner->GetLocation()!=bank)
{
pMiner->ChangeLocation(bank);
}
cout<<GetNameOfEntity(entMiner)<<"I will visit bank"<<endl;
}
void CVistBank::Execute(CMiner*pMiner)
{
pMiner->SetMoney(2);
pMiner->EmptyGold();
cout<<GetNameOfEntity(entMiner)<<"hello,mr.bank"<<endl;
if (pMiner->GetFatigue())
{
pMiner->GetStateMachine()->ChangeState(CGoHome::GetInstance());
}else
{
pMiner->GetStateMachine()->ChangeState(CGoMineAndDig::GetInstance());
}
}
void CVistBank::Exit(CMiner*pMiner)
{
cout<<GetNameOfEntity(entMiner)<<"bye mr.bank"<<endl;
}
bool CVistBank::OnMessage(CMiner*pMiner,const MESSAGE& msg)
{
return false;
}
CGoToBar* CGoToBar::GetInstance()
{
static CGoToBar bar;
return &bar;
}
void CGoToBar::Enter(CMiner*pMiner)
{
cout<<GetNameOfEntity(entMiner)<<"give me a cup of tea"<<endl;
}
void CGoToBar::Execute(CMiner*pMiner)
{
pMiner->SetFatigue(-1);
pMiner->SetThirst(-1);
pMiner->Pay(1);
cout<<GetNameOfEntity(entMiner)<<"good wine"<<endl;
if (pMiner->FeelWaterEnough())
{
pMiner->GetStateMachine()->ChangeState(CGoMineAndDig::GetInstance());
}
}
void CGoToBar::Exit(CMiner*pMiner)
{
cout<<GetNameOfEntity(entMiner)<<"bye beautity"<<endl;
}
bool CGoToBar::OnMessage(CMiner*pMiner,const MESSAGE& msg)
{
return false;
}
CEat* CEat::GetInstance()
{
static CEat e;
return &e;
}
void CEat::Enter(CMiner*pMiner)
{
cout<<GetNameOfEntity(entMiner)<<"ok,honey"<<endl;
}
void CEat::Execute(CMiner*pMiner)
{
cout<<GetNameOfEntity(entMiner)<<"haha ,good meat"<<endl;
pMiner->SetFatigue(-3);
if (pMiner->FeelComfort())
{
pMiner->GetStateMachine()->ChangeState(CGoMineAndDig::GetInstance());
}
}
void CEat::Exit(CMiner*pMiner)
{
cout<<GetNameOfEntity(entMiner)<<"honey,food enough,I will go to work"<<endl;
}
bool CEat::OnMessage(CMiner*pMiner,const MESSAGE& msg)
{
return false;
}
再實現Ellsa的狀態:
#include "WifeState.h"
#include "DispatchMessage.h"
CGlobalState* CGlobalState::GetInstance()
{
static CGlobalState global;
return &global;
}
void CGlobalState::Enter(CWife* pWife)
{
cout<<GetNameOfEntity(entWife)<<"this is global state"<<endl;
}
void CGlobalState::Execute(CWife*pWife)
{
if (Rand(10)==1)
{
cout<<GetNameOfEntity(entWife)<<"now I will go to toilet"<<endl;
pWife->GetStateMachine()->ChangeState(CGoToilet::GetInstance());
}
}
void CGlobalState::Exit(CWife*)
{
}
bool CGlobalState::OnMessage(CWife*pWife,const MESSAGE& msg)
{
switch(msg.msg)
{
case msgHiIGoHome:
cout<<GetNameOfEntity(entWife)<<"ok,honey,I will cook."<<endl;
pWife->GetStateMachine()->ChangeState(CCook::GetInstance());
return true;
default:
return false;
}
}
CDoHouseWork* CDoHouseWork::GetInstance()
{
static CDoHouseWork h;
return &h;
}
void CDoHouseWork::Enter(CWife*)
{
cout<<GetNameOfEntity(entWife)<<"now I am busy"<<endl;
}
void CDoHouseWork::Execute(CWife*)
{
switch(Rand(5))
{
case 1:
cout<<GetNameOfEntity(entWife)<<"wash clothes"<<endl;
break;
case 2:
cout<<GetNameOfEntity(entWife)<<"mop the floor"<<endl;
break;
case 3:
cout<<GetNameOfEntity(entWife)<<"clean the table"<<endl;
break;
default:
cout<<GetNameOfEntity(entWife)<<"have a cup of tea"<<endl;
break;
}
}
void CDoHouseWork::Exit(CWife*)
{
}
bool CDoHouseWork::OnMessage(CWife*,const MESSAGE& msg)
{
switch(msg.msg)
{
case msgCookOk:
cout<<GetNameOfEntity(entWife)<<"cook ok ,come here"<<endl;
CDispatchMessage::GetInstance()->SendMessage(0,entWife,entMiner,msgCookOk,NULL);
return true;
default:
return false;
}
}
CGoToilet* CGoToilet::GetInstance()
{
static CGoToilet t;
return &t;
}
void CGoToilet::Enter(CWife*)
{
cout<<GetNameOfEntity(entWife)<<"urgent thing"<<endl;
}
void CGoToilet::Execute(CWife*pWife)
{
cout<<GetNameOfEntity(entWife)<<"relax ,ZZZZZZZZZZZZZZZ"<<endl;
pWife->GetStateMachine()->RevertToPreviousState();
}
void CGoToilet::Exit(CWife*)
{
}
bool CGoToilet::OnMessage(CWife*,const MESSAGE& msg)
{
switch(msg.msg)
{
case msgCookOk:
cout<<GetNameOfEntity(entWife)<<"cook ok ,come here"<<endl;
CDispatchMessage::GetInstance()->SendMessage(0,entWife,entMiner,msgCookOk,NULL);
return true;
default:
return false;
}
}
CCook* CCook::GetInstance()
{
static CCook c;
return &c;
}
void CCook::Enter(CWife*)
{
cout<<GetNameOfEntity(entWife)<<"now ,I am cooking"<<endl;
}
void CCook::Execute(CWife*pWife)
{
cout<<GetNameOfEntity(entWife)<<"flip the timer switch of even"<<endl;
CDispatchMessage::GetInstance()->SendMessage(0.25,entWife,entWife,msgCookOk,NULL);
cout<<GetNameOfEntity(entWife)<<"please reminder me"<<endl;
pWife->GetStateMachine()->ChangeState(CDoHouseWork::GetInstance());
}
void CCook::Exit(CWife*)
{
}
bool CCook::OnMessage(CWife*,const MESSAGE& msg)
{
switch(msg.msg)
{
case msgCookOk:
cout<<GetNameOfEntity(entWife)<<"cook ok ,come here"<<endl;
CDispatchMessage::GetInstance()->SendMessage(0,entWife,entMiner,msgCookOk,NULL);
return true;
default:
return false;
}
}
全域性函式:
#pragma once
#include <iostream>
#include <string>
#include <stdlib.h>
#include <time.h>
#include <Windows.h>
using namespace std;
//#define NULL 0;
enum Entity
{
entMiner,entWife
};
inline string GetNameOfEntity(int id)
{
switch(id)
{
case entMiner:
return "Miner Bob: ";
case entWife:
return "Wife Ellsa: ";
default:
return "unknown";
}
}
enum LocationType
{
GoldMine,shack,bank,bar
};
inline int Rand(int seed)
{
srand(unsigned int (time(NULL)));
return rand()%seed;
}
最後總整合:
#include "stdafx.h"
#include "Miner.h"
#include "Wife.h"
#include "DispatchMessage.h"
int main()
{
CEntityBase* Bob=new CMiner(entMiner);
CEntityBase* Ellsa=new CWife(entWife);
CEntityManager::GetInstance()->EntityRegister(Bob->GetID(),Bob);
CEntityManager::GetInstance()->EntityRegister(Ellsa->GetID(),Ellsa);
for (int i=0;i<100;i++)
{
Bob->Update();
Ellsa->Update();
CDispatchMessage::GetInstance()->SendDelayMessage();
Sleep(800);
}
delete Bob;
delete Ellsa;
system("pause");
return 0;
}
http://www.aibbt.com/a/13786.html
相關文章
- 訊息佇列Kafka學習總結佇列Kafka
- MySQL專案實戰總結MySql
- 學成線上專案總結 - Day5 RabbitMQ訊息佇列MQ佇列
- android學習視訊(實戰專案演練)Android
- 實習專案開發總結
- 吐血總結!10個Python實戰專案(附原始碼)Python原始碼
- 實戰專案後對 React Hooks 總結ReactHook
- 【Javascript】DOM程式設計學習總結篇JavaScript程式設計
- 知乎專案程式碼閱後總結
- 去哪兒網專案學習總結
- 伺服器專案實戰與總結(五)伺服器
- 密碼學系列——訊息摘要(c#程式碼實操)密碼學C#
- NestJS學習總結篇JS
- PHP程式碼審計學習總結PHP
- 十餘行程式碼完成遷移學習,PaddleHub實戰篇行程遷移學習
- TensorFlow 2.0 程式碼實戰專欄開篇
- iOS專案開發實戰——實現蘋果本地訊息通知推送服務iOS蘋果
- Java專案中MongoDb學習和使用總結JavaMongoDB
- 小程式實戰踩坑之B2B商城專案總結
- 小程式專案總結
- 小程式專案-總結
- iOS 點選推送訊息跳轉指定介面 —總結篇iOS
- 【深度學習】深度學習md筆記總結第1篇:深度學習課程,要求【附程式碼文件】深度學習筆記
- DDD實戰課(實戰篇)--學習筆記筆記
- Snmp學習總結系列——開篇
- RabbitMQ實戰:理解訊息通訊MQ
- 「實戰篇」開源專案docker化運維部署(終結篇)(11)Docker運維
- 小程式學習總結
- maven 學習總結(三)——使用Maven構建專案Maven
- 訊息佇列mq總結佇列MQ
- 專案(FBMS)總結-管理篇(4)
- 專案(FBMS)總結-管理篇(3)
- 專案(FBMS)總結-管理篇(2)
- 專案(FBMS)總結-管理篇(1)
- 專案(FBMS)總結-簡介篇
- 微信小程式學習總結01:專案結構中增加業務邏輯目錄微信小程式
- SonarQube學習(三)- 專案程式碼掃描
- 深度學習專案實戰:垃圾分類系統深度學習