日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

双人贪吃蛇@botzone算法设计

發(fā)布時(shí)間:2023/12/14 编程问答 77 豆豆
生活随笔 收集整理的這篇文章主要介紹了 双人贪吃蛇@botzone算法设计 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

單人貪吃蛇游戲的一般算法思路是進(jìn)行前向預(yù)測,尋找空間最大的可能走法。
雙人對戰(zhàn)中,對方的走法不確定,必須加以預(yù)測。此外,還可以堵截對方的權(quán)值。
為了實(shí)現(xiàn)以上目的,需要對于己方蛇體、對方蛇體、地圖障礙物進(jìn)行建模。建立局面對象包含全部信息,每移動一個(gè)回合遞歸復(fù)制局面對象,以某種規(guī)則預(yù)測對手行為進(jìn)行更新。

需要傳遞的數(shù)據(jù)有:
- 地圖信息(本游戲中為靜態(tài),故傳全局指針單一對象)
- 對方蛇所在位置
- 我方蛇所在位置
- 蛇歷史運(yùn)動數(shù)據(jù)*

可以供決策的技術(shù)指標(biāo):
1. 近步成殺。即按照這一走法,己方不死,對方無論怎么走都會死。該情況屬于硬性勝利條件,只要存在即實(shí)施,無須再看其他指標(biāo)。
2. 自己不死的自由度大小,對方可假設(shè)為路徑貪心:適用于敵人的模型,假設(shè)對手(我)為不動,選取可行步數(shù)最長的方向
3. 連通性分析尋找關(guān)鍵通道,力求將對方包圍在盡量小的封閉區(qū)域內(nèi)。應(yīng)用最短路徑算法,對于每個(gè)方格假設(shè)按最短路徑到達(dá),則令對方到達(dá)各方格最曲折甚至不能到達(dá)的就是最優(yōu)路徑。
有一點(diǎn)需要注意,即不同的路徑有不同的長度,我們在評價(jià)最優(yōu)的時(shí)候需要排除單純由于走的路線長占據(jù)的格點(diǎn)多而使得對方無路可走。這種“最優(yōu)”是被動的,因?yàn)闀p易被對方的移動所攪亂,故不具有實(shí)用性。解決方法是將評價(jià)函數(shù)S設(shè)置為:
S=SUM(1/(1+對方的可行方格數(shù)的步數(shù)))+自身步數(shù)/6

然后取MAXS-S最大的前幾個(gè)方案,按照初始方向累加,返回最大的方向和對應(yīng)權(quán)值。
其中MAXS是S的最大值,超過此值就沒意義了不合格。
4. 貼近對方,并且自己能逃脫


搜索最短路徑使用dijistra算法,使用小頂堆尋找未放入連通子圖的最近的頂點(diǎn)。
從堆頂取出頂點(diǎn)時(shí),關(guān)心的是其值和坐標(biāo);
在更新頂點(diǎn)的值的時(shí)候,需要修改指定坐標(biāo)頂點(diǎn)的值,然后修正堆(也可以刪除指定頂點(diǎn),修改值后重新插入)。需要通過坐標(biāo)索引小頂堆的位置;
于是,我們需要一個(gè)數(shù)據(jù)結(jié)構(gòu)具有雙向指向功能

為了加快移動速度,節(jié)省空間,小頂堆中存儲的都是指針

typedef struct _Block {int val; //地圖中的距離int index; //堆中的索引值//int xy=x*MAX_MAP+y; //地圖中的坐標(biāo) 直接用數(shù)組索引值替代了 }Block; Block *heap[MAX_MAP*MAX_MAP];


小頂堆的精髓在于,使用數(shù)組順序存儲時(shí),若以1作為堆頂索引號,則任意一個(gè)節(jié)點(diǎn)i,父節(jié)點(diǎn)索引為i/2,左子節(jié)點(diǎn)索引為2*i

添加節(jié)點(diǎn)時(shí)從數(shù)組尾部,不斷比較大小上浮即可

for(i = ++Size; Elements[i/2]>X; i/=2)Elements[i]=H->Elements[i/2 ]; Elements[i]=X;


移除堆頂時(shí),也是同樣的策略從上到下將小元素逐個(gè)上浮。有一個(gè)特殊情況需要處理:設(shè)堆最后一個(gè)元素是L,在推進(jìn)到倒數(shù)第二層時(shí),可能使得最后一層的某個(gè)孩子被換上去而產(chǎn)生一個(gè)洞。為了保持堆的結(jié)構(gòu),必須把最后一個(gè)元素運(yùn)過去補(bǔ)上,此時(shí)如果L比那個(gè)孩子小的話就不能保證堆序的性質(zhì)了。例如:

[] 4 3 ______\ 6 4 3 ______\ 6 4 3 6 6 7 7 4 4 ______/ 6 [] 7 7 4 4 ______/ 6 4 7 7 4 []

解決方法是每一級判斷子元素是否大于最后一個(gè)元素,如果大于,則應(yīng)該直接把最后一個(gè)元素移動上來,然后終止向下過程返回。

MinElement=Elements[1]; LastElement=Elements[Size--];for(i=1;i*2<=Size;i=Child) {/* Find smaller child */Child =i*2;if(Child!=Size && Elements[Child+1] <Elements[Child])Child++;/* Percolate one level */if(LastElement>Elements[Child])Elements[i]=Elements[Child];elsebreak;}Elements[i]=LastElement;


最短路徑算法中,頻繁出現(xiàn)的是對于堆中元素的修改操作,相應(yīng)的調(diào)整堆算法如下:

void ChangeAt(int index) if(Elements[i]<Elements[i/2]) {//改小了,應(yīng)該上浮for(ChangedElement=Elements[i]; ChangedElement<Elements[i/2]; i/=2)Elements[i]=Elements[i/2]; Elements[i]=ChangedElement; }else if(i*2>size) { return; //下面沒東西 不用改 } else if(Elements[i]>( Size==i*2 ? Elements[i*2]:MIN(Elements[i*2],Elements[i*2+1])) ) {//改大了,應(yīng)該下沉for(ChangedElement=Elements[i]; i*2<=Size;i=Child){/* Find smaller child */Child =i*2;if(Child!=Size && Elements[Child+1] <Elements[Child])Child++;/* Percolate one level */if(ChangedElement > Elements[Child]){Elements[i]=Elements[Child];}else{break;}}Elements[i]=ChangedElement; } else {//沒改多少,不用修正return; }


以上算法均為針對常規(guī)數(shù)值,本程序中需要改寫為指針數(shù)據(jù)進(jìn)行訪問,且每次數(shù)據(jù)移動都需要增加相應(yīng)修改index的步驟。例如,insert()中

for(i = ++heap_size; heap[i/2]->val > x->val; i/=2){heap[i]=heap[i/2];heap[i]->index=i;}heap[i]=x;heap[i]->index=i;

代碼見 https://github.com/merfii/DoubleSnakeAI

總結(jié)

以上是生活随笔為你收集整理的双人贪吃蛇@botzone算法设计的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。