編程實(shí)現(xiàn)一個(gè)掃雷機(jī)器人_第1頁(yè)
編程實(shí)現(xiàn)一個(gè)掃雷機(jī)器人_第2頁(yè)
編程實(shí)現(xiàn)一個(gè)掃雷機(jī)器人_第3頁(yè)
編程實(shí)現(xiàn)一個(gè)掃雷機(jī)器人_第4頁(yè)
編程實(shí)現(xiàn)一個(gè)掃雷機(jī)器人_第5頁(yè)
已閱讀5頁(yè),還剩13頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

付費(fèi)下載

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、編程實(shí)現(xiàn)一個(gè)掃雷機(jī)器人一、課題內(nèi)容和要求在一個(gè)20*20的地圖上,分布著81顆地雷,掃雷機(jī)器人走到其中一個(gè)方格上,如果是地雷,它將被炸死,如果不是,它可以探測(cè)到它周圍的八個(gè)方格中有幾個(gè)地雷?,F(xiàn)在你擁有10個(gè)掃雷機(jī)器人(10次錯(cuò)誤機(jī)會(huì)),請(qǐng)你將這片雷區(qū)中的所有地雷標(biāo)出來(lái)。二、需求分析(1)規(guī)則描述 游戲開(kāi)始時(shí),系統(tǒng)會(huì)在雷區(qū)的某些小方塊中隨機(jī)布下81顆雷,部署完畢后,系統(tǒng)會(huì)在其他非雷方塊中填充一些數(shù)字,某一個(gè)具體數(shù)字表示預(yù)期緊鄰的8個(gè)方塊中有多少雷方塊,玩家可以可以根據(jù)這些信息去判斷是否可以打開(kāi)某些方塊,并把認(rèn)為是地雷的方塊打上標(biāo)記,當(dāng)玩家將所有地雷找出后,其余的非雷方塊區(qū)域都已打開(kāi),此時(shí)游戲勝利

2、結(jié)束,在游戲過(guò)程中,一旦錯(cuò)誤地打開(kāi)了雷方塊10次以上,游戲結(jié)束。(2)功能需求分析此掃雷機(jī)器人游戲是一個(gè)交互式的游戲,它的開(kāi)發(fā)需滿足的要求包括以下幾個(gè)部分:一部分是此游戲界面需要在20*20的界面上實(shí)現(xiàn),并規(guī)定雷數(shù)為81顆,第二部分是實(shí)現(xiàn)掃雷要求,即掃雷機(jī)器人走到其中一個(gè)方格上,如果是地雷,它將被炸死,如果不是,它可以探測(cè)到它周圍的八個(gè)方格中有幾個(gè)地雷,該部分包括進(jìn)行某種操作判斷某區(qū)域是否是雷,如果是雷該如何操作,如果不是雷該如何操作,判斷某區(qū)域是雷則如何加以標(biāo)記,以及點(diǎn)擊某區(qū)域時(shí),判斷與該區(qū)域相鄰的其它8個(gè)區(qū)域是否是雷并做一個(gè)標(biāo)記。第三部分是此掃雷機(jī)器人有10次錯(cuò)誤機(jī)會(huì)。(3)功能模塊需求分

3、析程序設(shè)計(jì)過(guò)程中涉及到的功能模塊函數(shù):1函數(shù):static int TextOut(const char* pstr ); 功能要求:在當(dāng)前位置輸出字符串,本程序根據(jù)各種操作,定義的字符串分別為"ArrowKey:MoveCursor Key1:Open Key2:Mark Key3:OpenNeighbors"代表程序標(biāo)題、Congratulations! You Win! Thank you for playing!代表游戲獲勝、Game Over, thank you for playing!代表游戲失敗、Presented by 1803 . Press ESC t

