軟件綜合實(shí)習(xí)報(bào)告五子棋游戲的實(shí)現(xiàn)_第1頁(yè)
軟件綜合實(shí)習(xí)報(bào)告五子棋游戲的實(shí)現(xiàn)_第2頁(yè)
軟件綜合實(shí)習(xí)報(bào)告五子棋游戲的實(shí)現(xiàn)_第3頁(yè)
軟件綜合實(shí)習(xí)報(bào)告五子棋游戲的實(shí)現(xiàn)_第4頁(yè)
軟件綜合實(shí)習(xí)報(bào)告五子棋游戲的實(shí)現(xiàn)_第5頁(yè)
已閱讀5頁(yè),還剩23頁(yè)未讀, 繼續(xù)免費(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í)習(xí)報(bào)告題目:五子棋人機(jī)博弈游戲院(系): 計(jì)算機(jī)學(xué)院 專 業(yè): 計(jì)算機(jī)科學(xué)與技術(shù) 姓 名: 楊祺鵬 班級(jí)學(xué)號(hào): 191072-03 20071000566 指導(dǎo)教師: 王改芳 2010 年 9 月 18 日目錄一 系統(tǒng)需求分析與總體設(shè)計(jì)1. 需求分析 問(wèn)題描述 數(shù)據(jù)流程圖2. 總體設(shè)計(jì) 開(kāi)發(fā)背景 開(kāi)發(fā)語(yǔ)言 開(kāi)發(fā)平臺(tái)和運(yùn)行平臺(tái) 總體功能設(shè)計(jì)二 詳細(xì)設(shè)計(jì)與系統(tǒng)實(shí)現(xiàn)1. 類和類的方法設(shè)計(jì) 類的設(shè)計(jì) 類的方法設(shè)計(jì)2. 算法描述三 系統(tǒng)測(cè)試1. 功能測(cè)試2. 性能測(cè)試四 總結(jié)1. 系統(tǒng)仍存在的不足2. 結(jié)論和體會(huì)一 系統(tǒng)需求分析與總體設(shè)計(jì)1. 需求分析 問(wèn)題描述題目:五子棋人機(jī)博弈游戲題目要求

2、:實(shí)現(xiàn)五子棋游戲的人機(jī)博弈。要求:友好的人機(jī)圖形化界面、方便的操作方式;自動(dòng)判斷輸、贏或平;可選擇黑白;可悔棋;可以基于人工智能方面的知識(shí)進(jìn)行設(shè)計(jì),如:?jiǎn)l(fā)式搜索、搜索函數(shù)的設(shè)置、_算法、知識(shí)的表示及知識(shí)庫(kù),推理機(jī)等。五子棋簡(jiǎn)介:五子棋是起源于中國(guó)古代的傳統(tǒng)黑白棋種之一。顧名思義,只要連成五子即可獲得勝利。聽(tīng)上去好像很簡(jiǎn)單,但是不用技巧好似很難獲勝的,這其中就有“活三”,“沖三”等等專業(yè)名詞,這些我會(huì)在后續(xù)的程序中進(jìn)行介紹。五子棋不僅能增強(qiáng)思維能力,提高智力,而且富含哲理,有助于修身養(yǎng)性。五子棋既有現(xiàn)代休閑的明顯特征“短、平、快”,又有古典哲學(xué)的高深學(xué)問(wèn)“陰陽(yáng)易理”;它既有簡(jiǎn)單易學(xué)的特性,為人

3、民群眾所喜聞樂(lè)見(jiàn)。 通過(guò)問(wèn)題的描述,初步分析可得出此軟件應(yīng)具有以下的功能:1. 友好的界面,方面的操作方式可以快速開(kāi)始游戲,功能明確而且界面明朗2. 自動(dòng)判斷輸贏計(jì)算機(jī)可以根據(jù)棋子的狀態(tài)判斷勝負(fù)情況3. 可選擇黑白可以先手下棋和后手下棋4. 可悔棋具有悔棋功能5. 計(jì)算機(jī)AI計(jì)算機(jī)需要具有一定的AI,需要AI攻守兼?zhèn)?數(shù)據(jù)流程圖判斷誰(shuí)是先手玩家計(jì)算機(jī)AI:即算法數(shù)據(jù)流動(dòng)很少,主要是在算法內(nèi)部進(jìn)行計(jì)算,實(shí)際進(jìn)行交互的數(shù)據(jù)是沒(méi)有的。 要求開(kāi)始游戲 落子,33禁手 棋子坐標(biāo) 玩家落子 是否再來(lái)一盤輸贏判斷 取最佳位置并落子(若不分勝負(fù)) 再來(lái)一盤 勝負(fù)已分2. 總體設(shè)計(jì) 開(kāi)發(fā)背景軟件工程綜合實(shí)習(xí),因

