国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

AI自動尋路AStar算法【圖示講解原理】

這篇具有很好參考價值的文章主要介紹了AI自動尋路AStar算法【圖示講解原理】。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

AI自動尋路AStar算法

背景

AI自動尋路的算法可以分為以下幾種:

1、A*算法:A*算法是一種啟發(fā)式搜索算法,它利用啟發(fā)函數(shù)(heuristic function)來評估節(jié)點的估價函數(shù)(estimated cost function),從而尋找最短路徑。A*算法綜合考慮了節(jié)點的實際代價到目標(biāo)節(jié)點的預(yù)計代價,因此能夠快速而準(zhǔn)確地尋找最短路徑【不一定最短,A*算法并不一定能夠找到最短路徑,但它通常可以找到接近最短路徑的解決方案。】

2、Dijkstra算法:Dijkstra算法是一種貪心算法,它從起點開始,每次選擇當(dāng)前代價最小的節(jié)點作為下一個節(jié)點。通過不斷更新節(jié)點的代價,最終可以找到起點到終點的最短路徑。

3、Bellman-Ford算法:Bellman-Ford算法是一種動態(tài)規(guī)劃算法,它通過不斷更新節(jié)點的代價,直到收斂到最短路徑。相比于Dijkstra算法,Bellman-Ford算法能夠處理負(fù)權(quán)邊的情況。

4、Floyd-Warshall算法:Floyd-Warshall算法是一種動態(tài)規(guī)劃算法,它能夠計算出圖中任意兩點之間的最短路徑。Floyd-Warshall算法通過不斷更新節(jié)點之間的代價,直到收斂到最短路徑。


這些算法都可以用于AI自動尋路,具體選擇哪種算法需要根據(jù)具體的應(yīng)用場景和性能要求進(jìn)行選擇。

隨著 3D 游戲的日趨流行,在復(fù)雜的 3D 游戲環(huán)境中如何能使非玩家控制角色準(zhǔn)確實現(xiàn)自動尋路功能成為了 3D 游戲開
發(fā)技術(shù)中一大研究熱點。其中 A*算法得到了大量的運(yùn)用,A*算法較之傳統(tǒng)的路徑規(guī)劃算法,實時性更高、靈活性更強(qiáng),尋路
結(jié)果更加接近人工選擇的路徑結(jié)果. A*尋路算法并不是找到最優(yōu)路徑,只是找到相對近的路徑,因為找最優(yōu)要把所有可行
路徑都找出來進(jìn)行對比,消耗性能太大,尋路效果只要相對近路徑就行了。
所以對于自動尋路,A*算法是一個很不錯的選擇?。?!
AI自動尋路AStar算法【圖示講解原理】


AStar算法原理

我們假設(shè)在推箱子游戲中人要從站里的地方移動到右側(cè)的箱子目的地,但是這兩點之間被一堵墻隔開。
AI自動尋路AStar算法【圖示講解原理】

我們下一步要做的便是查找最短路徑。既然是 AI 算法, A* 算法和人尋找路徑的做法十分類似,當(dāng)我們離目標(biāo)較遠(yuǎn)時,我
們的目標(biāo)方向是朝向目的點直線移動,但是在近距離上因為各種障礙需要繞行(走彎路)!而且已走過的地方就無須再次
嘗試。
為了簡化問題,我們把要搜尋的區(qū)域劃分成了正方形的格子。這是尋路的第一步,簡化搜索區(qū)域,就像推箱子游戲一樣。
這樣就把我們的搜索區(qū)域簡化為了 2 維數(shù)組。數(shù)組的每一項代表一個格子,它的狀態(tài)就是可走 (walkalbe) 和不可走
(unwalkable) 。通過計算出從起點到終點需要走過哪些方格,就找到了路徑。一旦路徑找到了,人物便從一個方格的中心
移動到另一個方格的中心,直至到達(dá)目的地。