4、o exit代表退出。2函數(shù):  static int GotoXY(int x , int y );功能要求:光標(biāo)移至(x,y)處并得到此光標(biāo)位置。3函數(shù):static int CharOut(int x, int y, const int pstr);功能要求:在(x,y)處輸出一字符。4函數(shù):static int TextOut(int x, int y, const char* pstr);功能要求:由任意位置移到(x,y)并在當(dāng)前位置輸出字符串5函數(shù):static int GetKey(); 功能要求:等待鍵1、2、3的輸入并返回此值。6函數(shù):int InitPool(in

5、t Width, int Height, int nBoom);功能要求:初始化游戲環(huán)境。 7函數(shù):int DrawPool(int bDrawBoom = 0);功能要求:根據(jù)各區(qū)域內(nèi)容輸出字符串 、 *、 #、 .。8. 函數(shù):int WaitMessage( );功能要求:根據(jù)各種輸入KEY_UP、 KEY_DOWN、 KEY_LEFT、 KEY_RIGHT、 KEY_1、 KEY_2 、KEY_3、 KEY_ESC執(zhí)行操作,通過(guò)返回的nRT來(lái)判斷失敗、勝利或未結(jié)束。9. 函數(shù):int GetShowNum(int x, int y);功能要求:確定認(rèn)一點(diǎn)(x,y)和它周圍8個(gè)方向的總雷

6、數(shù),并把雷的數(shù)目顯示出來(lái)。10. 函數(shù):int TryOpen(int x, int y); 功能要求:打開(kāi)點(diǎn)(x,y)并顯示雷數(shù)號(hào)碼,必須實(shí)現(xiàn)10次機(jī)會(huì)錯(cuò)誤這一功能要求,若超出10次而未找出全部雷數(shù),則將游戲界面上的所有雷顯示出來(lái)(即返回EOF)。11. 函數(shù):int DFSShowNum(int x, int y);功能要求:在游戲界面范圍內(nèi),先通過(guò)調(diào)用函數(shù)int GetShowNum(int x, int y)獲得任意一點(diǎn)周圍的總雷數(shù),若為0,則通過(guò)遞歸調(diào)用直至將獲得的雷數(shù)顯示出來(lái)。 四、概要設(shè)計(jì)整體游戲流程圖:游戲開(kāi)始執(zhí)行操作雷區(qū)GAME OVER判斷非雷區(qū)程序使用了面向?qū)ο?/p>

7、的方法,首先創(chuàng)建工程項(xiàng)目,本程序基于Win32 Console Application.程序定義了窗口類class CConsoleWnd和類模塊class CSLGame , 類中成員變量和成員函數(shù)原型聲明分別如下:(1).class CConsoleWnd public: static int TextOut(const char*); static int GotoXY(int, int); static int CharOut(int, int, const int); static int TextOut(int, int, const char*); static int GetK

8、ey(); ;(2).class CSLGame:public CConsoleWnd private: int curX,curY; int poolWidth,poolHeight; int bm_gamepoolGAME_MAX_HEIGHT+2GAME_MAX_WIDTH+2; public: CSLGame():curX(0),curY(0)poolWidth=poolHeight=0; int InitPool(int, int, int); int MoveCursor()return CConsoleWnd:GotoXY(curX, curY); int DrawPool(in

9、t); int WaitMessage(); int GetShowNum(int, int); int TryOpen(int, int); private: int DFSShowNum(int, int); private: const static int GMARK_BOOM; const static int GMARK_EMPTY; const static int GMARK_MARK;const int CSLGame:GMARK_BOOM = 0x10;const int CSLGame:GMARK_EMPTY= 0x100;const int CSLGame:GMARK_

10、MARK = 0x200;#define KEY_UP 0xE048#define KEY_DOWN 0xE050#define KEY_LEFT 0xE04B#define KEY_RIGHT 0xE04D#define KEY_ESC 0x001B#define KEY_1 '1'#define KEY_2 '2'#define KEY_3 '3'#define GAME_MAX_WIDTH 100#define GAME_MAX_HEIGHT 100算法設(shè)計(jì)包括:1 隨機(jī)布雷可以隨即獲取一個(gè)狀態(tài)為非雷的點(diǎn),將它的屬性標(biāo)志為雷,重復(fù)這樣的工作

11、直到將81顆雷布完。流程圖如下:是開(kāi)始生成隨機(jī)的雷方塊的坐標(biāo)(x,y)判斷(x,y)區(qū)域是否已經(jīng)布下雷在(x,y)區(qū)域布雷,修改狀態(tài)數(shù)據(jù)判斷是否布下所有雷結(jié)束否否是設(shè)數(shù)組bm_gamepoolyx為地雷標(biāo)志數(shù)組,若此數(shù)組恒為0,則標(biāo)志為雷,Windows的API有這樣的一種機(jī)制,可以生成隨機(jī)函數(shù)。先用strand()函數(shù)產(chǎn)生并返回隨機(jī)種子,可以利用系統(tǒng)的時(shí)間作為隨機(jī)數(shù)產(chǎn)生的種子,而產(chǎn)生的隨機(jī)數(shù)實(shí)際上是偽隨機(jī)數(shù),它的產(chǎn)生是根據(jù)遞推公式計(jì)算的一組數(shù)組,即int x = rand()%Width + 1, y = rand()%Height + 1,當(dāng)序列長(zhǎng)度滿足81時(shí),這組數(shù)值近似滿足均勻分布。2

