C++五子棋人機(jī)對(duì)戰(zhàn)游戲設(shè)計(jì).doc_第1頁(yè)
C++五子棋人機(jī)對(duì)戰(zhàn)游戲設(shè)計(jì).doc_第2頁(yè)
C++五子棋人機(jī)對(duì)戰(zhàn)游戲設(shè)計(jì).doc_第3頁(yè)
C++五子棋人機(jī)對(duì)戰(zhàn)游戲設(shè)計(jì).doc_第4頁(yè)
C++五子棋人機(jī)對(duì)戰(zhàn)游戲設(shè)計(jì).doc_第5頁(yè)
已閱讀5頁(yè),還剩12頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

五子棋人機(jī)對(duì)戰(zhàn)游戲摘要:本文用visual c+來(lái)設(shè)計(jì)與實(shí)現(xiàn)簡(jiǎn)單的五子棋人機(jī)對(duì)戰(zhàn)游戲的基本功能,玩家可以在游戲區(qū)域中適當(dāng)?shù)奈恢脕?lái)放棋子,通過(guò)程序設(shè)計(jì)讓電腦選擇最佳的落棋點(diǎn),來(lái)實(shí)現(xiàn)人機(jī)對(duì)戰(zhàn)。文中對(duì)該游戲的算法進(jìn)行了詳細(xì)的介紹,其中核心內(nèi)容包括界面的設(shè)計(jì)、最佳落棋位置的判斷以及游戲勝利判斷功能的實(shí)現(xiàn)。程序?qū)崿F(xiàn)起來(lái)較簡(jiǎn)單,同時(shí)也比較實(shí)用。關(guān)鍵詞: 五子棋 ,vc,人機(jī)對(duì)戰(zhàn)游戲 1.引言1.1 游戲介紹五子棋是一種很受人們喜愛(ài)的智力游戲,它的規(guī)則簡(jiǎn)單,但玩法變化多端,富有趣味性,特別鍛煉人的智力,適合人們消遣。1.2 目的網(wǎng)絡(luò)小游戲制作的目的是滿(mǎn)足了人們休閑的需要,在緊張工作之余休閑類(lèi)的小游戲能夠給人帶來(lái)最大程度的放松,也可以增進(jìn)人們之間的交流,溝通,通過(guò)游戲還可以認(rèn)識(shí)更多的朋友,也可以到達(dá)跨省、跨市,甚至跨國(guó)間人們互相娛樂(lè)的目的。 1.3 主要問(wèn)題 開(kāi)始制作游戲時(shí),主要要解決的問(wèn)題有以下幾個(gè)方面:1. 如何設(shè)置整個(gè)游戲的界面;2 判斷是否可以放下棋子;3. 如何讓電腦選擇最佳位置;4. 判斷是黑棋勝還是白棋勝。2 需求分析關(guān)于五子棋游戲的功能描述如下:運(yùn)行游戲并進(jìn)行初始化工作,將整個(gè)游戲區(qū)域中縱線(xiàn)和橫線(xiàn)相交的點(diǎn)坐標(biāo)化,并且這些點(diǎn)是將來(lái)下棋的位置。玩家可以在任意沒(méi)有放棋子的點(diǎn)放下棋子,直到一方有五個(gè)棋子連成一條線(xiàn)為勝方。 游戲的整體運(yùn)行效果如圖1.1。圖1.13. 功能模塊的設(shè)計(jì)3.1 變量和函數(shù) 在view類(lèi)中添加變量函數(shù)如下:保存vscomputer時(shí)白棋位置 CPoint vspoint;CPoint bpointcan4, /這個(gè)位置空,它旁邊有四個(gè)黑棋wpointcan4, /這個(gè)位置空,它旁邊有四個(gè)白棋bpointcan3, /這個(gè)位置空,它的旁邊有三個(gè)黑棋wpointcan3, /這個(gè)位置空,它的旁邊有三個(gè)白棋bpointcan2, /這個(gè)位置空,它的旁邊有兩個(gè)黑棋wpointcan2, /這個(gè)位置空,它的旁邊有兩個(gè)白棋bpointcan1; /不是以上情況,這個(gè)位置空 在得到最大值和方向上尋找落棋點(diǎn),其中i、j表示搜索起點(diǎn),n表示方向void searchcandown1(int i,int j,int n);void searchcandown2(int i,int j,int n);void searchcandown3(int i,int j,int n);void searchcandown4(int i,int j,int n);計(jì)算最大值及方向CPoint maxnum(int a,int b,int c,int d);最好落棋點(diǎn)void bestputdown(int i,int j);計(jì)算機(jī)下棋void computerdown();在位置point放下棋子void putdown(CPoint point);人對(duì)機(jī)菜單afx_msg void OnCpmputer();3.2.框架的搭建 新建工程,選擇單文檔,在Step 4 of 6中先中Windows Sockets復(fù)選框4 算法分析與設(shè)計(jì)4.1游戲界面的設(shè)計(jì)由于游戲的棋盤(pán)大小是一定的,不能改變大小的,是應(yīng)該符合要求的。用如下函數(shù)設(shè)置窗口大?。築OOL CMainFrame:PreCreateWindow(CREATESTRUCT& cs) if( !CFrameWnd:PreCreateWindow(cs) ) return FALSE; / TODO: Modify the Window class or styles here by modifying / the CREATESTRUCT cs cs.dwExStyle=cs.dwExStyle|WS_EX_TOPMOST; / cs.style=WS_SYSMENU|WS_OVERLAPPED|WS_MINIMIZEBOX;/; /設(shè)置窗口大?。?00*340 cs.cx=450; cs.cy=500; return TRUE;畫(huà)棋盤(pán): 在OnDraw(CDC* pDC)函數(shù)中畫(huà)棋盤(pán),由于在游戲過(guò)程中有可能重畫(huà)棋盤(pán),而那時(shí)棋盤(pán)上面有棋子,所以,我們?cè)谶@個(gè)函數(shù)里面必須有畫(huà)棋子的語(yǔ)句。在此用數(shù)組的做為1表示白棋,-1表示黑棋。 void CMy3_1View:OnDraw(CDC* pDC) CMy3_1Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); /畫(huà)背景 CBrush mybrush1; mybrush1.CreateSolidBrush(RGB(192,192,192); CRect myrect1(0,0,1200,800); pDC-FillRect(myrect1,&mybrush1); /畫(huà)棋盤(pán)框線(xiàn) CPen mypen; CPen*myoldPen; mypen.CreatePen(PS_SOLID,1,RGB(0,0,0); myoldPen=pDC-SelectObject(&mypen); for(int i=0;iMoveTo(40,40+i*20); pDC-LineTo(400,40+i*20); pDC-MoveTo(40+i*20,40); pDC-LineTo(40+i*20,400); /重畫(huà)時(shí)顯示存在的棋子 CDC Dc; if(Dc.CreateCompatibleDC(pDC)=FALSE) AfxMessageBox(Cant create DC); for(int n=0;n19;n+) for(int m=0;mBitBlt(n*20+32,m*20+32,160,160,&Dc,0,0,SRCCOPY); else if(wzqnm=-1) /顯示黑棋 Dc.SelectObject(m_bmblack); pDC-BitBlt(n*20+32,m*20+32,160,160,&Dc,0,0,SRCCOPY); 棋盤(pán)的效果如圖5. 核心算法 在完成界面設(shè)計(jì)后,就開(kāi)始展開(kāi)游戲核心的設(shè)計(jì),該部分主要包括計(jì)算機(jī)搜索最佳落棋位置,游戲勝利判斷的實(shí)現(xiàn)。5.1 搜索最佳落棋位置 計(jì)算機(jī)是怎樣下棋?這就是定位的問(wèn)題了。即搜索棋盤(pán),找出一個(gè)最佳點(diǎn),放下黑棋。我們實(shí)現(xiàn)的方法是:全盤(pán)搜索,并把搜索到的位置,保存在變量。由于有多種情況,我們定義變量如下:CPoint bpointcan4, /這個(gè)位置空,它旁邊有四個(gè)黑棋 wpointcan4, /這個(gè)位置空,它旁邊有四個(gè)白棋 bpointcan3, /這個(gè)位置空,它的旁邊有三個(gè)黑棋 wpointcan3, /這個(gè)位置空,它的旁邊有三個(gè)白棋 bpointcan2, /這個(gè)位置空,它的旁邊有兩個(gè)黑棋 wpointcan2, /這個(gè)位置空,它的旁邊有兩個(gè)白棋 bpointcan1; /不是以上情況,這個(gè)位置空 并在搜索之前都賦值為(-1,-1),然后,進(jìn)行搜索,并把相應(yīng)的值保存在相應(yīng)變量里面,而如果前面已經(jīng)對(duì)變量賦值,我們依然賦值,用新值代替舊值。注意:只保存最后一個(gè)值,這樣的一個(gè)好處是,避免了每次都從左上角開(kāi)始,并且它的隨機(jī)性比隨機(jī)函數(shù)還隨機(jī)。全盤(pán)搜索完之后,由于上面的變量中至少有一個(gè)已經(jīng)被賦值,即不是(-1,-1),可以采用多數(shù)優(yōu)先的方法,讓已經(jīng)有多個(gè)同色棋子的位置先下棋。其原理是,如果已經(jīng)有四個(gè)黑棋,計(jì)算機(jī)再下一個(gè)黑棋就贏了;否則,如果人已經(jīng)有四個(gè)白棋,那么計(jì)算機(jī)就必須放下一個(gè)黑棋,阻止白棋下一步贏;如果已經(jīng)有三個(gè)黑棋,再下一個(gè)黑棋,變成四個(gè);否則,如果已經(jīng)有三個(gè)白棋,下一個(gè)黑棋,破壞它;兩個(gè)棋子的同理;否則,在剛才白棋下的地方,順便找一個(gè)位置,下棋。computerdown()函數(shù)如下:/輪到計(jì)算機(jī)下棋void CMy3_1View:computerdown() /把各種情形賦值為如下 bpointcan4=(-1,-1); wpointcan4=(-1,-1); bpointcan3=(-1,-1); wpointcan3=(-1,-1); bpointcan2=(-1,-1); wpointcan2=(-1,-1); bpointcan1=(-1,-1); /搜索最好的落棋點(diǎn) for(int i=0;i19;i+) for(int j=0;jBitBlt(point.x*20+32,point.y*20+32,160,160,&Dc,0,0,SRCCOPY); wzqpoint.xpoint.y=-1;/由于原來(lái)我們檢查是否結(jié)束時(shí)用的是鼠標(biāo)點(diǎn)下的坐標(biāo),而現(xiàn)在/putdown(CPoint point)函數(shù)用的是數(shù)組棋盤(pán)的坐標(biāo),所以必須轉(zhuǎn)換 CPoint overpoint; overpoint.x=point.x*20+30; overpoint.y=point.y*20+30; over(overpoint); colorwhite=true; 搜索最佳落棋點(diǎn): 現(xiàn)在還有void bestputdown(int i,int j)函數(shù)沒(méi)有定義。它的實(shí)現(xiàn)原理是:在四個(gè)方向上,各自計(jì)算那個(gè)方向上棋子的狀態(tài),利用原來(lái)定義的白棋為1,黑棋為-1的思想,讓同個(gè)方向上的五個(gè)棋子的值相加,取絕對(duì)值并賦值給為這個(gè)方向定義的局部變量numi。 如果幾個(gè)棋子是同色的,無(wú)論黑白,它的絕對(duì)值必然大,而對(duì)于幾個(gè)棋子中有黑棋和白棋的,其值必然相加而抵消變小。所以我們可以利用這種方法來(lái)尋找旁邊有多個(gè)同色棋子的空位置(前面已經(jīng)具體說(shuō)明)。在每一個(gè)棋盤(pán)位置,計(jì)算以它為起點(diǎn)的四個(gè)方向(橫、豎、撇、捺),再比較這四個(gè)方向中哪個(gè)值最大,然后在這個(gè)方向上尋找落棋點(diǎn)。/檢查四個(gè)方向,各算出五個(gè)棋子的和并賦值void CMy3_1View:bestputdown(int i,int j) /四個(gè)方向的值 int num4; int a,k; / num0 - a=0; if(i15) for(k=0;k5;k+) a=a+wzqi+kj; num0=abs(a); / num1 | a=0; if(j15) for(k=0;k5;k+) a=a+wzqij+k; num1=abs(a); / num2 a=0; if(i15&j15) for(k=0;k4)&(j15) for(k=0;k=b) point.x=0; point.y=a; else point.x=1; point.y=b; if(cpoint.y) point.x=2; point.y=c; if(dpoint.y) point.x=3; point.y=d; return point; 而另外的四個(gè)函數(shù),有其相似性,分別介紹如下: void searchcandown4(int i,int j,int n)函數(shù): 如果最大值是四,它必然有一個(gè)空位置;可以這樣計(jì)算,如果第一個(gè)是空,那我們把它賦值給相應(yīng)變量;否則,先找那個(gè)空位置,然后判斷第一個(gè)棋子的顏色,并賦相應(yīng)的值。 /由于相似,下面代碼只解釋第一個(gè)方向 /有四個(gè)同色棋void CMy3_1View:searchcandown4(int i, int j, int n) int k; / num0 - if(n=0) for(k=0;k5;k+) /如果第一個(gè)是空 if(wzqij=0) /如果下面有白棋 if(wzqi+1j=1) /下面位置可以下棋,已經(jīng)有四個(gè)白棋 wpointcan4.x=i; wpointcan4.y=j; break; else /下面位置可以下棋,已經(jīng)有四個(gè)黑棋 bpointcan4.x=i; bpointcan4.y=j; break; /如果找到下棋位置,一定能找到! else if(wzqi+kj=0) /如果第一個(gè)是白棋 if(wzqjj=1) wpointcan4.x=i+k; wpointcan4.y=j; break; /否則第一個(gè)是黑棋 else bpointcan4.x=i+k; bpointcan4.y=j; break; / num1 | if(n=1) for(k=0;k5;k+) if(wzqij=0) if(wzqij+1=1) wpointcan4.x=i; wpointcan4.y=j; break; else bpointcan4.x=i; bpointcan4.y=j; break; else if(wzqij+k=0) if(wzqij=1) wpointcan4.x=i; wpointcan4.y=j+k; break; else bpointcan4.x=i; bpointcan4.y=j+k; break; / num2 if(n=2) for(k=0;k5;k+) if(wzqij=0) if(wzqi+1j+1=1) wpointcan4.x=i; wpointcan4.y=j; break; else bpointcan4.x=i; bpointcan4.y=j; break; else if(wzqi+kj+k=0) if(wzqij=1) wpointcan4.x=i+k; wpointcan4.y=j+k; break; else bpointcan4.x=i+k; bpointcan4.y=j+k; break; / num3 / if(n=3) for(k=0;k5;k+) if(wzqij=0) if(wzqi-1j+1=1) wpointcan4.x=i; wpointcan4.y=j; break; else bpointcan4.x=i; bpointcan4.y=j; break; else if(wzqi-kj+k=0) if(wzqij=1) wpointcan4.x=i-k; wpointcan4.y=j+k; break; else bpointcan4.x=i-k; bpointcan4.y=j+k; break; void searchcandown3(int i,int j,int n)函數(shù): 如果最大值是三,它有兩種情況,一種是三個(gè)同色和兩個(gè)空;一種是四個(gè)同色和一個(gè)異色。前一種必定能找到一個(gè)空位置,賦值;后一種必定找不到空位置,不賦值。所以我們的想法很簡(jiǎn)單,先找到空位置,證明有三個(gè)同色,這對(duì)于玩五子棋來(lái)說(shuō)三個(gè)同色是很重要的,再判斷是哪種顏色,賦相應(yīng)的值。void searchcandown2(int i,int j,int n)函數(shù): 如果最大值是二,也有兩種情況:一種是有兩個(gè)同色和三個(gè)空位置;一種是有三個(gè)同色和一個(gè)異色和一個(gè)空位置,并且只算三個(gè)同色不連在一起的情況(因?yàn)槿绻腥齻€(gè)連續(xù)的情況,重全盤(pán)搜索的角度看,必然會(huì)被另外的情況所代替)。分兩種算法:一種是有一個(gè)空位置,一種是有三個(gè)空位置。前者先找到空位置,再判斷它下面兩個(gè)是否同色,同色則賦值給相應(yīng)變量,異色則不賦值,因?yàn)橐饬x不大;后者只要找到一個(gè)空位置就行了。void searchcandown1(int i,int j,int n)函數(shù): 最后的一個(gè)函數(shù)是searchcandown1(int i, int j, int n),這是為了預(yù)防用的,如果以上情況不發(fā)生,這個(gè)函數(shù)就是為了處理這種情況。這里就說(shuō)明了為什么我們要添加vspoint的原因了,它保存了上次白棋下棋的位置,而我們?cè)跊](méi)有辦法的情況下,在白棋旁邊隨便找個(gè)位置就可以了。 /如果五個(gè)位置的和是一void CMy3_1View:searchcandown1(int i, int j, int n) /計(jì)算剛才白棋落棋點(diǎn) int ii=(vspoint.x-30)/20; int jj=(vspoint.y-30)/20; int a; for(a=0;a5;a+) /如果不到邊界 if(ii+a19) /向右,如果有空位置 if(wzqii+ajj=0) /在這個(gè)位置下黑棋 bpointcan1.x=ii+a; bpointcan1.y=jj; return; /到了邊界 else /向左,如果有空位置 if(wzqii-1jj=0) bpointcan1.x=ii-a; bpointcan1.y=jj; return; 5.2 判斷游戲是否結(jié)束 用一個(gè)over()函數(shù)判斷是否結(jié)束,是則結(jié)束并重新開(kāi)始;否則,接著把鼠標(biāo)變成棋子,表示繼續(xù)下棋。此函數(shù)是利用剛下棋的位置為中心,檢查它各個(gè)方向上的連續(xù)五個(gè)棋子是否同色,是則結(jié)束并重新開(kāi)始。利用連續(xù)五個(gè)棋子的值相加,如果它們的值的絕對(duì)值等于5,則說(shuō)明是同色。void CMy3_1View:over(CPoint point) /獲取鼠標(biāo)指向數(shù)組位置,即中心位置 int x=(point.x-30)/20; int y=(point.y-30)/20; /計(jì)算開(kāi)始判斷的坐標(biāo) xx,yy int xx,yy; if(x4) xx=0; else xx=x-4;

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 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ì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論