簡化搜索區(qū)域以后,如何定義小人當(dāng)前走要走的格子離終點是近是遠(yuǎn)呢?我們需要兩個指標(biāo)來表示:
1、 G 表示從起點移動到網(wǎng)格上指定方格的移動距離 (暫時不考慮沿斜向移動,只考慮上下左右移動)。
2、 H 表示從指定的方格移動到終點預(yù)計移動距離,只計算直線距離 (H 有很多計算方法, 這里我們設(shè)定只可以上
下左右移動,即該點與終點的直線距離)。
AI自動尋路AStar算法【圖示講解原理】
令 F = G + H ,F(xiàn) 即表示從起點經(jīng)過此點預(yù)計到終點的總移動距離


AStar尋路步驟

1、從起點開始, 把它作為待處理的方格存入一個預(yù)測可達(dá)的節(jié)點列表,簡稱 openList, 即把起點放入“預(yù)測可達(dá)節(jié)點列表”,可達(dá)節(jié)點列表 openList 就是一個等待檢查方格的列表

2、尋找 openList 中 F 值最小的點 min(一開始只有起點)周圍可以到達(dá)的方格(可到達(dá)的意思是其不是障礙物,也不存在關(guān)閉列表中的方格,即不是已走過的方格)。計算 min 周圍可到達(dá)的方格的 F 值。將還沒在 openList 中點放入其中, 并設(shè)置它們的"父方格"為點 min,表示他們的上一步是經(jīng)過 min 到達(dá)的。如果 min 下一步某個可到達(dá)的方格已經(jīng)在 openList列表那么并且經(jīng) min 點它的 F 值更優(yōu),則修改 F 值并把其"父方格"設(shè)為點 min。

3、把 2 中的點 min 從"開啟列表"中刪除并存入"關(guān)閉列表"closeList 中【當(dāng)自己對四周擴(kuò)散時,將自己放入到closeList中】, closeList 中存放的都是不需要再次檢查的方格。如果 2 中點 min 不是終點并且開啟列表的數(shù)量大于零,那么繼續(xù)從第 2 步開始。如果是終點執(zhí)行第 4 步,如果 openList 列表數(shù)量為零,那么就是找不到有效路徑。

4、如果第 3 步中 min 是終點,則結(jié)束查找,直接追溯父節(jié)點到起點的路徑即為所選路徑


AStar具體尋路過程

AI自動尋路AStar算法【圖示講解原理】


AI自動尋路AStar算法【圖示講解原理】


AI自動尋路AStar算法【圖示講解原理】


AI自動尋路AStar算法【圖示講解原理】


AI自動尋路AStar算法【圖示講解原理】


AI自動尋路AStar算法【圖示講解原理】


AI自動尋路AStar算法【圖示講解原理】


AI自動尋路AStar算法【圖示講解原理】


AI自動尋路AStar算法【圖示講解原理】
AI自動尋路AStar算法【圖示講解原理】


AI自動尋路AStar算法【圖示講解原理】


AI自動尋路AStar算法【圖示講解原理】


AI自動尋路AStar算法【圖示講解原理】


AI自動尋路AStar算法【圖示講解原理】


AI自動尋路AStar算法【圖示講解原理】


AI自動尋路AStar算法【圖示講解原理】


AI自動尋路AStar算法【圖示講解原理】


AI自動尋路AStar算法【圖示講解原理】
最后通過父子關(guān)系將一條起點到終點的路徑完整的描述出來


AStar代碼實現(xiàn)

Astar.h

#pragma once
#include<list>//鏈表
#include<vector>
const int k_Cost1 = 10;//走一格消耗10
const int k_Cost2 = 14;//斜移走一個消耗14

typedef struct _Point {
	int x, y;  //x為行,y為列
	int F, G, H;  //F=G+H;
	struct _Point* parent;  //父節(jié)點的坐標(biāo)
}Point;

//分配一個節(jié)點
Point* AllocPoint(int x, int y);


//初始化地圖,地圖,行,列
void InitAstarMaze(int* _maze, int _line, int _colums);

//通過A*算法尋找路徑
std::list<Point*>GetPath(const Point* startPoint, const Point* endPoint);


//查找路徑的小方法,返回一個終點,根據(jù)終點可以回溯到起點
static Point* findPath(const Point* startPoint, const Point* endPoint);//用static是為了只能在函數(shù)內(nèi)部調(diào)用而不能單獨(dú)的使用