4、為我對(duì)算法很有興趣,就決定通過(guò)這個(gè)程序?qū)W習(xí)一下。 語(yǔ)言選擇使用C#平臺(tái)在設(shè)計(jì)人機(jī)界面時(shí)更人性化,畫圖工具也更為簡(jiǎn)潔易用。 開(kāi)發(fā)環(huán)境及運(yùn)行環(huán)境開(kāi)發(fā)環(huán)境:操作系統(tǒng)名稱Microsoft Windows 7 旗艦版版本6.1.7600 版本 7600處理器AMD Turion(tm) X2 Dual-Core Mobile RM-72,2100 Mhz, 物理內(nèi)存(RAM)3.00 GB開(kāi)發(fā)平臺(tái):Microsoft Visual Studio 2008 專業(yè)版 - 簡(jiǎn)體中文 Microsoft Visual C# 2008運(yùn)行平臺(tái):Intel® Pentium® 2及以上處理器,

5、32M以上內(nèi)存,4G以上硬盤Microsoft® Windows 9X/NT操作系統(tǒng)800*600或以上的屏幕分辨率Net.framework2.0及以上版本 具體功能設(shè)計(jì)主要函數(shù):1. 畫棋子2. 畫棋盤3. 先手判斷4. 勝負(fù)判斷5. 計(jì)算機(jī)AI算法(權(quán)值賦值,權(quán)值計(jì)算,找最大權(quán)值)界面設(shè)計(jì):1. 快速開(kāi)始游戲2. 先手選擇3. 悔棋,認(rèn)輸,電腦提示4. 棋子的坐標(biāo)顯示(計(jì)算電腦提示的附加功能)5. 幫助這幾個(gè)模塊的重點(diǎn)是計(jì)算機(jī)AI算法的設(shè)計(jì)。在參閱了很多資料以后,我發(fā)現(xiàn)解決五子棋問(wèn)題的算法非常之多,遺傳算法,剪枝算法等等,這些算法的特點(diǎn)是對(duì)后續(xù)步驟進(jìn)行無(wú)數(shù)次的推演并一一評(píng)分,最

6、后去評(píng)分最高的一種方案的第一步,在下完一子之后再進(jìn)行算法計(jì)算,雖然AI非常聰明但是計(jì)算繁瑣且計(jì)算時(shí)間其長(zhǎng)無(wú)比。在網(wǎng)上發(fā)現(xiàn)的算法有更多的程序員是采用了權(quán)值計(jì)算的方法,具體來(lái)說(shuō)就是根據(jù)每種情況每種可能對(duì)每個(gè)點(diǎn)都賦不同的權(quán)值,AI在判斷應(yīng)該進(jìn)攻還是應(yīng)該防守就是依靠權(quán)值的大小,權(quán)值最大的位置放棋子,采用這種方法雖然笨是笨了些,但是計(jì)算速度快,尤其是在棋盤比較小的時(shí)候(15*15棋盤),而且在對(duì)比中發(fā)現(xiàn)這種AI也很聰明。在速度和計(jì)算精度之間權(quán)衡之后,我準(zhǔn)備選擇計(jì)算權(quán)值的方法來(lái)做,如果時(shí)間仍有富裕的話再使用別的算法來(lái)計(jì)算并進(jìn)行對(duì)比。二 詳細(xì)設(shè)計(jì)與系統(tǒng)實(shí)現(xiàn)1. 類和類的方法設(shè)計(jì) 類的設(shè)計(jì)(后面的方法設(shè)計(jì)也遵

7、從這個(gè)順序逐個(gè)進(jìn)行詳細(xì)注釋)棋盤類Chessboard棋盤類主要實(shí)現(xiàn)對(duì)棋盤棋子,以及電腦和人下棋的顯示,對(duì)虛擬棋盤的定義,對(duì)下棋路徑的堆棧的初始化,對(duì)棋局的初始化。棋子類 Stone棋子類主要實(shí)現(xiàn)對(duì)棋子的畫圖操作。計(jì)算機(jī)類Computer計(jì)算機(jī)類是本程序的核心模塊,主要實(shí)現(xiàn)計(jì)算機(jī)對(duì)每個(gè)棋子每個(gè)位置的權(quán)值賦值,對(duì)每個(gè)棋盤位置的權(quán)值計(jì)算,求最大權(quán)值。規(guī)則類Rule規(guī)則類主要實(shí)現(xiàn)對(duì)勝負(fù)平局的判斷,對(duì)黑棋禁手的判斷,對(duì)每個(gè)方向上的連子數(shù)的計(jì)算,對(duì)棋局判斷是依據(jù)連子數(shù)計(jì)算的。主函數(shù)類frmMain主函數(shù)主要是對(duì)界面上每個(gè)按鍵的功能進(jìn)行實(shí)現(xiàn),另實(shí)現(xiàn)對(duì)鼠標(biāo)的move和click事件的定義,獲取鼠標(biāo)的坐標(biāo)。