12、. 做雷陣,即雷數(shù)目的計(jì)算和顯示在沒(méi)有雷的地方點(diǎn)擊后就會(huì)顯示一個(gè)數(shù)字表示它周圍有幾個(gè)雷,這是怎么實(shí)現(xiàn)的呢?我們可以把整個(gè)雷區(qū)看成一個(gè)二維數(shù)組bm_gamepoolyx,假如雷區(qū):  11  12  13  14  15  16  17  18 21  22  23  24  25  26  27  28 31  32  33  34  35  36  37 

13、 38 41  42  43  44  45  46  47  48 51  52  53  54  55  56  57  58我要知道a34周圍有幾個(gè)雷,就只有去檢測(cè) a23,a24,a25 a33,       a35 a43,a44,a45這8個(gè)雷區(qū)是否放上了雷,仔細(xì)觀察它們成在數(shù)學(xué)關(guān)系,抽象出來(lái)就是:ai,j的雷的個(gè)數(shù)就是由&#

14、160;ai-1,j-1,ai-1,j,ai-1,j+1 a i ,j-1,           a i ,j+1 ai+1,j-1,ai+1,j,ai+1,j+1 這樣的8個(gè)雷區(qū)決定的。對(duì)于任意一點(diǎn)(x,y)執(zhí)行循環(huán)語(yǔ)句:for(int Y=-1;Y<=1;+Y) for(int X=-1;X<=1;+X) if(bm_gamepooly+Yx+X & GMARK_BOOM)+nCount; 觀察并計(jì)算它周圍8個(gè)方向雷區(qū)的總雷數(shù)。3.

15、 雷方塊拓展接著上面的例子,假如a3,4周圍雷數(shù)為1,a2,3已被標(biāo)示為地雷,那么a24,a25,a33,a35,a43,a44,a45將被展開(kāi),一直波及到不可確定的雷區(qū)。這也是實(shí)現(xiàn)的關(guān)鍵。我們可以把數(shù)組的元素設(shè)定為一個(gè)類對(duì)象,它們所屬的類設(shè)定這樣的一個(gè)事件:在被展開(kāi)時(shí),檢查周圍的雷數(shù)是否與周圍標(biāo)示出來(lái)的雷數(shù)相等,如果相等則展開(kāi)周圍未標(biāo)示的雷區(qū)。這樣新的雷區(qū)展開(kāi)又觸發(fā)這個(gè)事件,就這樣遞歸下去,一直蔓延到不可展開(kāi)的雷區(qū)。4. KEY_1事件在雷區(qū)鍵1的時(shí)候,光標(biāo)所在的方塊將顯示提示信息,即它周圍8個(gè)方向的雷區(qū)總雷數(shù)。(1) 判斷鼠標(biāo)點(diǎn)擊的雷區(qū)位置,計(jì)算出當(dāng)前打開(kāi)的小方塊坐標(biāo)。(2) 檢測(cè)小方塊的

16、狀態(tài),判斷能否打開(kāi),是則跳到無(wú)雷狀態(tài)處理。(3) 檢測(cè)小方塊的狀態(tài),判斷是否為雷,是則跳到雷狀態(tài)處理。(4) 繼續(xù)狀態(tài)處理,打開(kāi)小方塊,并拓展最大可能顯示范圍。KEY_1事件流程圖如下:KEY_1事件游戲結(jié)束雷方塊定位繼續(xù)處理打開(kāi)區(qū)域拓展最大的可能顯示范圍勝利失敗處理勝利處理顯示結(jié)束否是否是5. KEY_2事件對(duì)雷區(qū)域中某個(gè)小方塊的屬性做出判斷后,可以鍵2做出相應(yīng)的屬性標(biāo)記,當(dāng)鍵2時(shí),可以根據(jù)以前該雷方塊標(biāo)識(shí)的狀態(tài)去計(jì)算出應(yīng)該顯示的下一狀態(tài),并標(biāo)識(shí)對(duì)該雷方塊的推測(cè)屬性,人啊背后予以顯示,其實(shí)現(xiàn)步驟如下:(1)光標(biāo)所在的雷區(qū)位置。(2)歷史標(biāo)志狀態(tài)。(3)使?fàn)顟B(tài)修改為即將顯示的狀態(tài)。(4)顯示。