//返回開放列表中F的最小值的點
static Point* getLeastFPoint();

//獲取周圍的節(jié)點
static std::vector<Point*> getSurroundPoint(const Point* point);

//某個點是否可達(dá)
static bool isCanreach(const Point* point, const Point* target);

//是否存在某個list中,這里用作是否存在closeList/openList中
static Point* isInList(const std::list<Point*>& list, const Point* point);

//獲取G,H,F(xiàn)
static int caloG(const Point* temp_start, const Point* point);
static int caloH(const Point* point, const Point* end);
static int caloF(const Point* point);

//清理資源
void clearAstarMaze();

Astar.cpp

#include"Astar.h"
#include<cmath>
#include<iostream>
#include<vector>
//extern int k_Cost1;
//extern int k_Cost2;

static int* maze;//初始化迷宮
static int cols;//二維數(shù)組對應(yīng)的列
static int lines;//二維數(shù)組對應(yīng)的行

static std::list<Point*>openList;  //開放列表
static std::list<Point*>closeList; //關(guān)閉列表


/*初始化地圖*/
void InitAstarMaze(int* _maze, int _line, int colums) {//一級指針保存二維數(shù)組
	maze = _maze;
	lines = _line;
	cols = colums;
}

/*分配節(jié)點*/
Point* AllocPoint(int x, int y) {
	Point* temp = new Point;
	memset(temp, 0, sizeof(Point));//清理養(yǎng)成好習(xí)慣

	temp->x = x;
	temp->y = y;
	return temp;
}

/*通過A*算法尋找路徑*/
std::list<Point*>GetPath(const Point* startPoint, const Point* endPoint) {
	Point *result = findPath(startPoint, endPoint);
	std::list<Point*>path;

	//返回路徑
	while (result) {
		path.push_front(result);//這樣起點就是在這個鏈表的最前面了
		result = result->parent;
	}

	return path;

}

/*查找路徑的小方法,返回一個終點,根據(jù)終點可以回溯到起點*/
static Point* findPath(const Point* startPoint, const Point* endPoint) {
	openList.push_back(AllocPoint(startPoint->x, startPoint->y));//重新分配更加的安全,置入起點

	while (!openList.empty()) {
		//1、獲取開放表中最小的F值
		Point* curPoint = getLeastFPoint();

		//2、把當(dāng)前節(jié)點放到closeList中
		openList.remove(curPoint);
		closeList.push_back(curPoint);

		//3、找到當(dāng)前節(jié)點周圍可到達(dá)的節(jié)點并計算F值
		std::vector<Point*> surroundPoints = getSurroundPoint(curPoint);

		std::vector<Point*>::const_iterator iter;
		for (iter = surroundPoints.begin(); iter != surroundPoints.end(); iter++) {
			Point* target = *iter;

			//如果沒在開放列表中就加入到開放列表,設(shè)置當(dāng)前節(jié)點為父節(jié)點
			Point* exist = isInList(openList, target);
			if (!exist) {

				target->parent = curPoint;
				target->G = caloG(curPoint, target);//父節(jié)點的G加上某個數(shù)就好(自己設(shè)計的)
				target->H = caloH(target, endPoint);
				target->F = caloF(target);

				openList.push_back(target);
			}
			else {//如果已存在就重新計算G值看要不要替代
				int tempG = caloG(curPoint, target);
				if (tempG < target->G) {//更新
					exist->parent = curPoint;
					exist->G = tempG;
					exist->F = caloF(target);
				}

				delete *iter;
			}

		}//end for循環(huán)

		surroundPoints.clear();
		Point* resPoint = isInList(openList, endPoint);//終點是否在openList上
		if (resPoint) {
			return resPoint;
		}


	}


	return NULL;
}

//返回開放列表中F的最小值的點
static Point* getLeastFPoint() {
	//遍歷
	if (!openList.empty()) {
		Point* resPoint = openList.front();

		std::list<Point*>::const_iterator itor;//定義迭代器,用于遍歷鏈表

		//迭代器遍歷,C++特性,直接理解成平時我們用的for
		for (itor = openList.begin(); itor != openList.end(); itor++) {
			Point* p = *itor;//把元素拿出來
			if (p->F < resPoint->F) {
				resPoint = p;
			}
		}
		return resPoint;
	}
	return NULL;
}

