版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、<p> 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計報告</p><p> 選題名稱: 五子棋人機對戰(zhàn) </p><p> 系(院): 計算機工程學院 </p><p> 專 業(yè): 計算機科學與技術(shù) </p><p> 班 級:
2、 </p><p> 姓 名: 學 號: </p><p> 指導教師: </p><p> 學年學期: 2012 ~ 2013 學年 第 1 學期</p><p> 2012年 12 月 20 日</p>
3、;<p><b> 設(shè)計任務(wù)書</b></p><p><b> 摘要:</b></p><p> 人工智能是一門正在迅速發(fā)展的新興的,綜合性很強的邊緣科學。它與生物工程、空間技術(shù)一起被并列為二十一世界三大尖端技術(shù)。它的中心任務(wù)是研究如何使計算機去做那些過去只能靠人的智力才能做的工作。目前各發(fā)達國家都把人工智能作為重點列入本車
4、的高科技發(fā)展計劃當中,投入巨大的人力和物力。</p><p> 計算機人機對弈也是其中之一。作為人智能研究的一個重要分支,計算機博弈是檢驗人工水平的一個重要方面。它的研究為人工智能帶來了很多重要的方法和理論,產(chǎn)生了廣泛的社會影響和學術(shù)影響。</p><p> 五子棋人機對弈是計算機博弈中的一種。研究其計算機算法,可以讓我們看到人工智能的初影,也有助于我們?nèi)四X的開發(fā)。五子棋是我國發(fā)明的,
5、研究它可以讓更多的外國人了解,有助于我國優(yōu)秀文化的推廣。</p><p> 關(guān)鍵詞:人工智能;計算人機對弈;五子棋;算法目錄</p><p><b> 1.概 述5</b></p><p><b> 1.1背景分析5</b></p><p> 1.2 國內(nèi)外現(xiàn)狀5</p>
6、<p><b> 2.需求分析5</b></p><p><b> 2.1業(yè)務(wù)需求5</b></p><p> 2.2 性能需求5</p><p> 2.3 系統(tǒng)平臺需求6</p><p><b> 3.總體設(shè)計6</b></p>
7、<p> 3.1 系統(tǒng)流程圖6</p><p><b> 3.2系統(tǒng)分析6</b></p><p><b> 4.系統(tǒng)實現(xiàn)10</b></p><p> 4.1 界面的實現(xiàn)10</p><p> 4.2 智能算法實現(xiàn)11</p><p> 5
8、.系統(tǒng)測試分析26</p><p> 5.1 系統(tǒng)測試26</p><p><b> 總 結(jié)27</b></p><p><b> 致 謝28</b></p><p><b> 參考文獻29</b></p><p><b>
9、; 1.概 述</b></p><p> 當電腦進入我們的生活中,許多與相關(guān)學科都欣欣的向上發(fā)展。典型的有電子商務(wù)、電子郵件等。當然也有人智能了。人們在驚嘆機器人高效的工作時,也會想起自己聰明的一面。人工智能也這方面也就深受我們喜愛。</p><p><b> 1.1背景分析</b></p><p> 五子棋是起源于中國古代
10、的傳統(tǒng)黑白棋種之一?,F(xiàn)代五子棋日文稱之為“連珠”,英譯為“Ren-ju”,英文稱之為“Gobang”或“FIR”(Five in a Row的縮寫),亦有“連五子”、“五子連”、“串珠”、“五目”、“五目碰”、“五格”等多種稱謂。</p><p><b> 1.2 國內(nèi)外現(xiàn)狀</b></p><p> 國內(nèi)外研究五子棋的算法不少。有遞歸法、二叉樹等。當然我所討論的
11、是一般的算了法。</p><p> 無論何種算法,其大體遵循兩條原則:1.使規(guī)則更加自然流暢,更容易被人接受。2.使棋的內(nèi)容更加豐富多彩。而對于五子棋來說,所面臨的困境歸根結(jié)底是來自于其最本質(zhì)的特點,也是目前一切規(guī)則的共同之處:連五終局。</p><p><b> 2.需求分析</b></p><p><b> 2.1業(yè)務(wù)需求&
12、lt;/b></p><p> 2.1.1使用范圍要求</p><p> 該系統(tǒng)適于游戲愛好者。</p><p> 2.1.2 功能要求</p><p> ?。?)玩家能與電腦下子</p><p><b> (2)適于新手來玩</b></p><p><
13、b> 2.2 性能需求</b></p><p> 系統(tǒng)不大,但滿足玩家基本要求,電腦有一定智能,能給于新手幫助。</p><p> 2.3 系統(tǒng)平臺需求</p><p> 2.3.1. 系統(tǒng)開發(fā)平臺</p><p> 操作系統(tǒng):Windows xp系列</p><p> 開發(fā)工具:Visu
14、al C++ 6.0</p><p><b> 3.總體設(shè)計</b></p><p> 進入系統(tǒng)之后。玩家按F1開始游戲,首先是玩家下子,接著電腦下子。一直循環(huán)。在電腦或是玩家下了一個子后,電腦計算一下,是否電腦獲勝或玩家獲勝或是和棋。若有一種情況出現(xiàn),則暫停游戲顯示出相應的結(jié)果。若玩家還想玩,繼續(xù)按F1,若要退出則按F12。在游戲開始后,玩家可按F11進行智能提
15、示。</p><p><b> 3.1 系統(tǒng)流程圖</b></p><p> 程序流程圖如圖3-1所示。首先看到的界面是我們熟悉的棋盤??煽吹较旅嬗幸恍形淖?。當用戶按F1時,則游戲開始,這時用戶先下子。電腦此時先根據(jù)算法計算下,是否和棋,是否電腦獲勝,是否玩家獲勝,若有一種情況發(fā)生,則進入暫停階段,此時下子則無效,電腦顯示相應的結(jié)果,否則電腦就根據(jù)自己的得分算法,
16、計算出最佳位置。電腦下子了后,則電腦繼續(xù)判斷是否和棋,是否電腦獲勝,是否玩家獲勝,若有一種情況發(fā)生,同樣進入到暫停階段,顯示相應的結(jié)果。若用戶按了F12,則整個系統(tǒng)退出結(jié)束。若在開始后,又按了F11,則顯示提示功能。這對于新手來說是很好的功能。</p><p><b> 3.2系統(tǒng)分析</b></p><p> 在看別人下棋時,我們常說一句“當局者迷,旁觀者清”,
17、但這句話對于AI所控制的計算機來說是不正確的。</p><p> A:求得所有獲勝的組合</p><p> 首先,在一場五子棋的游戲中,計算機必須要知道有哪些獲勝的組合,因此必須求得獲勝的組合的總數(shù),而求出總數(shù)后便可建立一個數(shù)組。</p><p> 我要做的是19X19的棋盤,獲勝總數(shù)有點多。下面一一來討論。(以表格作為棋盤,1表示為某一方的子,其中以(i,j
18、)表示第i行第j列的格子,)</p><p> 3.2.1計算水平方向的獲勝組合數(shù)</p><p> 1 2 3 …… 15 16 17 18 19 可以看到對于第一行中(1,1),(1,2),(1,3),(1,4),(1,5)這五個格可以是一個獲勝組合,而(1,2),(1,3),(1,4),(1,5),(1,6)這五個格子也可以組成一個獲勝組合。這樣一直到最
19、后一種為(1,15),(1,16),(1,17),(1,18),(1,19)這五個格子組成一個獲勝組合。即第一行有15種獲勝的組合??偟挠?9行??傻?,對于行中,我們有19X15=285種獲勝組合。</p><p> 3.2.2計算垂直方向的獲勝組合數(shù)</p><p> 同理對于垂直的獲勝組合中第一種為第一列的1,2,3,4,5可組成一個獲勝組合。總的獲勝組合也是19X15=285種。
20、</p><p> 3.2.3計算正斜方向的獲勝組合數(shù)</p><p> 1 2 3 4 5 …… 15 16 17 18 19、 在第一行中,則可知(1,1),(2,2),(3,3),(4,4),(5,5)為一獲勝組合,而(1,3),(2,4),(3,5),(4,6),(5,7)也是一種獲勝組合。第一行中的最后一種為(1,15),(2,16)
21、,(3,17),(4,18),(5,19)??偟墨@勝組合有15種,而最后一行i只能到15。這樣我們可以計算得到正斜有15X15=225種。</p><p> 3.2.4計算反斜方向的獲勝組合數(shù)</p><p> 依據(jù)上一種正斜,同理可推知反斜也有15X15=225種。</p><p> 由前面的討論中,我們可計算出19X19表格中五子棋的獲勝種數(shù)。一共有285
22、+285+225+225=1020種獲勝方式。</p><p> B:建立一些相應的變量</p><p> 對此我建立了一個數(shù)組,如下:</p><p> BOOL cmp[19][19][1020]; //電腦的每一顆棋子是否在各個獲勝組合中</p><p> BOOL ply[19][19][1020]; //電腦的每一顆
23、棋子是否在各個獲勝組合中</p><p> int wcount[2][1020]; //電腦與玩家在各個組合中的棋子個數(shù)</p><p> (三個變量的簡寫來源cmp:computer ply:player wcount:win count)</p><p> 如上述討論可知,對于電腦,若為正斜中的第一種情況,并假定為1020種獲勝組合中的第570
24、種獲勝組合。則其數(shù)組元素值設(shè)定如下:</p><p> cmp[0][0][570]=true;</p><p> cmp[0][1][570]=flase;</p><p> cmp[0][2][570]=false;</p><p><b> ……</b></p><p> cmp[
25、1][0][570]=false;</p><p> cmp[1][1][570]=true;</p><p> cmp[1][2][570]=false;</p><p><b> ……</b></p><p> cmp[2][2][570]=true;</p><p><b>
26、; ……</b></p><p> cmp[3][3][570]=true;</p><p><b> ……</b></p><p> cmp[4][4][570]=true;</p><p> ply[][][]數(shù)組元素的初始化與cmp[][][]是相同的,但若程序執(zhí)行時,若玩家的棋占了(0,0)
27、的位置,那么電腦在cmp[0][0][570]元素就會置為false,因為計算機就不可能再下到(0,0)上,第570種方法中對電腦來說是不可能的情況了。對于若是電腦占了(0,0)的位置,則玩家中此獲勝組合中也置為不可能。</p><p> wcount[2][1020]用來記錄玩家或計算機在各自的獲勝組合中棋子的個數(shù)。其中wcount[0][]來計算電腦的個數(shù),wcount[1][]用來計算玩家的個數(shù)。<
28、/p><p><b> C:分數(shù)的設(shè)定</b></p><p> 組在游戲中,為了讓電腦找到最佳的走法,必須計算出電腦下到棋盤中任一格的分數(shù),其中最高分即是電腦下的位置。</p><p><b> 如下表所示</b></p><p> 1 2 3 4 5 6 7
29、 8 9 10</p><p> 如上表所示,為什么會出現(xiàn)在C左邊為0而下面卻為20分呢。</p><p> 我們看下上面的表格就可知,C的左邊有三個格,則必須再加上左右邊的一個格了,而右邊的一個格子被電腦占了,此獲勝組合中置為不可能,得分為0。</p><p> 以上是按每一種獲勝組合為5分的來計算的。在每一次運行中,電腦都按些種算法,則電腦可
30、以找到最佳的位置。</p><p><b> D:攻擊與防守</b></p><p> 經(jīng)上述討論可知,電腦一直在找自己一方的最佳位置。若玩家在某個時刻獲勝了,電腦也在尋找自己的位置。</p><p><b> 4.系統(tǒng)實現(xiàn)</b></p><p> 系統(tǒng)經(jīng)過分析并加以設(shè)計,就可以著手進行實
31、現(xiàn)了,本系統(tǒng)主要分為界面實現(xiàn)和算法實現(xiàn)。</p><p> 4.1 界面的實現(xiàn) </p><p> 本系統(tǒng)首先印入眼簾的是五子棋的界面。本系統(tǒng)的啟動界面窗口如圖4-1所示。</p><p><b> 圖4-1</b></p><p> 利用MFC建立一個MFC工程。在mainFrame的析構(gòu)函數(shù)中,插入下一句代碼
32、:</p><p> Create(NULL,"五子棋",WS_OVERLAPPEDWINDOW&~WS_SIZEBOX&~WS_MAXIMIZEBOX,CRect(0,0,700,700),NULL,NULL,0,NULL);</p><p> 則此窗口生成的標題為“五子棋”,當加入了WS_SIZEBOX與WS_MAXIMIZEBOX后,此窗口就
33、不能最大化顯示且不能調(diào)整邊框大小,即一創(chuàng)建的框架為不可改變的大小,另一個為CRect(0,0,700,700)。此框架的大小為700X700。</p><p> 窗口創(chuàng)建后就是導入圖片。為此首先導入圖片到工程中,命名為IDB_BJ。初始值為0,加載背景之后就置為1。則可知,背景只顯示一次。其代碼如下:</p><p> CBitmap bj;//存放背景圖</p>
34、<p> CDC membj; //內(nèi)存變量背景</p><p> membj.CreateCompatibleDC(&dc);//創(chuàng)建相容的內(nèi)存變量</p><p> bj.LoadBitmap(IDB_BJ); //加載背景圖</p><p> membj.SelectObject(&bj);
35、 //選擇背景圖</p><p> //初始時只需顯示一次背景就可</p><p> if(0==flagbj) {</p><p> //若是左鍵單擊了之后才可重新繪圖,目的是白子只重新繪制一次</p><p> if(1==flaglb) {</p><p> dc.BitBlt(0,0,700,70
36、0,&membj,0,0,SRCCOPY);</p><p><b> }</b></p><p> //置為1表示不再顯示背景</p><p><b> flagbj=1;</b></p><p><b> }</b></p><p>
37、 4.2 智能算法實現(xiàn)</p><p> 為了計算得分,在討論之前要聲明幾個變量和幾個函數(shù)。</p><p> int borad[19][19];//五子棋盤的狀態(tài)。0表示無棋,1表示為電腦的棋子,2表示為玩家的棋子(borad)</p><p> BOOL cmp[19][19][1020];//電腦的獲勝組合情況(computer)</p
38、><p> BOOL ply[19][19][1020];//玩家的獲勝組合情況(player)</p><p> int wcount[2][1020];//雙方的組合情況中子的個數(shù),wcount[0][1020]為電腦,wcount[1][1020]為玩家(win count)</p><p> int pscore[19][19];//電腦的得分
39、(player score)</p><p> int cscore[19][19];//玩家的得分(computer score)</p><p> BOOL bcmp;//是否輪到電腦下棋(bool computer)</p><p> BOOL bply;//是否輪到玩家下棋(bool computer)</p><p
40、> BOOL start;//游戲是否開始(start)</p><p> BOOL pwin;//電腦是否獲勝(player win)</p><p> BOOL cwin;//玩家是否獲勝(computer win)</p><p> BOOL tie;//是否和棋(tie)</p><p> BO
41、OL tishi;//是否有智能提示(tishi)</p><p> void initGame();//初始化棋盤(initalite game)</p><p> void countScore();//計分函數(shù)(count score)</p><p> void cmpTurn();//電腦下子算法(computer turn)&l
42、t;/p><p> BOOL plyGame();//是否玩家獲勝(player game win)</p><p> BOOL cmpGame();//是否電腦獲勝(computer game win)</p><p> BOOL tieGame();//是否為和棋(tie game)</p><p> int top
43、Score();//查找最高分;返回最高分數(shù)(top score) //尋找電腦的隨機位置并保存在mc,nc中(search count) void searchCount(int top,int countTep,int *mc,int *nc);</p><p> int countTop(int top);//返回最高分的個數(shù)(count top score)</p><p
44、> 首先要進行初始化。先對棋盤及分數(shù)進行初始化。</p><p> //0表示無棋子,1表示為電腦的棋子,2表示為玩家的棋子</p><p> for(i=0;i<19;i++){</p><p> for(j=0;j<19;j++){</p><p> pscore[i][j]=0;//玩家各得分為0<
45、/p><p> cscore[i][j]=0;//電腦各得分為0</p><p> borad[i][j]=0;//各空格置為無子 </p><p><b> }</b></p><p><b> }</b></p><p> //各獲勝組合中的棋子數(shù)為0<
46、;/p><p> for(k=0;k<1020;k++){</p><p> wcount[0][k]=0;//電腦獲勝組合數(shù)的個數(shù)</p><p> wcount[1][k]=0;//玩家獲勝組合數(shù)的個數(shù)</p><p><b> }</b></p><p> 然后要對獲勝組
47、合進行初始化。</p><p> //初始時各種獲勝組合中的值都為false</p><p> for(i=0;i<19;i++){</p><p> for(j=0;j<19;j++){</p><p> for(k=0;k<1020;k++){</p><p> cmp[i][j][k]
48、=false;</p><p> ply[i][j][k]=false;</p><p><b> }</b></p><p><b> }</b></p><p><b> }</b></p><p> //行的組合情況,count的初始
49、值為0</p><p> for(i=0;i<19;i++){</p><p> for(j=0;j<15;j++){</p><p> for(k=0;k<5;k++){</p><p> cmp[i][j+k][count]=true;</p><p> ply[i][j+k][coun
50、t]=true;</p><p><b> }</b></p><p><b> count++;</b></p><p><b> }</b></p><p><b> }</b></p><p><b> /
51、/列的組合情況</b></p><p> for(i=0;i<15;i++){</p><p> for(j=0;j<19;j++){</p><p> for(k=0;k<5;k++){</p><p> cmp[i+k][j][count]=true;</p><p> pl
52、y[i+k][j][count]=true;</p><p><b> }</b></p><p><b> count++;</b></p><p><b> }</b></p><p><b> }</b></p><p&g
53、t;<b> //正斜的組合情況</b></p><p> for(i=0;i<15;i++){</p><p> for(j=0;j<15;j++){</p><p> for(k=0;k<5;k++){</p><p> cmp[i+k][j+k][count]=true;</p&g
54、t;<p> ply[i+k][j+k][count]=true;</p><p><b> }</b></p><p><b> count++;</b></p><p><b> }</b></p><p><b> }</b>
55、</p><p><b> //反斜的組合情況</b></p><p> for(i=0;i<15;i++){</p><p> for(j=18;j>=4;j--){</p><p> for(k=0;k<5;k++){</p><p> cmp[i+k][j-k][
56、count]=true;</p><p> ply[i+k][j-k][count]=true;</p><p><b> }</b></p><p><b> count++;</b></p><p><b> }</b></p><p>
57、<b> }</b></p><p> 進行初始化后,此時start、bply置為ture,bcmp置為false。即對每一種獲勝組合中的情況進行初始化。先玩家下子,轉(zhuǎn)入到系統(tǒng)函數(shù)OnLButtonDown()。void mainFrame::OnLButtonDown(UINT nFlags, CPoint point) {</p><p> //玩家單擊時的
58、動作</p><p> if(start&&bply){//若開始后且輪到玩家下子則進行判斷</p><p> if(point.x>=38&&point.y&&point.x<=602&&point.y<=602) {</p><p> mp=(int)floor((po
59、int.x-36)/30);</p><p> np=(int)floor((point.y-36)/30);</p><p><b> //空格才可下子</b></p><p> if(0==borad[mp][np]) {</p><p><b> //置為玩家的子</b></p&
60、gt;<p> borad[mp][np]=2;</p><p> for(k=0;k<1020;k++){</p><p><b> //玩家子個數(shù)加1</b></p><p> if(-1!=wcount[1][k]&&ply[mp][np][k])</p><p> w
61、count[1][k]++;</p><p> //電腦置為不可能獲勝</p><p> if(cmp[mp][np][k]){</p><p> cmp[mp][np][k]=false;</p><p> wcount[0][k]=-1;</p><p><b> }</b><
62、/p><p><b> }</b></p><p> flaglb=1;//玩家下子了可以貼白子 與tishi中的flaglb形成合作關(guān)系</p><p> bply=false;//玩家不可下子</p><p> bcmp=true;//電腦可以下子</p><p><b&
63、gt; }</b></p><p><b> }</b></p><p><b> }</b></p><p> CFrameWnd::OnLButtonDown(nFlags, point);</p><p><b> }</b></p>
64、<p> 在此函數(shù)中,首先要判斷下子的位置是否在五子棋的棋盤區(qū)域中。即使其成立point.x>=38&&point.y&&point.x<=602&&point.y<=602。</p><p> //玩家下完之后就重新貼子</p><p> for(i=0;i<19;i++){</p>&
65、lt;p> for(j=0;j<19;j++){</p><p><b> //電腦為紅子</b></p><p> if(1==borad[i][j])</p><p> dc.BitBlt(i*30+36,j*30+36,24,24,&memcs,0,0,SRCCOPY);</p><p>
66、;<b> // 玩家為綠子</b></p><p> if(2==borad[i][j])</p><p> dc.BitBlt(i*30+36,j*30+36,24,24,&memps,0,0,SRCCOPY);</p><p><b> }</b></p><p><b&
67、gt; }</b></p><p> 這時電腦就進入了計算階段。這也是此系統(tǒng)的核心代碼。此函數(shù)放置在OnTimer()中。如下所示:</p><p><b> //是否和棋</b></p><p> tie=tieGame();</p><p> if(tie&&start)<
68、/p><p> {start=false;//游戲結(jié)束</p><p> bcmp=false;//電腦不可下子</p><p> bply=false;//玩家不檔下子</p><p> MessageBox("朋友,水平不錯,竟能與電腦和棋哦……\n(按F1開始,F(xiàn)12退出!)");</p>
69、;<p> flagbj=0;//重新顯示背景圖片</p><p><b> }</b></p><p><b> //是否電腦獲勝</b></p><p> cwin=cmpGame();</p><p> if(cwin&&start)</p&
70、gt;<p> { start=false;//游戲結(jié)束</p><p> bcmp=false;//電腦不可下子</p><p> bply=false;//玩家不檔下子</p><p> MessageBox("朋友,失敗乃成功之母,請再接再勵!\n(按F1開始,F(xiàn)12退出!)");</p>
71、<p> flagbj=0;//重新顯示背景圖片</p><p><b> }</b></p><p><b> //是否玩家獲勝</b></p><p> pwin=plyGame();</p><p> if(pwin&&start)</p>
72、<p> { start=false;//游戲結(jié)束</p><p> bcmp=false;//電腦不可下子</p><p> bply=false;//玩家不檔下子</p><p> MessageBox("朋友,真牛!一下就贏了,要不收我作徒弟吧~~\n(按F1開始,F(xiàn)12退出!)");</p>
73、<p> flagbj=0;//重新顯示背景圖片</p><p><b> }</b></p><p> 先判斷是否是和棋,若是則暫停程序。當然在此,判斷和棋,我是調(diào)用了和棋的函數(shù)tieGame()。其內(nèi)容如下:</p><p> BOOL mainFrame::tieGame(){</p><p
74、> //若有空格則不為和棋</p><p> for(i=0;i<19;i++){</p><p> for(j=0;j<19;j++){</p><p> if(0==borad[i][j]) {</p><p> return false;</p><p><b> }<
75、;/b></p><p><b> }</b></p><p><b> }</b></p><p> //若有一方勝也不為和棋</p><p> for(k=0;k<1020;k++){</p><p> if(5==wcount[0][k]||5==
76、wcount[1][k]) {</p><p> return false;</p><p><b> }</b></p><p><b> }</b></p><p><b> //否則為和棋</b></p><p> return true
77、;</p><p><b> }</b></p><p> 要討論19X19格了中的每一個格子。即borad[][]!=0,并且在獲勝組合中沒有一方獲勝,則此時電腦即為和棋,返回true,否則都為false。若不為和棋,則判斷是否是電腦獲勝,其也調(diào)用判斷電腦獲勝的函數(shù)cmpGame()</p><p><b> //是否玩家獲勝
78、</b></p><p> BOOL mainFrame::plyGame(){</p><p> for(k=0;k<1020;k++){</p><p> if(5==wcount[1][k])//有五子棋相連則獲勝</p><p> return true;</p><p><
79、;b> }</b></p><p> return false;</p><p><b> }</b></p><p> 只要看下wcount[1][]中是否有一種情況中的個數(shù)為5,若有此時就返回true,否則返回flase。</p><p> 若電腦不獲勝,則繼續(xù)判斷是否玩家獲勝,此時同樣調(diào)
80、用函數(shù)cmpGame()來處理。如下所示:</p><p> BOOL mainFrame::cmpGame(){</p><p> for(k=0;k<1020;k++){</p><p> if(5==wcount[0][k])//有五子棋相連則獲勝</p><p> return true;</p>&
81、lt;p><b> }</b></p><p> return false;</p><p><b> }</b></p><p> 若在電腦的獲勝組合中有一個組合的個數(shù)為5,則電腦獲勝,這時就彈出對話框,顯示電腦獲勝,游戲時放暫停狀態(tài)。否則繼續(xù)執(zhí)行。</p><p> 首先統(tǒng)計下當
82、前分數(shù),看下當前的得分情況。如下:</p><p> void mainFrame::countScore(){</p><p> for(i=0;i<19;i++){</p><p> for(j=0;j<19;j++){</p><p><b> //初始值為0</b></p>&l
83、t;p> pscore[i][j]=0;</p><p> cscore[i][j]=0;</p><p> //若為空則計算分數(shù)</p><p> if(0==borad[i][j]) {</p><p> //各種情況一一討論</p><p> for(k=0;k<1020;k++){<
84、;/p><p><b> //若是玩家</b></p><p> if(ply[i][j][k]) {</p><p> switch(wcount[1][k]) {</p><p> case 0://零個子情況</p><p> pscore[i][j]+=1;</p
85、><p><b> break;</b></p><p> case 1: //一個子情況</p><p> pscore[i][j]+=5;</p><p><b> break;</b></p><p> case 2: //
86、二個子情況</p><p> pscore[i][j]+=10;</p><p><b> break;</b></p><p> case 3: //三個子情況</p><p> pscore[i][j]+=30; break;</p><p> ca
87、se 4: //四個子情況</p><p> pscore[i][j]+=120;</p><p><b> break;</b></p><p><b> }</b></p><p><b> }</b></p><p><
88、;b> //若是電腦</b></p><p> if(cmp[i][j][k]) {</p><p> switch(wcount[0][k]) {</p><p><b> case 0:</b></p><p> cscore[i][j]+=1;</p><p>&
89、lt;b> break;</b></p><p><b> case 1:</b></p><p> cscore[i][j]+=2;</p><p><b> break;</b></p><p><b> case 2:</b></p>
90、;<p> cscore[i][j]+=8;</p><p><b> break;</b></p><p><b> case 3:</b></p><p> cscore[i][j]+=32;</p><p><b> break;</b></
91、p><p><b> case 4:</b></p><p> cscore[i][j]+=128;</p><p><b> break;</b></p><p><b> }</b></p><p><b> }</b>&
92、lt;/p><p><b> }</b></p><p><b> }</b></p><p><b> }</b></p><p><b> }</b></p><p><b> }</b></p
93、><p> 對于19X19的格子,一一討論。若格子為空,則進行統(tǒng)計,因為只有空格才可下子。統(tǒng)計完分之后,若是輪到電腦下子,游戲未結(jié)束,則電腦下子。</p><p> //是否輪到電腦下子</p><p> if(bcmp&start)</p><p> cmpTurn();</p><p> 在此也調(diào)用了
94、函數(shù)來處理電腦下子的算法。對于cmpTurn()的代碼如下:</p><p> void mainFrame::cmpTurn(){</p><p> //以下用于找到最高分</p><p> //最高分為0,tc為電腦的最高分,tp為玩家的最高分</p><p><b> tc=tp=0;</b></p&
95、gt;<p> //標記位,0為沒找到位置,1為有電腦下子的位置</p><p> int flag=0;</p><p> for(i=0;i<19;i++){</p><p> for(j=0;j<19;j++){</p><p> //若是空格則統(tǒng)計分數(shù)</p><p> i
96、f(0==borad[i][j]) {</p><p> if(pscore[i][j]>=tp) {</p><p><b> mp=i;</b></p><p><b> np=j;</b></p><p> tp=pscore[i][j];</p><p>
97、;<b> flag=1;</b></p><p><b> }</b></p><p> if(cscore[i][j]>=tc) {</p><p><b> mc=i;</b></p><p><b> nc=j;</b></p
98、><p> tc=cscore[i][j];</p><p><b> flag=1;</b></p><p><b> }</b></p><p><b> }</b></p><p><b> }</b></p>
99、;<p><b> }</b></p><p> //以下是電腦下了的位置</p><p> if(1==flag) {//若有電腦下子的位置才可下子</p><p> //玩家分數(shù)高,則下在玩家的最高分位置,否則下在電腦的最高分位置</p><p> if(tc<tp) {</p
100、><p><b> mc=mp;</b></p><p><b> nc=np;</b></p><p><b> }</b></p><p><b> //置為電腦的子</b></p><p> borad[mc][nc]=
101、1;</p><p> //將1020種情況一一討論</p><p> for(k=0;k<1020;k++){</p><p> //電腦可以獲勝且在此位置有獲勝組合,則此組合個數(shù)加1</p><p> if(-1!=wcount[0][k]&&cmp[mc][nc][k])</p><p&
102、gt; wcount[0][k]++;</p><p> //電腦可獲勝,則置玩家不可能獲勝</p><p> if(ply[mc][nc][k]) {</p><p> ply[mc][nc][k]=false;</p><p> wcount[1][k]=-1;</p><p><b> }&
103、lt;/b></p><p><b> }</b></p><p> //電腦下完后是玩家下子</p><p> bcmp=false;</p><p> bply=true;</p><p><b> }</b></p><p>
104、<b> }</b></p><p> 此函數(shù)先對于玩家與電腦的分數(shù)pscore[][],cscroe[][]進行統(tǒng)計,分別找出電腦和玩家的最高分,若找到了,則置flag為1,表示電腦有可下的子。</p><p> //顯示黑子,意為電腦下的最后一個子,起提示作用</p><p> if(bply&&start) {&l
105、t;/p><p> dc.BitBlt(mc*30+45,nc*30+45,6,6,&membs,0,0,SRCCOPY);</p><p><b> }</b></p><p> 電腦下子之后,也要進行判斷,看下雙方是和棋、電腦獲勝還是玩家獲勝。到此才算OnTimer()的結(jié)束。</p><p> 這是個隱
106、藏的功能。要實現(xiàn)這樣的功能也不難</p><p> if(tishi&&bply) {</p><p><b> //先統(tǒng)計分數(shù)</b></p><p> countScore();</p><p> //以下用于找到當前的最佳位置</p><p> int top;
107、//臨時存放最高分,分最高的為最佳位置</p><p> top=topScore();</p><p> for(i=0;i<19;i++){</p><p> for(j=0;j<19;j++){</p><p> if(top==pscore[i][j]) {//若為玩家最高分則貼子 </p>&l
108、t;p><b> mp=i;</b></p><p><b> np=j;</b></p><p><b> //貼提示子</b></p><p> dc.BitBlt(mp*30+44,np*30+41,9,9,&memrs,0,0,SRCCOPY);</p>&
109、lt;p><b> }</b></p><p> if(top==cscore[i][j]){//若為電腦最高分則貼子 </p><p><b> mp=i;</b></p><p><b> np=j;</b></p><p><b> //
110、貼提示子</b></p><p> dc.BitBlt(mp*30+44,np*30+41,9,9,&memrs,0,0,SRCCOPY);</p><p><b> }</b></p><p><b> }</b></p><p><b> }</b&g
111、t;</p><p> flagbj=0;//重新繪制背景</p><p><b> }</b></p><p> 對于此函數(shù),首先還是統(tǒng)計當前的分數(shù),根據(jù)當前分數(shù)來尋找當前的最佳位置。在此我又調(diào)用了一個topScroe(),用于統(tǒng)計分數(shù)中的最高分。如下所示:</p><p> int mainFrame
112、::topScore(){</p><p> int top=0;//臨時最高分</p><p> for(i=0;i<19;i++){</p><p> for(j=0;j<19;j++){</p><p> //若是空格則統(tǒng)計分數(shù)</p><p> if(0==borad[i][j])
113、{</p><p> if(pscore[i][j]>=top) {</p><p> top=pscore[i][j];</p><p><b> }</b></p><p> if(cscore[i][j]>=top) {</p><p> top=cscore[i][j
114、];</p><p><b> }</b></p><p><b> }</b></p><p><b> }</b></p><p><b> }</b></p><p><b> //返回最高分數(shù)</b
115、></p><p> return top;</p><p> } 統(tǒng)計之后,再逐一進行討論,若是最高分,則此即為當前的最佳位置。當然若是這樣的算法,也就是一般人的算法,電腦的隨機算法如下:</p><p> void mainFrame::cmpTurn(){</p><p> int topc=topScore();
116、//得出最高分,臨時存入到topc中</p><p> //找到最高分的個數(shù),臨時存入到countc中int countc=countTopScore(topc);</p><p> int ranc=randomCount(countc);//返回0----countc-1中的一個隨機數(shù),用于增加難度</p><p> //找到最高分的隨機位置,并
117、保存到mc,nc中</p><p> searchCount(topc,ranc,&mc,&nc);</p><p><b> ……………</b></p><p><b> }</b></p><p> 在此,我所用的想法是,首先尋到最高分,調(diào)用topScore()函數(shù),找到
118、最高分的個數(shù),調(diào)用countTopScore(int topCount)函數(shù),并存入到countc中,然后調(diào)用randomCount(countc)返回一個0到countc-1之間的隨機數(shù)。</p><p> int mainFrame::randomCount(int ran) {</p><p> int tempc=0;</p><p> tempc=(
119、int)(1+ran*rand()/(RAND_MAX+1));</p><p> return tempc;</p><p><b> }</b></p><p> 接著調(diào)用searchCount(),找到最高分top中的隨機位置countTep中的坐標并存入到mc,nc中。</p><p> void mai
120、nFrame::searchCount(int top,int countTep,int *mc,int *nc) {</p><p> int tempc=0;//臨時的個數(shù)</p><p> for(i=0;i<19;i++){</p><p> for(j=0;j<19;j++){</p><p> if(p
121、score[i][j]==top){</p><p> tempc++;//個數(shù)加1</p><p> if(tempc==countTep){</p><p> *mc=i;//電腦的X坐標</p><p> *nc=j;//電腦的Y坐標</p><p><b> return;<
122、;/b></p><p><b> }</b></p><p><b> }</b></p><p> if(cscore[i][j]==top){</p><p><b> tempc++;</b></p><p> if(tempc=
123、=countTep){</p><p> *mc=i;//電腦的X坐標</p><p> *nc=j;//電腦的Y坐標</p><p><b> return;</b></p><p><b> }</b></p><p><b> }</b
124、></p><p><b> }</b></p><p><b> }</b></p><p><b> }</b></p><p> 到此整個系統(tǒng)也就完成了。</p><p><b> 5.系統(tǒng)測試分析</b>&l
125、t;/p><p><b> 5.1 系統(tǒng)測試</b></p><p> 5.1.1系統(tǒng)測試概述</p><p> 通常在編寫出每個模塊之后就對它做必要測試。一般說來,測試不是由編寫程序本人進行,軟件一般有兩種方法:黑盒測試和白盒測試。黑盒測試把程序看成一個黑盒子,完全不考慮程序的內(nèi)部結(jié)構(gòu)和處理過程。</p><p>&
126、lt;b> 5.1.2系統(tǒng)測試</b></p><p> 剛進入系統(tǒng)時,單擊左鍵,此時系統(tǒng)無反應,表示游戲還未開始。若按下F1則彈出的對話框,玩家可以單擊,但要是單擊在五子棋的表格外,則不起作用。若在區(qū)域內(nèi),可以下子。若單擊時下有子,則不予響應。若某一方有五子連棋時,此時會出現(xiàn)相應的對話框。若按下F11時,此時會彈出智能提示對話框,并在當前最佳位置貼上白子。若按下F12時,此時系統(tǒng)彈出一個退
127、出對話框,單擊之后系統(tǒng)便退出。</p><p> 根據(jù)測試結(jié)果分析,測試數(shù)據(jù)與理論數(shù)據(jù)一致,能達到預期效果,該系統(tǒng)運行正常。</p><p><b> 總結(jié)</b></p><p> 通過獨立完成五子棋對弈系統(tǒng)的后,發(fā)現(xiàn)自己在進行軟件開發(fā)方面提高不少,同時積極利用所學到的新技術(shù)用于自己的設(shè)計開發(fā)過程。另外,在整個開發(fā)的過程中,時間也比
128、較倉促。因此,該系統(tǒng)必然會存在一些缺陷和不足。如:沒有討論五子棋禁手的問題。另一個就是電腦按即定的算法去與玩家下子。這種算法有點“固定”。不太會變,玩家若是仔細觀察,可以掌握其規(guī)律。還有就是界面不是很華麗。有待改進。</p><p> 在Windows操作系統(tǒng)下,用VC++實現(xiàn)了這個人機對戰(zhàn)的五子棋程序。和國內(nèi)許多只是采用規(guī)則或者只是采用簡單遞歸而沒有剪枝的那些程序相比,在智力上和時間有效性上都要好于這些程序。
129、同時所討論的方法和設(shè)計過程為用戶設(shè)計其他的游戲(如象棋和圍棋等)提供了一個參考。</p><p> 人機博弈是一門復雜而又有意思的類別,而五子棋是一個相對來說規(guī)則和變 化簡單的棋種,通過設(shè)計一個簡單的五子棋AI,學生將進一步加深理解數(shù)據(jù)結(jié)構(gòu)和計算方法的關(guān)系,了解AI中基本的利用樹圖尋求最佳權(quán)值的計算方法。同時自己和自己的計算機程序?qū)膶W生來說也是一個很有意思的課題。在這么多有趣的原因的吸引下,懷著一顆強
130、烈的好奇心,在選擇畢業(yè)設(shè)計課題的時候我選擇了游戲設(shè)計(五子棋游戲設(shè)計)。拿到題目以后腦海中首先浮現(xiàn)出的是那一張方方正正上面滿是小格的棋盤。經(jīng)過一番構(gòu)思,我開始動手收集相關(guān)的資料,經(jīng)過一周的“搜刮”我積累了各種相關(guān)的資料,有關(guān)于博弈算法的,數(shù)據(jù)結(jié)構(gòu)的等等。從一個問題入手我找到的各位專家的簡介說法各不相同,經(jīng)過整理總結(jié)再加上我的一點點小的想法,我開始正式動手設(shè)計程序。我找來對五子棋頗有研究的同學和他對下,在游戲中向他取經(jīng),在了解這些專業(yè)走法
131、,陣勢的同時自己的棋藝也得到了很大的提高,真是受益非淺。了解了一些專業(yè)的走法以后我的電腦等級水平提升的空間陡然加大。</p><p> 盡管本系統(tǒng)存在著很多不足,但其實現(xiàn)了最重要的功能就是有人工智能。這也讓我對計算機中的人工智能領(lǐng)域有一定的了解。另一個就是在做系統(tǒng)的過程中,我學到了Visual C++的一些基本結(jié)構(gòu),尤其對于MFC有一定的了解。還有就是對于C++有更深一步的認識。</p><
132、p><b> 致謝</b></p><p> 在課程設(shè)計即將完成之際,本人在此對xx系提供的實踐機會,實驗室人員提供的實驗環(huán)境,指導教師的辛勤指導,同組同學的幫助,參考文獻的原作者,所有關(guān)心我的及幫助我的老師和同學們致以最真誠的感謝。</p><p> 在本次課程設(shè)計中,我從指導老師--------xx老師、單老師,身上學到了很多東西。他認真負責的工作
133、態(tài)度,嚴謹?shù)闹螌W精神和深厚的理論水平都使我收益匪淺。他無論在理論上還是在實踐中,都給與我很大的幫助,使我得到很大的提高,這對于我以后的工作和學習都有一種巨大的幫助,在此感謝他耐心的輔導。在撰寫課程設(shè)計階段,周老師幾次審閱我們的論文,提出了許多寶貴意見,沒有他的指導,我們就不能較好的完成課題設(shè)計的任務(wù)。</p><p> 另外,我還要感謝在這幾年來對我有所教導的老師,他們孜孜不倦的教誨不但讓我學到了很多知識,而且
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- java課程設(shè)計--對戰(zhàn)五子棋
- 五子棋人機對戰(zhàn)系統(tǒng)設(shè)計.pdf
- c語言課程設(shè)計---五子棋(雙人對戰(zhàn))
- java課程設(shè)計--人機對弈五子棋
- 五子棋課程設(shè)計
- 五子棋對戰(zhàn)游戲
- 網(wǎng)絡(luò)對戰(zhàn)五子棋
- java五子棋課程設(shè)計
- 五子棋-課程設(shè)計報告
- java課程設(shè)計--五子棋
- 五子棋java課程設(shè)計
- 五子棋java課程設(shè)計
- java課程設(shè)計--五子棋游戲
- 五子棋c++課程設(shè)計
- 五子棋c++課程設(shè)計
- 五子棋小游戲課程設(shè)計
- c語言五子棋課程設(shè)計
- java課程設(shè)計-五子棋游戲
- java課程設(shè)計報告-五子棋
- 五子棋游戲課程設(shè)計報告
評論
0/150
提交評論