8、類的方法的具體實(shí)現(xiàn)1. Chessboard類中方法的實(shí)現(xiàn)一 Chessboard中的變量定義所謂的在棋盤上下棋,其實(shí)就是在相應(yīng)坐標(biāo)進(jìn)行繪圖,實(shí)際是不存在棋盤的,這里我定義一個(gè)15,15的二維數(shù)組來(lái)表示虛擬的棋盤進(jìn)行下棋,其他見(jiàn)程序注釋。public int, arrchessboard = new int 15,15; / /arrchessboard為棋盤情況數(shù)組,虛擬棋盤的定義,arrchessboardi,j=2表示此處無(wú)子arrchessboardi,j=0表示此處為黑子,arrchessboardi,j=1表示此處為白子private Graphics mg; /繪制的對(duì)象publ

9、ic Stone stone; /棋子對(duì)象public Computer computer; /電腦對(duì)象private bool stoneflag = true; /判斷當(dāng)前棋子是黑(true)是白(false)private bool mplayfirstflag = false; /判斷先手玩家(是電腦(true)還人(false),先手下黑棋)private Stack mStarckHistory = new Stack();/歷史記錄堆棧二 Chessboard中對(duì)棋盤和棋子的繪制對(duì)棋子和棋盤的繪圖要用到system.draw這個(gè)系統(tǒng)自帶的畫圖類,我使用的方式是先讀取文件流中的文件

10、,然后在每次畫圖的時(shí)候就不用再次讀取了,直接可以進(jìn)行繪圖,這樣處理速度比較快。詳細(xì)見(jiàn)注釋。public void Draw()/從資源中獲取,讀取棋盤圖像,就是在當(dāng)前項(xiàng)目中讀取文件System.Reflection.Assembly thisExe;thisExe = System.Reflection.Assembly.GetExecutingAssembly();System.IO.Stream file = thisExe.GetManifestResourceStream("FiveStones.chessboard.gif");/棋盤文件Image imgChes

11、sboard = System.Drawing.Image.FromStream(file); /棋盤圖片大小*600像素,每個(gè)棋子的點(diǎn)的坐標(biāo),個(gè)棋子,個(gè)空,兩邊線留空();mg.DrawImage(imgChessboard,0,0,imgChessboard.Width,imgChessboard.Height);/繪制棋子for (int i=0;i<15;i+)for(int j=0;j<15;j+)if (arrchessboardi,j = 0)/對(duì)棋盤上的點(diǎn)進(jìn)行判斷后,根據(jù)虛擬數(shù)組的值來(lái)判斷繪制哪一種棋子stone.DrawStone(i,j,true);/Stone

12、里面具體的繪制方法if (arrchessboardi,j = 1)stone.DrawStone(i,j,false); 三 Chessboard中人下棋和電腦下棋就是獲取下棋的坐標(biāo),然后在該坐標(biāo)進(jìn)行相應(yīng)的繪圖,然后把該點(diǎn)的虛擬棋盤置成2,表示已經(jīng)下過(guò)棋了。public void PersonDownStone(int x,int y)if (x < 600 && y < 600) /取下棋點(diǎn)int m = (int)Math.Floor(double)x/40);/求浮點(diǎn)數(shù)的“地板數(shù)”,就是求小于等于該點(diǎn)浮點(diǎn)數(shù)的整數(shù)int n = (int)Math.Floor