17、 KEY_2的流程分析如下圖:KEY_2事件雷方塊定位判斷歷史屬性以及相關(guān)狀態(tài)修改相關(guān)狀態(tài)顯示結(jié)束6. KEY_3事件對(duì)雷區(qū)域中某個(gè)小方塊的屬性做出判斷后,可以鍵3做出相應(yīng)的雷區(qū)拓展,首先顯示該區(qū)域的方塊狀態(tài),然后判斷該方塊周圍8個(gè)方向的方塊中是否有雷,如果沒(méi)有,則在此方塊鍵3,將會(huì)打開(kāi)這8個(gè)方塊中無(wú)雷的區(qū)域。實(shí)現(xiàn)步驟如下:(1) 光標(biāo)所在雷區(qū)顯示的數(shù)字。(2) 相鄰8個(gè)方向的區(qū)域狀態(tài)。(3) 進(jìn)行判斷,并做相應(yīng)操作。(4) 結(jié)果顯示。 KEY_3流程分析如下圖:KEY_3事件雷方塊定位判斷其屬性以及周圍方塊狀態(tài)打開(kāi)其周圍非雷區(qū)顯示結(jié)束 五、詳細(xì)設(shè)計(jì)1.二維數(shù)組初始化我開(kāi)的是一個(gè)22

18、*22的數(shù)組,而實(shí)際使用的雷區(qū)是20*20的數(shù)組,周圍一圈是空的,這樣對(duì)雷區(qū)的邊界,我也可以簡(jiǎn)單的將它周圍8個(gè)點(diǎn)的雷數(shù)相加,而不會(huì)發(fā)生數(shù)組越界的情況,但在編程的時(shí)候,仍應(yīng)該認(rèn)為雷區(qū)是一個(gè)簡(jiǎn)單的20*20的數(shù)組,可以利用的應(yīng)該是0,19.  #define GAME_MAX_WIDTH 100#define GAME_MAX_HEIGHT 100int bm_gamepoolGAME_MAX_HEIGHT+2GAME_MAX_WIDTH+2;while(nBoom) int x = rand()%Width + 1, y = rand()%Height + 1; if(bm_gamep

19、oolyx=0) bm_gamepoolyx = GMARK_BOOM; -nBoom; 2.判斷一個(gè)區(qū)域是否是雷方塊int CSLGame:DrawPool(int bDrawBoom = 0)if(bm_gamepoolyx & GMARK_BOOM) if(bDrawBoom) putchar('*'); else putchar('.'); 3.相鄰區(qū)域的雷數(shù)獲取/ return ShowNum at (x, y) int CSLGame:GetShowNum(int x, int y) int nCount = 0; for(int Y=-1;

20、Y<=1;+Y) for(int X=-1;X<=1;+X) if(bm_gamepooly+Yx+X & GMARK_BOOM)+nCount; return nCount; 4.根據(jù)玩家的操作和雷區(qū)的分布,在游戲界面上顯示 各字符串 用來(lái)表示空、 *用來(lái)表示為雷、 #表示此區(qū)域標(biāo)志為雷、 .表示未確定區(qū)域或雷數(shù),即任意一點(diǎn)周圍8個(gè)方向的總雷數(shù)。/ Draw game pool to Console windowint CSLGame:DrawPool(int bDrawBoom = 0) for(int y=1;y<=poolHeight;+y) CConsole