/*獲取周圍的節(jié)點*/
static std::vector<Point*> getSurroundPoint(const Point* point) {
	std::vector<Point*>surroundPoints;
	//周圍九個點都會進(jìn)行檢測
	for (int x = point->x - 1; x <= point->x + 1; x++) {
		for (int y = point->y - 1; y <= point->y + 1; y++) {
			Point* temp = AllocPoint(x, y);
			if (isCanreach(point, temp)) {
				surroundPoints.push_back(temp);
			}
			else {
				delete temp;
			}
		}
	}
	return surroundPoints;
}


/*某個點是否可達(dá)*/
static bool isCanreach(const Point* point, const Point* target) {
	if (target->x<0 || target->x>(lines - 1)
		|| target->y<0 || target->y>(cols - 1)
		|| (maze[target->x * cols + target->y] == 1)//找到對應(yīng)的二維數(shù)組中的位置-》障礙物
		|| (maze[target->x * cols + target->y] == 2)
		|| (target->x == point->x && target->y == point->y)
		|| isInList(closeList, target)) {
		return false;

	}

	if (abs(point->x - target->x) + abs(point->y - target->y) == 1) {//我們現(xiàn)在只考慮上下左右4個點
		return true;
	}
	else {
		return false;
	}
}


/*是否存在某個list中,這里用作是否存在closeList/openList中*/
static Point* isInList(const std::list<Point*>& list, const Point* point) {
	std::list<Point*>::const_iterator itor;
	for (itor = list.begin(); itor != list.end(); itor++) {
		if ((*itor)->x == point->x && (*itor)->y == point->y) {
			return *itor;  //存在返回該節(jié)點
		}
	}
	return NULL;
}

static int caloG(const Point* temp_start, const Point* point) {
	int extraG = (abs(point->x - temp_start->x) + abs(point->y - temp_start->y)) == 1 ? k_Cost1 : k_Cost2;//周圍的點與擴(kuò)散點的差值,是否為斜邊
	int parentG = (point->parent == NULL ? NULL : point->parent->G);//如果是初始值為null,其他的點是父類的G值
	return parentG + extraG;//返回兩個量相加
}

static int caloH(const Point* point, const Point* end) {
	//歐幾里得求斜邊
	return (int)sqrt((double)(end->x - point->x) * (double)(end->x - point->x)) + (double)(end->y - point->y) * (double)(end->y - point->y) * k_Cost1;

}

static int caloF(const Point* point) {
	return point->G + point->H;
}

/*清理資源*/
void clearAstarMaze() {
	maze = NULL;
	lines = 0;
	cols = 0;
	std::list<Point*>::iterator itor;
	for (itor = openList.begin(); itor != openList.end();) {
		delete* itor;
		itor = openList.erase(itor);//獲取到下一個節(jié)點
	}
	for (itor = closeList.begin(); itor != closeList.end();) {
		delete* itor;
		itor = closeList.erase(itor);//獲取到下一個節(jié)點
	}
}

main.cpp