13、(double)y/40);if (!Rule.IsExist(m,n,arrchessboard)/如果這個(gè)位置沒(méi)有子,則下子DownStone(m,n);/人下子ComputerDownStone();/電腦下子private void ComputerDownStone()int m,n,count=0;/count是計(jì)數(shù)器,每下一子就加1docomputer.Down(arrchessboard);m = computer.X;n = computer.Y;count+;if (count > 100)/如果下一百個(gè)子還不分勝負(fù),就直接異常退出MessageBox.Show(&q

14、uot;異常!");Start();return;while(Rule.IsExist(m,n,arrchessboard);/當(dāng)判斷該點(diǎn)沒(méi)有子的時(shí)候下子DownStone(m,n);四 Chessboard對(duì)棋局的初始化把初始化貼上來(lái)的目的是為了讓每次下棋的流程更明顯,構(gòu)造對(duì)象啊,還有清空堆棧呀,這些看似很簡(jiǎn)單,但是其中的順序是不可顛倒的,詳細(xì)見(jiàn)注釋。 private void Initialization()/棋盤初始化stoneflag = true; /置當(dāng)前要走的棋為黑棋(黑棋先走)for(int i=0;i<15;i+)for(int j=0;j<15;j+)

15、arrchessboardi,j = 2; /把棋盤所有位置置為空(未下子)mStarckHistory.Clear();/清空歷史記錄堆棧stone = new Stone(mg); /構(gòu)造棋子對(duì)象private void Start()/這個(gè)才是初始化函數(shù)Initialization();computer = new Computer(mplayfirstflag); /構(gòu)造電腦對(duì)象Draw();/畫棋盤if (mplayfirstflag)/如果是電腦先手的話就電腦下棋,否則等待ComputerDownStone();五 Chessboard中每下一子都要進(jìn)行的處理做法,更改虛擬棋盤的數(shù)

16、值,對(duì)禁手進(jìn)行判斷,將棋子坐標(biāo)壓入堆棧,下棋完成后交換下棋。這個(gè)過(guò)程顯示了下棋的步驟,在下棋之后,對(duì)虛擬棋盤也就是二維數(shù)組進(jìn)行賦值,然后把該點(diǎn)壓入堆棧,然后對(duì)黑棋是否禁手進(jìn)行判斷,這里用到了Rule傳過(guò)來(lái)的值,詳細(xì)見(jiàn)注釋。private void DownStone(int m,int n)stone.DrawStone(m,n,stoneflag);/下棋if (stoneflag) /記錄情況arrchessboardm,n = 0;/根據(jù)黑白標(biāo)記對(duì)虛擬棋盤數(shù)組進(jìn)行賦值elsearrchessboardm,n = 1;if (stoneflag) /記錄歷史記錄壓入堆棧/壓入堆棧的是棋子顏

17、色和坐標(biāo)mStarckHistory.Push("黑:"+m.ToString()+","+n.ToString();每下一子就壓入堆棧elsemStarckHistory.Push("白:"+m.ToString()+","+n.ToString();if (Rule.Result(m,n,arrchessboard) < 6) /判斷結(jié)果,這個(gè)要調(diào)用Rule中的方法switch(Rule.Result(m,n,arrchessboard) /禁手失敗直接判黑棋負(fù),重新開(kāi)始case 1: MessageBo

18、x.Show("黑棋雙三禁手失??!");由Rule.Rusult的返回值進(jìn)行判斷,這幾種情況都要重新開(kāi)始!break;case 2:MessageBox.Show("黑棋雙四禁手失??!");break;case 3:MessageBox.Show("黑棋長(zhǎng)連禁手失?。?quot;);break;case 4:if (stoneflag)MessageBox.Show("黑棋勝利!");elseMessageBox.Show("白棋勝利!");break;case 5:MessageBox.Show(&qu

19、ot;平局!");break;Start();/重新開(kāi)始!return;elsestoneflag = !stoneflag; /交換當(dāng)前棋子顏色 2.Stone類中方法的實(shí)現(xiàn) Stone類主要實(shí)現(xiàn)的就是對(duì)棋子的繪圖,沒(méi)什么好說(shuō)的。public class Stone對(duì)棋子的繪制方法,需要從當(dāng)前目錄進(jìn)行讀取圖片,再繪制private Graphics mg;privateImage imgBlackStone; /黑子圖片從文件獲取privateImage imgWhiteStone; /白子圖片public Stone(Graphics g)System.Reflection.As

20、sembly thisExe;thisExe = System.Reflection.Assembly.GetExecutingAssembly();System.IO.Stream wfile = thisExe.GetManifestResourceStream("FiveStones.whitestone.gif");/讀取黑子,白子圖片System.IO.Stream bfile = thisExe.GetManifestResourceStream("FiveStones.blackstone.gif");/從資源中獲取 imgBlackSto

21、ne = System.Drawing.Image.FromStream(bfile);imgWhiteStone = System.Drawing.Image.FromStream(wfile);b();w();mg = g;public void DrawStone(int m,int n,bool flag)/繪制棋子繪制棋子if (flag)/判斷是黑棋(true)還是白棋(false)g.DrawImage(imgBlackStone,m*40,n*40,imgBlackStone.Width,imgBlackStone.Height);elseg.DrawImage(imgWhit

22、eStone,m*40,n*40,imgWhiteStone.Width,imgWhiteStone.Height);3.Computer類中方法的實(shí)現(xiàn)一 每下一子都要進(jìn)行的過(guò)程 Down方法這個(gè)方法說(shuō)明了下子之后的整個(gè)計(jì)算過(guò)程,先重新定義一個(gè)虛擬棋盤,然后對(duì)該虛擬棋盤有子的位置的權(quán)值賦值為-1,就是肯定不會(huì)走的,然后調(diào)用Check方法對(duì)沒(méi)有子的位置進(jìn)行權(quán)值計(jì)算,然后使用Check返回的權(quán)值在MaxQZ里面計(jì)算權(quán)值的最大值。public void Down(int, arrchessboard) /基本思路:先計(jì)算每個(gè)點(diǎn)的權(quán)值,在權(quán)值最高的位置下棋int , qz = new int15,15

23、; /權(quán)值數(shù)組for (int i=0;i<15;i+)for(int j=0;j<15;j+)if (arrchessboardi,j < 2)qzi,j = -1;/當(dāng)已有子時(shí)標(biāo)注為-1elseqzi,j = Check(i,j,arrchessboard);/Check方法在下面介紹,是計(jì)算權(quán)值的方法MaxQZ(qz);/MaxQZ也在下面進(jìn)行介紹,是計(jì)算最大權(quán)值的方法二 計(jì)算權(quán)值的方法Check返回權(quán)值給對(duì)手顏色的連子點(diǎn)賦權(quán)值對(duì)當(dāng)前顏色的連子進(jìn)行賦權(quán)值根據(jù)當(dāng)前點(diǎn)調(diào)用Rule的方法計(jì)算連子上面的流程圖寫出了整體的過(guò)程,Check主要是對(duì)剛剛定義的權(quán)值數(shù)組進(jìn)行賦值,先對(duì)己

24、方進(jìn)行賦值,然后對(duì)對(duì)手的進(jìn)行賦值,然后判斷是應(yīng)該防守還是應(yīng)該進(jìn)攻。電腦Ai的攻擊力取決于權(quán)值的賦值,詳細(xì)見(jiàn)注釋。private int Check(int m, int n, int, arrchessboard)賦權(quán)值的原則 /賦值的原則決定了AI是進(jìn)攻強(qiáng)還是防守強(qiáng),進(jìn)攻強(qiáng)則在AI和人都有三字連起時(shí),給自己的賦值更高一些,防守強(qiáng)則是給人的賦值更高一些int qz = 0; int w1 = 100000; /找自己的取勝點(diǎn)()int w2 = 50000; /找對(duì)手的取勝點(diǎn)()int w3 = 10000; /找自己的三個(gè)相連的點(diǎn)()賦權(quán)值int w4 = 5000; /找對(duì)手的三個(gè)相連的點(diǎn)

25、()int w5 = 1000; /找自己的兩個(gè)相連的點(diǎn)()int w6 = 500; /找對(duì)手的兩個(gè)相連的點(diǎn)()int w7 = 100; /找自己的相連的點(diǎn)()int w8 = 50; /找對(duì)方的相連的點(diǎn)()int w9 = 999999; /找自己的失敗點(diǎn),無(wú)窮大,優(yōu)先勝利int arrf = new int4;if (mflag) /如果電腦是黑子arrchessboardm,n = 0;/如果該位置下我方的子的時(shí)候,進(jìn)行下面的權(quán)值計(jì)算,白黑子都要進(jìn)行計(jì)算else/否則電腦是白子arrchessboardm,n = 1;/這里賦值的原因是因?yàn)椴煌闹挡灰粯?/分別計(jì)算四個(gè)方向上的連子

26、數(shù),調(diào)用Rule里面的四個(gè)方法arrf0 = Rule.Xnum(m,n,arrchessboard);/橫向 arrf1 = Rule.Ynum(m,n,arrchessboard);/豎向arrf2 = Rule.YXnum(m,n,arrchessboard);/左上右下arrf3 = Rule.XYnum(m,n,arrchessboard);/右上左下if (m=7 && n=7)qz+=1;/中心點(diǎn)權(quán)值加,這主要是為了電腦先手時(shí),優(yōu)先走中間點(diǎn)for (int i=0;i<4;i+)if (Math.Abs(arrfi) = 5)/連成五子qz += w1;if

27、 (arrfi = 4)/連成四子賦值的過(guò)程!qz += w3;if (arrfi = 3)/連成三子qz += w5;if (arrfi = 2)/連成二子qz += w7;if (mflag) /如果我方為黑棋,還要檢查失敗點(diǎn)if (Rule.IsFail(arrf, arrchessboardm,n)>0)判斷是否是禁手點(diǎn),調(diào)用Rule里面的方法qz += w9;if (mflag) /如果該位置下對(duì)方的子arrchessboardm,n = 1; /對(duì)方白子else/對(duì)方黑子arrchessboardm,n = 0;arrf0 = Rule.Xnum(m,n,arrchessbo

28、ard);arrf1 = Rule.Ynum(m,n,arrchessboard);arrf2 = Rule.YXnum(m,n,arrchessboard);arrf3 = Rule.XYnum(m,n,arrchessboard);for (int i=0;i<4;i+)if (Math.Abs(arrfi) = 5)qz += w2;if (arrfi = 4)計(jì)算你的對(duì)手的權(quán)值,然后賦值!qz += w4;if (arrfi = 3)qz += w6;if (arrfi = 2)qz += w8;arrchessboardm,n = 2;/計(jì)算結(jié)束后對(duì)該點(diǎn)設(shè)置成沒(méi)有子return

29、 qz;/返回權(quán)值三 計(jì)算最大權(quán)值點(diǎn)比較,賦值,得出結(jié)果,沒(méi)什么好說(shuō)的。private void MaxQZ(int , qz)/計(jì)算最大權(quán)值/沒(méi)什么好解釋的。int max = 0;for (int i=0;i<15;i+)for(int j=0;j<15;j+)if (qzi,j>max)x = i;y = j;max = qzi,j;4.Rule類中的方法的實(shí)現(xiàn)一 計(jì)算每個(gè)方向上的連子數(shù)同色總體思路是在當(dāng)前點(diǎn)分別向兩邊進(jìn)行搜索,如果兩邊的點(diǎn)和當(dāng)前點(diǎn)顏色一致則連子數(shù)加1,直到碰到和當(dāng)前點(diǎn)不一樣顏色的點(diǎn)。不同顏色的點(diǎn)有三種,分別是空白點(diǎn),另一種顏色的點(diǎn),棋盤邊緣。對(duì)于空白點(diǎn)

30、,則置成活棋并返回值,如果是另一種顏色的點(diǎn)則置成死棋并返回值,對(duì)于棋盤邊緣也置成死棋并返回值。詳細(xì)見(jiàn)注釋。連子數(shù)加一對(duì)兩邊的點(diǎn)和當(dāng)前點(diǎn)進(jìn)行顏色的判斷從當(dāng)前點(diǎn)向兩邊進(jìn)行搜索不同置成活棋,返回值空白點(diǎn)對(duì)該點(diǎn)判斷不同色置成死棋,返回值棋盤邊緣PS.一共有四個(gè)方向的連子數(shù)的計(jì)算,僅列出X軸的計(jì)算方法 public static int Xnum(int m, int n, int, arrchessboard)int flag = 0;/檢查是否無(wú)子可下(當(dāng)flag=2時(shí)表示無(wú)子可下) /為什么flag=2的時(shí)候就不能下子了呢? /是因?yàn)橹挥凶笥覂蛇叾紱](méi)有棋子下的時(shí)候才結(jié)束計(jì)算權(quán)值,其他方向的檢測(cè)和這

31、個(gè)是一個(gè)原理的, /就是兩頭的兩個(gè)方向都是對(duì)方的子了int num = 1;/連子個(gè)數(shù)int i = m+1;/正東方向檢查(x+)while(i < 15)/不超出棋格if (arrchessboardi,n = arrchessboardm,n)/前方的棋子與m,n點(diǎn)不是一樣的棋子的時(shí)候跳出循環(huán)num+;i+;elsebreak;/正東方向超出棋格if (i=15)flag+;else/正東方向有別的子不可在下if(arrchessboardi,n != 2)flag+;i = m-1; /正西方向檢查(x-)減一向正西方向while(i >= 0) if (arrchessb

32、oardi,n = arrchessboardm,n) /前方的棋子與m,n點(diǎn)不是一樣的棋子時(shí)跳出循環(huán)num+;i-;elsebreak;if (i = -1) /正西方向超出棋格flag+;else if(arrchessboardi,n != 2) /正西方向有別的子不可在下flag+;if (flag = 2)return -num;else/連子數(shù)為時(shí)有一邊不能下就不是活三 不是活三的時(shí)候賦值降低 if (flag = 1 && num = 3 ) return -num;elsereturn num;二 勝負(fù)平局判斷,禁手判斷任意方向上連成五子即算勝利,在沒(méi)有一個(gè)連成

33、五子的情況下棋盤走滿算平局,禁手判斷是對(duì)當(dāng)前點(diǎn)的四個(gè)方向計(jì)算上有三個(gè)以上連子就算禁手(僅黑子有禁手),禁手直接判負(fù)重新開(kāi)始。詳細(xì)見(jiàn)注釋。勝利判斷:private static bool IsWin(int arr)for (int i=0;i<4;i+)當(dāng)連子數(shù)為5的時(shí)候就勝利了,arrI是四個(gè)方向的連子數(shù)if (Math.Abs(arri) = 5)return true;return false; 平局判斷:private static bool IsTie(int, arrchessboard)/當(dāng)所有位置都有子時(shí)為平局當(dāng)所有點(diǎn)都有子的時(shí)候即判斷為平局for (int i=0;i&

34、lt;15;i+)for (int j=0;j<15;j+)if (arrchessboardi,j = 2)return false;return true; 負(fù)局判斷:(要對(duì)禁手進(jìn)行判斷,比較難)public static int IsFail(int arr, int stoneflag)if (stoneflag = 1) /如果是白棋不驗(yàn)證因?yàn)榘灼鍩o(wú)禁手白棋沒(méi)有禁手return 0;elseint num = 0;/活的子相連的個(gè)數(shù)for (int i=0;i<4;i+)/驗(yàn)證雙三禁手(該處的雙三是活的雙三)/什么是活三呢?就是雙三的每個(gè)三的兩端都可以下子,就是活三if

35、(arri = 3)雙三和雙四都是活三和活四,這里定義的NUM是為了記錄活子的個(gè)數(shù),只有有活子的雙三雙四才禁手num+;if (num > 1)return 1;num = 0;/活的子相連的個(gè)數(shù)for (int i=0;i<4;i+)/驗(yàn)證雙四禁手(該處的雙四是活的雙四)if (arri = 4)num+;if (num > 1)return 2;for (int i=0;i<4;i+)/驗(yàn)證長(zhǎng)連禁手if (Math.Abs(arri) > 5)return 3;return 0;6. frmMain類中方法實(shí)現(xiàn)frmMain中的方法主要是實(shí)現(xiàn)窗口中的按鈕,這里

36、只對(duì)獲取鼠標(biāo)的坐標(biāo)的功能,還有悔棋功能,電腦提示功能進(jìn)行詳解。一 獲取鼠標(biāo)的坐標(biāo)為什么要說(shuō)獲取鼠標(biāo)坐標(biāo)的方法呢,主要是因?yàn)槠渲械膹?qiáng)制轉(zhuǎn)換還有求坐標(biāo)的方法當(dāng)時(shí)想了很久,個(gè)人感覺(jué)有用,所以就記下來(lái)了。private void frmMain_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)if (e.X < 600 && e.Y < 600)/取下棋點(diǎn)int m = (int)Math.Floor(double)e.X/40);int n = (int)Math.Floor(double)e.