21、Wnd:GotoXY(1, y); for(int x=1;x<=poolWidth;+x) if(bm_gamepoolyx=0) putchar('.'); else if(bm_gamepoolyx=GMARK_EMPTY) putchar(' '); else if(bm_gamepoolyx>0 && bm_gamepoolyx<=8) putchar('0'+bm_gamepoolyx); Else if(bDrawBoom=0&&(bm_gamepoolyx GMARK_MARK)

22、putchar('#'); else if(bm_gamepoolyx & GMARK_BOOM) if(bDrawBoom) putchar('*'); else putchar('.'); return 0;5掃雷機(jī)器人有10次錯(cuò)誤機(jī)會(huì),執(zhí)行以下循環(huán)函數(shù)if(bm_gamepoolyx & GMARK_BOOM) i+; if(i=10)nRT = EOF; 6.雷方塊的拓展int CSLGame:DFSShowNum(int x, int y) if(0<x && x<=poolWidth) &a

23、mp;&(0<y && y<=poolHeight) && (bm_gamepoolyx=0) int nCount = GetShowNum(x, y); if(nCount=0) bm_gamepoolyx = GMARK_EMPTY; for(int Y=-1;Y<=1;+Y) for(int X=-1;X<=1;+X) DFSShowNum(x+X,y+Y); else bm_gamepoolyx = nCount; return 0; 7. 勝利的判斷與相應(yīng)處理,根據(jù)各種輸入KEY_UP、 KEY_DOWN、 KEY_L

24、EFT、 KEY_RIGHT、 KEY_1、 KEY_2 、KEY_3、 KEY_ESC執(zhí)行操作,通過(guò)返回的nRT來(lái)判斷失敗、勝利或未結(jié)束。/ Game loop, wait and process an input message/ return: 0: not end; 1: Win; otherwise: Lose int CSLGame:WaitMessage() int nKey = CConsoleWnd:GetKey(); int nRT = 0, nArrow = 0; switch (nKey) case KEY_UP: if(curY>1)-curY; nArrow=

25、1; break; case KEY_DOWN: if(curY<poolHeight) +curY; nArrow=1; break; case KEY_LEFT: if(curX>1)-curX; nArrow=1; break; case KEY_RIGHT: if(curX<poolWidth)+curX; nArrow=1; break; case KEY_1: nRT = TryOpen(curX, curY); break; case KEY_2: if(bm_gamepoolcurYcurX & (GMARK_MARK|GMARK_BOOM)=0) b

26、m_gamepoolcurYcurX = GMARK_MARK; break; case KEY_3: if(bm_gamepoolcurYcurX & 0xF) int nb = bm_gamepoolcurYcurX & 0xF; for(int y=-1;y<=1;+y) for(int x=-1;x<=1;+x) if(bm_gamepoolcurY+ycurX+x&GMARK_MARK) -nb; if(nb=0) for(int y=-1;y<=1;+y) for(int x=-1;x<=1;+x) if(bm_gamepoolcur

27、Y+ycurX+x & (0xF|GMARK_MARK) = 0) nRT |= TryOpen(curX+x, curY+y); break; case KEY_ESC: nRT = EOF; break; if(nKey = KEY_1 | nKey = KEY_3) int y=1; for(;y<=poolHeight;+y) int x=1; for(;x<=poolWidth; +x) if(bm_gamepoolyx=0)break; if(x<=poolWidth) break; if(! (y<=poolHeight) nRT = 1; if(

28、nArrow=0) DrawPool(); MoveCursor(); return nRT; 六、測(cè)試數(shù)據(jù)及其結(jié)果分析游戲開(kāi)始頁(yè)面如下:在10次錯(cuò)誤機(jī)會(huì)內(nèi)未獲得游戲勝利,運(yùn)行結(jié)果如下:分析:(1)鍵1,打開(kāi)光標(biāo)所在區(qū)域并顯示其相鄰8個(gè)方向的總雷數(shù)。 (2)判斷某方塊的狀態(tài),若確定其為雷,鍵2,則在此方塊上標(biāo)記,表示此為雷。 (3)判斷已打開(kāi)方塊相鄰8個(gè)方向的方塊狀態(tài),若已顯示的雷數(shù)與此方塊顯示的數(shù)字相等,則在此方塊鍵3,將其相鄰方向未打開(kāi)區(qū)域打開(kāi)。(4)有10次錯(cuò)誤機(jī)會(huì),在10內(nèi)錯(cuò)誤將不顯示游戲失敗信息,只有超過(guò)10次才會(huì)出現(xiàn)游戲失敗的提示信息。七、調(diào)試過(guò)程中的問(wèn)題1.問(wèn)題:在布雷時(shí),如何實(shí)現(xiàn)隨機(jī)分布。解決為題:通過(guò)

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論