#include<iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include"Astar.h"
using namespace std;
int map[13][13] = {
{0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,1,0,1,0,1,0,1,0,1,0,1,0},
{0,1,0,1,0,1,0,1,0,1,0,1,0},
{0,1,0,1,0,1,2,1,0,1,0,1,0},
{0,1,0,1,0,1,0,1,0,1,0,1,0},
{0,1,0,1,0,0,0,1,0,1,0,1,0},
{0,0,0,0,0,1,0,1,0,0,0,0,0},
{2,0,1,1,0,0,0,1,0,1,0,0,2},
{0,0,0,0,0,1,1,1,0,0,0,0,0},
{0,1,0,1,0,1,0,1,0,1,0,1,0},
{0,1,0,1,0,1,0,1,0,1,0,1,0},
{0,1,0,1,0,0,0,0,0,1,0,1,0},
{0,0,0,0,0,1,3,1,0,0,0,0,0}
};
void astarTest() {

	InitAstarMaze(&map[0][0], 13, 13);
	//設(shè)置
	Point* start = AllocPoint(12, 4);
	Point* end = AllocPoint(0, 12);

	//尋找路徑
	list<Point*>path = GetPath(start, end);

	//設(shè)置迭代器遍歷
	list<Point*>::const_iterator iter;//迭代器

	cout << "(" << start->x << "," << start->y << ")" << "------>(" << end->x << "," << end->y << ")" << endl;
	cout << "****************** 尋路結(jié)果 ********************************" << endl;
	for (iter = path.begin(); iter != path.end(); ) {
		Point* cur = *iter;
		cout << '(' << cur->x << "," << cur->y << ')' << endl;
		//delete cur;//不用再進(jìn)行釋放了因為在openList和closeList鏈表中我們最后都有清理,如果再清理就會報錯
		iter = path.erase(iter);
		Sleep(800);  //休眠
	}
	clearAstarMaze();
}
int main() {
	astarTest();
	system("pause");
	return 0;
}

運(yùn)行結(jié)果

AI自動尋路AStar算法【圖示講解原理】文章來源地址http://www.zghlxwxcb.cn/news/detail-418453.html