37、Y/40);lblXY.Text = "X:"+m.ToString()+" Y:"+n.ToString();二 悔棋功能由于寫程序的時(shí)候把下子的功能和重繪棋盤寫到了一起,就是每次下子都要重繪棋盤,所以很悲劇的僅僅用比較低級(jí)的方法實(shí)現(xiàn)了悔棋功能,就是在對(duì)下棋路線的堆棧里面讀出來(lái)上兩步的坐標(biāo),然后在這個(gè)坐標(biāo)上花另外一個(gè)悔棋的標(biāo)志,同時(shí)把該地方的虛擬棋盤置成無(wú)子。我原本的設(shè)想是在堆棧中POP出最近的兩個(gè)點(diǎn)之后,對(duì)整個(gè)堆棧進(jìn)行讀取,然后對(duì)棋盤和棋子進(jìn)行重繪,但是繪制棋子和下子寫到了一起,就是不下子是不會(huì)畫棋子的,所以這個(gè)功能就實(shí)現(xiàn)的很失敗。詳細(xì)見(jiàn)注釋。具體方

38、法如下:public void backstone(int m, int n)/悔棋畫圖 Graphics ms = this.CreateGraphics(); Image imgResetStone; System.Reflection.Assembly thisExe; thisExe = System.Reflection.Assembly.GetExecutingAssembly(); System.IO.Stream rfile = thisExe.GetManifestResourceStream("FiveStones.backstone.gif");/從文

