演算法實現自動掃雷遊戲

2021-10-12 03:04:25 字數 3743 閱讀 3922

1.遊戲的構思

2.演算法偽**的實現

3.演算法的實現

1.首先需要建立起遊戲的整個框架(棋盤的繪製,地雷的生成,基本函式的實現等)

2.構思ai演算法的大概樣貌(先嘗試寫偽碼)

voidai(

)//ai演算法

if(first)

selectrandompos()

//遊戲開始隨機選擇一處位置翻開

selectpos()

//根據已有條件選擇最佳翻開位置if(

!gameover)ai(

)//遞迴繼續進行選擇,直到遊戲結束

3.簡單的偽碼寫好後,接下來應該來思考如何具體實現這一演算法

3.1對於selectrandompos()實現隨機位置,我們可以使用

col =

(rand()

)%colnum;

row =

(rand()

)%rownum;

//col,row為隨機翻開的行列座標

//colnum和rownum為總的行列數

//注意這裡的隨機為偽隨機,要想真正接近隨機可以使用下面這段**

srand((

unsigned

int)

(time

(null))

);int k =

(rand()

)%25;

int l =

(rand()

)%14;

參考:用時間做種子生成隨機數

實現這一函式功能

3.2對於函式selectpos(),這是我們的重頭戲,這個函式我們的作用是實現選擇最佳翻開位置,在我們不知道當前位置是否有雷的情況下,那麼我們去選擇呢?我們需要將問題數位化,定義乙個指數來判斷,是否應該翻開當前位置,而概率則可充當這一任務。

我們知道當第一次翻開時,我們是隨機的,那麼第二次我們就可以根據我們已知的條件來判斷了,例如當前如圖(1)

對於當前情況我們需要分析當前點周圍出現地雷的概率如圖(2)

周圍有count個點未被翻開,而周圍顯示有n個地雷,所以我們可以知道

p=n%count,得到概率為0.25,注意此處n,p,count應該定義為浮點型。

現在我們應該翻開它周圍點嗎?我們還需要思考能不能翻開它周圍以外的點,我稱它為冒險博弈getrisk();

由於我們已經知道,被掀開點周圍有2個地雷mine,(如果)地雷(minenum)和行(col)列(row)數目是已知的,那我們就可以得到除了它周圍以外的點是地雷mine的風險risk,p=(minenum-已知地雷數目)%(col*row-9)

將得到的概率相互一比較,得到最優選擇。

當區域內多點被掀開,我們應該如何去考慮它的概率?如圖(3)

但我們掀開周圍點後,發現另乙個點周圍有三個地雷,那麼如何確定這兩個點周圍點是地雷的概率呢?

首先我們需要確定新掀開的點周圍有雷的概率,然後再更新前乙個點的概率,注意概率的更新只影響到被掀開點周圍的點。

然後將兩掀開點周圍的點納入乙個陣列minearound中,再計算被掀開點周圍有雷的概率,注意,這一步的計算和前面不同,我們先將區域劃分如圖(4)

計算區域1的概率時,我們暫時不考慮區域2,區域1中右上角的點已經被掀開,那麼說明確定那一點沒有雷,那麼剩下的點是雷的概率是p1=1%7;

同樣對於區域二來說它中心點周圍點為雷的概率是:p2=3%7;

然後我們來考慮兩者結合的情況,對於兩區域為被掀開的點來說它們是雷的概率由它周圍點來確定,例如我們簡單的舉出兩個點,如圖(5)

對於點b的區域來說,它自身是沒有被掀開的,我們計算點b是雷的概率就需要通過它周圍的被掀開的點來確定,對於b來說,在它周圍只有左下角點被掀開,所以我們認為點b是雷的概率為pb=p2=3%7,也就是顯示3的點的周圍點概率。

那麼如何確定點a是雷的概率呢?

對於點a,它周圍有兩個點被掀開,我們就基於這兩個點來確定它是雷的概率pa:

pa1一定是雷的概率 = (1%7)(3%7)

pa2一定不是雷的概率 = (6%7)(4%7)

對於這裡我們的目的是知道a不是雷的概率,所以我們取pa = 1-pa1;

(雖然對於該點來說只有是雷和不是雷的情況,但是這裡只討論可能性)

這樣,當我們計算得到所有周圍點的概率後,比較出乙個最好的概率情況(概率相同時任意取),然後再與risk比較,得出最後最優選擇點位。

--------------------------------2020/12/17-機房-----------------------------------------------

顯然在實際情況中,我們遇到的情況將不會只有這些,如果單純應用上面的演算法,那麼你掃雷的效率(正確率)是不高的,這是為什麼呢?我們需要結合實際情況來分析:

如圖(6):

當程式執行到這一步的時候,如圖所示我標出的紅色線框

,按照我們的邏輯,對於紅色線框中的未被掀開點,我們可以確定它不是雷的(因為它周圍的唯一一顆雷已經被發現-標上了旗幟),但是當程式實際執行的時候程式會怎麼做呢?如圖(7)

可以看到程式並沒有選擇我們認為的最優點,這是為什麼呢?我們來嘗試通過我們的演算法計算一下最優點不是雷的概率:p 1= (3%4)1(1%3)=1%12

對於走錯的那個點(踩到雷的點),我們計算一下它不是雷的概率:p2 = (1-2%7)=5%7>p1

程式走得沒錯,完全按照了我們的演算法來執行,但是出現了錯誤,說明我們演算法還有改進的空間,我們忽略了這一種特殊情況,所以我們將它新增上:

for i in minearound[

](已經被掀開的點組成的陣列,不包括旗幟,空點和地雷)

if i.prob==

0(i周圍為雷的概率為0

) then open i.around

#在這裡,我們加入了一種特殊情況,當已經被掀開的點中,存在周圍點是雷概率為0的特殊情況是,我們不再比較最優選擇(概率),直接開啟它的周圍點。

新增**後,實現效果如圖(7)

筆者最近有點忙,更新可能會很慢。

未完待續。。。。。。。。

當然在實際除錯情況中,我們不僅僅將只是遇到這些情況,例如:

1.當我們遇到確認是地雷的點該怎麼辦?

2.當我們遇到的所有點周圍是雷的概率都很高(但不確定是雷或者不是雷)怎麼辦?

3.等等等等。。。還需要我們慢慢去**。

2020/12/

掃雷遊戲 C實現

相信掃雷遊戲對於這一代的我們來說並不陌生,小學中學階段在沒有網路的學校機房可沒少玩吧?以前,我們是以乙個使用者的角度來接觸它的,那麼,作為即將成為程式猿的我們來說,何不妨試試以開發者的角度來接觸它呢?先來分析一下掃雷程式的大體思路及框架 1 要實現掃雷程式,需要有乙個在每一局中固定的埋雷陣列,表示雷...

c 實現掃雷遊戲

設計思路 定義乙個結構體,裡面存放每乙個格仔是否被翻開,已經地雷和格仔周圍地雷數量。用結構體定義乙個二維陣列,隨機放入特定數量的地雷。玩家輸入要翻開的格仔的行數和列數。用乙個函式來翻開目標格仔,如果是地雷遊戲失敗,否則用乙個函式統計目標格仔周圍的地雷數。如果周圍沒有地雷,則遞迴使用乙個函式將附近周圍...

簡單掃雷遊戲的實現

掃雷遊戲的實現我採用多個原始檔的編寫方法,實現 的分模組化編寫,這樣不僅 清晰,且加強 的理解性。建議讀者在實現 時,不可心急求成,一次就要完成 的所有函式邏輯部分,而是先編寫大體 框架,一步步思考 的實現所需要的函式實現,進一步完善 的函式主體。標頭檔案部分 game.h ifndef game ...