到了這里,關(guān)于AI自動尋路AStar算法【圖示講解原理】的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 自動駕駛路徑規(guī)劃——A*(Astar)算法

    自動駕駛路徑規(guī)劃——A*(Astar)算法

    ???? 最佳優(yōu)先搜索(BFS) ,又稱A算法,是一種啟發(fā)式搜索算法(Heuristic Algorithm)。[不是廣度優(yōu)先搜索算法( Breadth First Search , BFS )] ????BFS算法在廣度優(yōu)先搜索的基礎(chǔ)上, 用啟發(fā)估價函數(shù)對將要被遍歷到的點進(jìn)行估價 ,然后選擇代價小的進(jìn)行遍歷,直到找到目標(biāo)節(jié)點

    2024年02月01日
    瀏覽(65)
  • Unity 中 A*尋路(AStar,A星)的優(yōu)化,二叉堆,雙向隊列,哈希表

    前篇:A星尋路的簡單實現(xiàn) A星尋路,在2D地圖下使用頻率較高 本篇基于上一篇文章實現(xiàn)的A星尋路進(jìn)一步優(yōu)化。利用二叉堆代替了原先openList的數(shù)據(jù)結(jié)構(gòu), 改進(jìn)了path返回時的操作,以及在搜索時的性能開銷。 c#中的Sort函數(shù),在實現(xiàn)方面采用的是快速排序。 在日常的使用上,好

    2024年02月03日
    瀏覽(19)
  • Unity AI Navigation自動尋路

    Unity AI Navigation自動尋路

    Unity是一款強(qiáng)大的游戲開發(fā)引擎,而人工智能(AI)導(dǎo)航是游戲中至關(guān)重要的一部分。通過Unity的AI Navigation系統(tǒng),開發(fā)者可以輕松地為游戲中的角色實現(xiàn)自動導(dǎo)航功能。本文將介紹Unity中AI Navigation的基礎(chǔ)內(nèi)容,幫助開發(fā)者快速入門。 Unity中的AI Navigation是一套用于游戲開發(fā)的導(dǎo)

    2024年04月16日
    瀏覽(23)
  • unity的AI自動尋路navigation基本用法

    unity的AI自動尋路navigation基本用法

    ?1.場景中的地面和障礙物都設(shè)置成靜態(tài)的, ?2.給需要尋路的AI物體添加Nav Mesh Agent 組件, 3在window下面找到navigation,打開選all,調(diào)好參數(shù)后點擊bake 4.運(yùn)行時用代碼實現(xiàn)鼠標(biāo)點擊屏幕一點,AI就自動避讓障礙物到達(dá)(代碼在下面) ? ? ?

    2024年02月11日
    瀏覽(27)
  • unity有限狀態(tài)機(jī)和模糊狀態(tài)機(jī)(怪物AI、自動尋路)

    unity有限狀態(tài)機(jī)和模糊狀態(tài)機(jī)(怪物AI、自動尋路)

    自動尋路步驟: 1、把場景中不同的物體勾選static 2、烘培尋路網(wǎng)格 3、添加NavMeshAgent組件 4、給需要尋路的物體添加腳本 游戲中有限狀態(tài)機(jī)的體現(xiàn):小怪的巡邏和追逐功能 模糊狀態(tài)機(jī)的體現(xiàn):當(dāng)玩家離小怪比較近時,小怪會追逐玩家,當(dāng)玩家離小怪比較遠(yuǎn)時小怪會停止追逐玩

    2024年02月04日
    瀏覽(25)
  • 【ROS-Navigation】—— Astar路徑規(guī)劃算法解析

    【ROS-Navigation】—— Astar路徑規(guī)劃算法解析

    ????最近在學(xué)習(xí)ROS的navigation部分,寫些東西作為筆記,方便理解與日后查看。本文從Astar算法入手,對navigation源碼進(jìn)行解析。 PS:ros navigation源碼版本https://gitcode.net/mirrors/ros-planning/navigation/-/tree/noetic-devel ????對于Astar算法,想必大家都非常熟悉了。具體算法原理就不

    2024年01月18日
    瀏覽(56)
  • 【Unity】一篇文章搞定AStar(A*)算法

    【Unity】一篇文章搞定AStar(A*)算法

    AStar(A*)算法,是一種在靜態(tài)網(wǎng)格中求解最短路徑直接有效的搜索方法。在游戲開發(fā)中,A*算法常應(yīng)用于部分RPG游戲和策略戰(zhàn)棋類游戲。對于Unity開發(fā)者來說,掌握A*算法也是十分有必要的。不過在了解A*算法之前,有必要先回顧一下深度優(yōu)先算法(DFS)、廣度優(yōu)先算法(BFS)

    2024年02月02日
    瀏覽(20)
  • 【Unity】Unity尋路系統(tǒng)講解及Navigation實際應(yīng)用

    【Unity】Unity尋路系統(tǒng)講解及Navigation實際應(yīng)用

    Unity常用的尋路方式主要有以下幾種: 路點尋路(WayPoint) 單元格尋路(Grid) 導(dǎo)航系統(tǒng)(Navigation) 路點尋路就是在地圖上指定一些路點,讓角色在路點之間移動。常用于一些固定路線的敵人或物體。 優(yōu)點:路點尋路的優(yōu)點是實現(xiàn)起來比較簡單,且占用資源少、計算開銷低

    2024年02月01日
    瀏覽(62)
  • 【Unity自動尋路】使用Navigation系統(tǒng)實現(xiàn)物體自動尋路繞開障礙物

    【Unity自動尋路】使用Navigation系統(tǒng)實現(xiàn)物體自動尋路繞開障礙物

    知識點流程圖 我們在游戲場景中經(jīng)常會有一些障礙物、墻壁、樹木等等,如果我想要讓角色或者怪物去墻的另一邊,我直接在墻另一邊點擊左鍵,我希望角色自動跑過去,但是他不能直接穿透墻,他需要“智能”的繞開障礙物,自動找到可以走的路,自己過去!這就是Unity

    2024年02月03日
    瀏覽(25)
  • 遺傳算法原理詳細(xì)講解(算法+Python源碼)

    遺傳算法原理詳細(xì)講解(算法+Python源碼)

    博主介紹:?專研于前后端領(lǐng)域優(yōu)質(zhì)創(chuàng)作者、本質(zhì)互聯(lián)網(wǎng)精神開源貢獻(xiàn)答疑解惑、堅持優(yōu)質(zhì)作品共享、掘金/騰訊云/阿里云等平臺優(yōu)質(zhì)作者、擅長前后端項目開發(fā)和畢業(yè)項目實戰(zhàn),深受全網(wǎng)粉絲喜愛與支持?有需要可以聯(lián)系作者我哦! ??文末獲取源碼聯(lián)系?? ???? 精彩專欄

    2024年01月25日
    瀏覽(34)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包