39、件讀取圖片流 imgResetStone = System.Drawing.Image.FromStream(rfile); r(); ms.DrawImage(imgResetStone,m*40,n*40,imgResetStone.Width, imgResetStone.Height);/畫圖 private void menuItem3_Click(object sender, EventArgs e) for (int j = 2; j > 0; j-)/悔棋要進(jìn)行兩次修改 上次我方和AI方都要改 object obj = chessboard.StarckHistory.P

40、eek();/獲取棧頂元素 string sta=obj.ToString(); char st = sta.ToCharArray(); int x = Int32.Parse(st2.ToString(); int y = Int32.Parse(st4.ToString();/讀出棧中的數(shù)據(jù)(x,y坐標(biāo)) backstone(x,y);/在該位置花悔棋的圖 chessboard.arrchessboardx, y = 2;/設(shè)置悔棋的點(diǎn)的棋子狀態(tài)為,即沒(méi)有棋子 chessboard.StarckHistory.Pop();/出棧 Array arr = chessboard.Starck

41、History.ToArray(); this.lstHistory.DataSource = arr;/listbox的datasource為堆棧的數(shù)組表示 三 電腦提示的功能的實(shí)現(xiàn)(在要求外額外實(shí)現(xiàn)的功能)原本想要在這一步使用一個(gè)比較靠譜的搜索樹算法向下搜索三步左右的,還是程序設(shè)計(jì)初期的問(wèn)題,沒(méi)有對(duì)程序有整體的把握,把很多東西都設(shè)計(jì)到了一起,后來(lái)再改的時(shí)候就很難了,所以也沒(méi)有實(shí)現(xiàn)?,F(xiàn)在實(shí)現(xiàn)的電腦提示的功能就是調(diào)用Computer類里面的方法對(duì)權(quán)值進(jìn)行計(jì)算,得到最大權(quán)值之后在棋盤上進(jìn)行繪制。private void aihelp() try puter.Aihelp(chessboard.a

42、rrchessboard); int a = puter.X;調(diào)用Chessboard類計(jì)算權(quán)值方法,得出最佳坐標(biāo) int b = puter.Y; helpline(a,b); catch (Exception ex) 在棋盤上畫出來(lái)一個(gè)紅色正方形 Console.WriteLine(ex); public void helpline(int m, int n) Graphics gr = this.CreateGraphics(); Pen pen = new Pen(Color.Red,2); gr.DrawRectangle(pen ,m*40+10,n*40+10,20,20);2. 算法描述一 本程序使用的算法本程序使用的比較簡(jiǎn)單的計(jì)算權(quán)值的算法,根據(jù)不同的點(diǎn)不同的情況不同的連子進(jìn)行賦值,然后每次

溫馨提示

  • 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)論