大學計算機畢業(yè)設計論文_第1頁
大學計算機畢業(yè)設計論文_第2頁
大學計算機畢業(yè)設計論文_第3頁
大學計算機畢業(yè)設計論文_第4頁
大學計算機畢業(yè)設計論文_第5頁
已閱讀5頁,還剩17頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

22/22目錄摘要3Abstract3第1章緒言51.1研究動機51.2主要研究內(nèi)容5第2章黑白棋簡介52.1黑白棋的歷史52.2黑白棋游戲規(guī)則62.3黑白棋戰(zhàn)術(shù)分析6第3章黑白棋程序概況63.1程序流程圖63.2主要模塊簡介73.3程序設計思路7第4章游戲主界面84.1背景設計84.2游戲標題84.3游戲主菜單8第5章動畫過渡效果95.1百葉窗效果105.2隨機線效果115.3隨機出現(xiàn)過度效果11第6章漢字的顯示與移動126.1漢字點陣字模存儲模式126.2漢字點陣輸出方法126.3漢字移動技術(shù)12第7章人機對戰(zhàn)137.1游戲初始化137.1.1初始化棋盤137.1.2初始化光標147.1.3初始化分數(shù)147.2用戶操作157.2.1鍵盤掃描碼157.2.2控制光標移動157.2.3落子判斷167.2.4判斷游戲是否結(jié)束187.3電腦戰(zhàn)術(shù)分析197.3.1棋盤掃描207.3.2判斷行動力207.3.3四角優(yōu)先戰(zhàn)術(shù)217.3.4選擇最佳位置落子22第8章總結(jié)與展望228.1總結(jié)228.2前景及展望22參考文獻23致謝24附錄1部分運行結(jié)果25附錄2光盤內(nèi)容簡介26C語言設計游戲——人工智能黑白棋摘要人工智能是計算機科學的一個分支,它企圖了解智能的實質(zhì),并生產(chǎn)出一種新的能以人類智能相似的方式做出反應的智能機器,該領(lǐng)域的研究包括機器人、語言識別、圖像識別、自然語言處理和專家系統(tǒng)等?!叭斯ぶ悄堋币辉~最初是在1956年Dartmouth學會上提出的。從那以后,研究者們發(fā)展了眾多理論和原理,人工智能的概念也隨之擴展。人工智能是一門極富挑戰(zhàn)性的科學,包括十分廣泛的科學,它由不同的領(lǐng)域組成,如機器學習,計算機視覺等等,總的說來,人工智能研究的一個主要目標是使機器能夠勝任一些通常需要人類智能才能完成的復雜工作。但不同的時代、不同的人對這種“復雜工作”的理解是不同的。例如繁重的科學和工程計算本來是要人腦來承擔的,現(xiàn)在計算機不但能完成這種計算,而且能夠比人腦做得更快、更準確,因而當代人已不再把這種計算看作是“需要人類智能才能完成的復雜任務”,可見復雜工作的定義是隨著時代的發(fā)展和技術(shù)的進步而變化的,人工智能這門科學的具體目標也自然隨著時代的變化而發(fā)展。它一方面不斷獲得新的進展,一方面又轉(zhuǎn)向更有意義、更加困難的目標。目前能夠用來研究人工智能的主要物質(zhì)手段以及能夠?qū)崿F(xiàn)人工智能技術(shù)的機器就是計算機,人工智能的發(fā)展歷史是和計算機科學與技術(shù)的發(fā)展史聯(lián)系在一起的。除了計算機科學以外,人工智能還涉及信息論、控制論、自動化、仿生學、生物學、心理學、數(shù)理邏輯、語言學、醫(yī)學和哲學等多門學科。本文的研究工作在于利用計算機模擬人腦進行下黑白棋,計算機下棋是人工智能領(lǐng)域中的一個研究熱點,多年以來,隨著計算機技術(shù)和人工智能技術(shù)的不斷發(fā)展,計算機下棋的水平得到了長足的進步。本文首先詳細介紹了黑白棋的游戲規(guī)則,和一些基本的戰(zhàn)術(shù),然后將基本戰(zhàn)術(shù)編寫成代碼存儲在計算機中,使計算機在與人對弈過程中,可以選擇一個較為合理的位置落子。本程序主要是采用最大最小搜索的戰(zhàn)術(shù),就在對抗中的開局和中局使用最小搜索,而在終局時采用最大搜索。對于一般的最大最小搜索,即使每一步只有很少的下法,搜索位置的數(shù)目也會隨著搜索深度呈級數(shù)增長。在大多數(shù)的中局棋形中,每步平均有十種下法,假設電腦搜索九步(程序術(shù)語稱為搜索深度為九),就要搜索十億個位置,這樣極大地限制了電腦的棋力:我們總不能忍受電腦棋手一年才下一步棋。減少搜索結(jié)點的最簡單的方法是減小搜索深度,但這大大影響了電腦棋手的棋力。是否有辦法在不減小搜索深度的前提下將需要搜索的結(jié)點減小一些?幸運的是,可以證明,程序不需要考慮所有的位置而找到最佳點,于是人們采用了一個方法,叫"alpha-beta剪枝",它大為減少了檢測的數(shù)目,提高電腦搜索的速度。所有的強力黑白棋程序都用到了各種各樣的這種算法。文章的最后,對全文進行了總結(jié)和分析,并展望了人工智能計算機下棋在計算機領(lǐng)域和其他一些領(lǐng)域的前景與應用。關(guān)鍵詞:人工智能行動力搜索估值最小最大算法Abstractputerartificialintelligenceisabranchofsciencethatattemptstounderstandtherealsmart,andproduceanewenergytohumanintelligencesimilartothewayintelligentresponsemachinery,researchinthefield,includingrobotics,speechrecognition,imagerecognition,naturallanguageprocessingandexpertsystems."ArtificialIntelligence"isthefirstwordin1956,DartmouthmadebytheInstitute.Sincethen,researchershavedevelopedmanytheoriesandprinciples,theconceptofartificialintelligencehavealsoexpanded.Artificialintelligenceisaverychallengingscience,includingaverywiderangeofscientific,whichisposedofdifferentareas,suchasmachinelearning,putervision,etc.,ingeneral,artificialintelligenceresearchamajorobjectiveistomakesomemachinescapableofhumanintelligenceisoftenneededtopletetheplextask.Butdifferenttimes,differentpeopleofthis"plex"understandingisdifferent.Forexample,theheavyscienceandengineeringisdignitarieshavetobearthebrain,theputerwillbeabletoacplishthis,Moreoverthanthehumanbraincandofasterandmoreaccurate.socontemporarypeoplearenolongersuchtermsas"humanintelligenceneededtopletetheplextask"Visibilityplexworkisdefinedasthedevelopmentofthetimesandtechnologicaladvancesandchanges,thescienceofartificialintelligencethatthespecificobjectivesnaturallyastimeschangeanddevelopment.Whileachievenewprogress,ithastobemoremeaningful,moredifficultgoal.AtpresentAIcanbeusedtostudythematerialmeansandartificialintelligencetechnologytoachievethemachinery,includingputers,Thehistoryofthedevelopmentofartificialintelligenceandputerscienceiswiththehistoryofthedevelopmentoftechnologylinked.Inadditiontoputerscience,artificialintelligencebutalsoinformationtheory,controltheory,automation,bionics,biology,psychology,mathematicallogic,linguistics,medicineandphilosophyandothersubjects.Thisresearchistheuseofputersimulationofhumanbrainforthenextreversi.puterchessisinthefieldofartificialintelligenceresearchahottopicformanyyears,Withputertechnologyandartificialintelligencetechnologycontinuestodevelop,thelevelofputerchesshasbeengreatprogress.Thispaperdetailstherulesofthegamereversi,andsomebasictactics,Thenbasictacticalpiledcodestoredintheputer,sotheputerinthecourseofonegame,chooseamorereasonablepositionofLaoZi.Theprocedureisbasedonthemaximumandminimumsearchtactics,inthebeginningoftheconfrontationandtheuseofthesmallestSearchBureau,andthefinaluseofthelargestsearch.Fortheaveragemaximumandminimumsearch,evenifonlyasmallstepinthedismount,Searchlocationwillbethenumberofsearchdepthwiththeserieslevelwasincreased.Inmostofthemiddle-game,everystep,anaverageof10dismount,Assumingfurthernineputersearch(searchprocedure,technicallyknownasthedepthof9),itisnecessarytosearch1billionlocation(10tonine),ThisgreatlylimitstheputerJili:Wecannotputupwiththeputerplayerswillmovenextyear.Searchnodestoreducethesimplestwayistoreducethesearchdepth,butgreatlyaffectedtheplayersintheputerQili.Whethertherearewaystoreducethesearchindepthunderthepremiseoftheneedtosearchnodesdecreased?Fortunately,itprovedthattheprocedureneednotconsiderallthebestpositiontofind,sopeopleusedamethodcalled"alpha-betapruning",whichgreatlyreducedthenumberofdetection,improveputersearchofspeed.Allpowerfulreversiproceduresusedinawiderangeofthisalgorithm.(Thesameforothertypesofboardgames,suchaschessandcheckers).Inordertosearchninestep,agoodsearchprocessonly100,000to1millionlocation,andnotuselessbillionsoftimesbefore.Thefinalarticle,thefulltextofthesummaryandanalysisProspectsofartificialintelligenceandputerchessintheputerfieldandotherareaswiththeprospectofapplication.Keywords:ArtificialIntelligenceActionForceSearchValuationMinimumlargestAlgorithm第1章緒言1.1研究動機隨著計算機處理速度的飛速提高,人們很早就提出了疑問:計算機是否會超越人類?世界國際象棋棋王卡斯帕羅夫與美國IBM公司的RS/6000(深藍)計算機系統(tǒng)于1997年5月11日進行了六局“人機大戰(zhàn)”,結(jié)果“深藍”以3.5比2.5的總比分獲勝。比賽結(jié)束了給人們留下了深刻的思考;下棋要獲勝要求選手要有很強的思維能力、記憶能力、豐富的下棋經(jīng)驗,還得及時做出反應,迅速進行有效的處理,否則一著出錯滿皆輸,這顯然是個“智能”問題。盡管開發(fā)“深藍”計算機的IBM專家也認為它離智能計算機還相差甚遠,但它以高速的并行的計算能力(2r108步/秒棋的計算速度)。實現(xiàn)了人類智力的計算機上的部分模擬。那么計算機已經(jīng)超過了人類嗎?看完本文,相信你會對計算機棋手的智能有所了解。1.2主要研究內(nèi)容本文將對計算機棋手下黑白棋做一個全面綜述,介紹計算機對黑白棋戰(zhàn)術(shù)分析的全過程,包括對圖形和動畫的處理、彩色菜單的制作、漢字點陣輸出、過度效果制作、對棋盤搜索的算法、對棋局做出正確的估計、并生成最佳走法,并將介紹其中各個流程的研究狀況及實用技術(shù)。本文的重點放在計算機對當前棋局的分析,并做出最佳的選擇。 介紹搜索算法,棋類游戲不可能一步就決出勝負,象棋中不可能第一步就將對方將死;而對某個棋局的判斷也不可能完全精確,在黑白棋中,初局時棋子多并不一定最終取得勝利,因為對手可能在后面的博弈過程中將局面扭轉(zhuǎn)。想想人類下棋時,一般會假設我走這步,那么對手會怎樣回應,如果對手回應了某一步,我再走哪一步,如果對手回應了另外某一步,我又該怎么走;然后再假設我走另外的某一步,如此反復下去。這個過程叫做搜索。第2章黑白棋簡介2.1黑白棋的歷史黑白棋是19世紀末英國人發(fā)明的。直到上個世紀70年代一個日本人將其發(fā)展,借用莎士比亞名劇奧賽羅(othello)為這個游戲重新命名,也就是現(xiàn)在大家玩的黑白棋。為何借用莎士比亞名劇呢?是因為奧賽羅是莎士比亞一個名劇的男主角。他是一個黑人,妻子是白人,因受小人挑撥,懷疑妻子不忠一直情海翻波,最終親手把妻子殺死。后來真相大白,奧賽羅懊悔不已,自殺而死。黑白棋就是借用這個黑人白人斗爭的故事而命名。2.2黑白棋游戲規(guī)則黑白棋(Reversi、Othello),也叫蘋果棋,翻轉(zhuǎn)棋,是一個經(jīng)典的策略性游戲。它使用8x8的棋盤,由兩人執(zhí)黑子和白子輪流下棋,最后子多方為勝方。輪到一方下棋時,必須把棋下在與對方棋子相鄰的空位上,要求所下的棋子和原有的已方棋子夾住對方的至少一個棋子(橫豎斜夾均可),然后把被夾住的子變成己方的顏色(也叫吃子)。下棋過程中,任何棋子既不會從棋盤上拿走,也不會從一個格子移到另一個格子。黑白棋規(guī)則簡單,但是變化復雜,是典型的易學難精(aminutetolearn,alifetimetomaster),它看似簡單,實際奧妙無窮。2.3黑白棋戰(zhàn)術(shù)分析 從黑白棋的游戲規(guī)則上看,應該盡量使自己的棋子多于對手的,很容易就得到了一個戰(zhàn)術(shù),就是每步棋都落在能吃掉對手棋子最多的位置,但是經(jīng)過幾局后,你就會發(fā)現(xiàn)這并不是一個好的方法。那么黑白棋的正確戰(zhàn)術(shù)應該是怎樣的呢?一般說來,下棋過程中,你必須盡量削減對手的行動力,同時增加自己的行動力,這種策略我們稱之為行動力原則(或行動力戰(zhàn)術(shù))。當一方達到或接近這個目標時,我們就稱該棋手控制了棋局。另外,這個戰(zhàn)術(shù)的目的是迫使對方下壞棋,如果對方雖然可選位置很少,但每一步卻總有好棋,那戰(zhàn)術(shù)目的就沒有達成。記住,你必須讓對方完全無好棋可下。黑白棋規(guī)則規(guī)定只能在對方棋子相鄰的空位下棋,這就可以推出另一個原則。對方棋子邊上的空位越多,你下棋的選擇也就越多,換句話說,你的行動力就越強;相反,如果你棋子邊上的空位越少,對方可下的位置也就越少。我們把相鄰位置上有空位的子稱為外子,反之稱為內(nèi)子,連在一起的外子稱為前線或墻。下棋時要盡量減少自己的外子。第三章黑白棋程序概況3.1程序流程圖程序開始主界面程序開始主界面顯示標題中文菜單人機對戰(zhàn)人人對戰(zhàn)游戲說明退出游戲初始化游戲界面人機對戰(zhàn)函數(shù)人機對戰(zhàn)函數(shù)(人工智能模塊)3.2主要模塊簡介主菜單模塊(mainFace.h):該模塊用于顯示游戲開始前的主界面,其中包括初始化背景、漢字點陣顯示游戲標題“歡樂五子棋”、彩色菜單的移動和執(zhí)行。過度效果模塊(effect.h):該模塊存儲了幾種過度效果,用于在界面之間切換時使用。漢字字庫模塊(word.h):該模塊存儲了本程序用到的所有漢字的點陣字模。初始化游戲界面模塊(playFace.h):該模塊用于初始化游戲的界面,其中包括初始化棋盤、初始化各種在后面用到的結(jié)構(gòu)體、數(shù)組等變量。人機對戰(zhàn)模塊(pvs.h):該模塊是黑白棋實現(xiàn)人工智能的主要部分,其中包括計算機對棋盤的搜索、對當前局面的估值、并做出正確的反應,也是本程序的核心模塊。3.3程序設計思路從程序表面看,這是一個二維平面圖,所以數(shù)據(jù)用二維數(shù)組來表示,數(shù)組兩個下標可以表示棋盤上的位置,數(shù)組元素的值代表棋格上的狀態(tài),共有三種情況,分別是0代表空格,1代表白棋,2代表黑棋。這樣程序的主要工作是接收棋手按鍵操作,棋手用Up、Down、Left、Right控制光標移動,回車鍵表示落子。如果無棋可走則顯示停步信息。一旦接收到回車鍵或空格鍵,說明棋手落子,先判斷是否是有效位置,也就是說已經(jīng)有棋子的位置不能重疊落子,然后再判斷該位置能否吃掉對方的棋子(根據(jù)黑白棋的游戲規(guī)則,只能將棋子落子能吃掉對方棋子的位置上),如果條件滿足則在該位置落子,落子時執(zhí)行這樣幾個步驟,先調(diào)用畫棋子函數(shù),將棋盤的相應位置上畫上棋子,再調(diào)用吃棋子函數(shù),將對手的棋子變成自己顏色的棋子,然后根據(jù)吃掉對手棋子的個數(shù),給自己加上相應的分數(shù)和給對手減去相應的分數(shù),再將數(shù)組中的相應元素賦值,標志該位置已經(jīng)落子,最后將落子的權(quán)限交給對手。當輪到計算機落子時,計算機先對棋盤進行掃面,找出所有能落子的位置,在從找出的位置中選擇一個合理的進行落子,在選擇時本程序采用的是最大最小算法,在棋局的開局和中局采用最小戰(zhàn)術(shù),而在終局的時候采用最大戰(zhàn)術(shù),同時采用的戰(zhàn)術(shù)還有四角優(yōu)先,削弱行動力戰(zhàn)術(shù),這些將在第7章中詳細介紹。如果想退出游戲,可以按Esc鍵。第4章游戲主界面4.1背景設計為了增加程序的視覺效果,在屏幕上隨機位置畫出300個不同顏色的點,實現(xiàn)主界面背景模擬星空的效果。主要技術(shù)為畫點函數(shù)與隨機函數(shù)的配合使用,代碼如下:voidshowStar(void)/*星空效果*/{inti;for(i=0;i<300;i++){putpixel(random(640),random(480),random(15));}}4.2游戲標題在屏幕中上方以64*64的點陣字模顯示了“歡樂五子棋”五個字,先用灰色顯示這五個漢字,作為底色,然后將坐標向左上方偏移兩個像素,重新輸出,其中“黑”字用黑色,“白”字用白色,其余字用黃色顯示,以實現(xiàn)陰影字的效果。關(guān)于漢字點陣的輸出將在第六章中詳細介紹。4.3游戲主菜單 本程序的主界面采用的是彩色移動菜單,菜單共有4項分別為:人機對戰(zhàn)、人人對戰(zhàn)、游戲說明、退出游戲。實現(xiàn)菜單移動的技術(shù)與4.2中的標題相似,先將4個菜單以灰色為底色的陰影顯示在屏幕上,然后利用改變文字的前景色,來實現(xiàn)菜單視覺上的移動。再使用了一個變量sele來記錄程序內(nèi)部的當前菜單,當sele的值為1,表示當前菜單為人機對戰(zhàn)、2為人人對戰(zhàn)、3為游戲說明、4為退出游戲。 當程序執(zhí)行時,菜單的默認當前選項為人機對戰(zhàn)(即sele的初值為1),顯示效果為人機對戰(zhàn)的前景色用粉色,其余選項前景色用深灰色。當接收到鍵盤掃描碼(關(guān)于鍵盤掃描碼的接收將在第七章介紹)UP鍵或DOWN鍵時,相應改變sele的值,同時將原當前菜單的前景色用深灰色覆蓋,再將當前菜單的前景色用粉色表示。這樣不斷的按UP或DOWN時,就會實現(xiàn)菜單不斷移動的效果。 當按下回車鍵或是空格鍵時,表示要執(zhí)行當前菜單,則將sele的值作為參數(shù)傳給執(zhí)行菜單的函數(shù)即可。 進入游戲后的主界面的效果如圖4-1圖4–1游戲主界面第5章動畫過渡效果為了增加游戲換面切換的視覺效果,為本程序設計了以下幾個用戶畫面切換的過渡效果。為了下文描述方便,先了解一下屏幕的設計情況,本程序是在C語言的圖形模式下編寫的,在程序開始時,已經(jīng)將屏幕設置為分辨率為640*480像素,顏色為16色。下面程序?qū)⒂玫降暮甓x:#defineN40/*百葉窗的每個葉片的寬度*/#defineWW640/*屏幕的寬度*/#defineHH480/*屏幕的高度*/#definewaitdelay(60000);delay(60000)/*延遲一段時間*/4.1百葉窗效果百葉窗效果分為水平百葉窗和垂直百葉窗。以水平百葉窗為例。在高度能被40整除的位置上畫水平線,然后延遲100毫秒,再在高度能除以40余1的位置上畫水平線,再延遲100毫秒。不斷循環(huán)直到屏幕全部被覆蓋為止。代碼如下:voideffectWindow1(intcolor)/*水平百葉窗*/{inti,j;setcolor(color);/*設置前景色*/for(i=0;i<N;i++){for(j=0;j<480;j+=N){line(0,j+i,639,j+i);/*畫出水平線*/delay(100);/*延遲100毫秒*/}}}4.2隨機線效果隨機線也分為水平隨機線和垂直隨機線。以水平隨機線為例。屏幕的高度為480個像素,在每個像素上畫一條水平線,但是畫線的順序的隨機的,每兩條線之間延遲200毫秒。這里涉及到一個產(chǎn)生不重復隨機數(shù)的算法,具體代碼如下:voidrandLine1(intcolor)/*水平隨機線*/{inta[WW],b[WW],i,t;setcolor(color);/*設置前景色*/for(i=0;i<WW;i++)/*將數(shù)組a初始化*/a[i]=i;for(i=0;i<WW;i++)/*產(chǎn)生不重復的隨機數(shù)*/{t=random(WW-i);/*隨機產(chǎn)生數(shù)組a的下標,每次隨機X圍縮小1*/b[i]=a[t];/*將隨機產(chǎn)生的下標所對應的元素賦值給數(shù)組b*/a[t]=a[WW-i-1];/*將數(shù)組a后面的元素賦值給本次隨機出現(xiàn)的元素*/

/*避免下次重復出現(xiàn)相同的隨機數(shù)*/}for(i=0;i<WW;i++){line(b[i],0,b[i],479);delay(200);}} 產(chǎn)生不重復隨機數(shù)的方法是,先將預產(chǎn)生隨機數(shù)的X圍存儲到一個一維數(shù)組中,例如上面代碼中隨機數(shù)的X圍是0-639,共640個整數(shù),那么就定義一個長度為640的一維數(shù)組a,數(shù)組a中元素的初始值就設置為與下標相等的數(shù)。然后調(diào)用隨機函數(shù),X圍是0-639,產(chǎn)生隨機數(shù)后(假如這里產(chǎn)生的隨機數(shù)為100),并不直接使用該數(shù),而是將這個數(shù)作為數(shù)組的下標,將第100個元素的值取出(當然第一次隨機到100這個下標時,所對應的元素也是100),存放到另一個事先定義好的數(shù)組b中,然后將數(shù)組a的最后一個元素的取出,存放到第100個元素中。然后再次調(diào)用隨機函數(shù),但這次的隨機X圍變成0-638,這樣即使第二次產(chǎn)生的隨機數(shù)又是100,那么100這個下標所對應的元素已經(jīng)發(fā)生了改變。這樣每次循環(huán)產(chǎn)生隨機數(shù)后,都將隨機X圍縮小1,就可以實現(xiàn)產(chǎn)生不重復的隨機數(shù)了。4.3隨機出現(xiàn)的過渡效果實際上,每次換面切換的時候,調(diào)用的過渡效果也是隨機的,并且過渡效果所使用的顏色也是隨機產(chǎn)生的,以避免視覺上的疲勞。代碼如下:voideffect(void)/*隨機出現(xiàn)不同的過渡效果*/{switch(random(4))/*switch語句的參數(shù)為0到3之間的隨機數(shù)*/{case0:effectWindow1(random(15)+1);/*調(diào)用水平百葉窗,顏色隨機*/wait;/*延遲一段時間*/effectWindow1(0);/*再次調(diào)用水平百葉窗,顏色黑色*/break;case1:effectWindow2(random(15)+1);wait;effectWindow2(0);break;case2:randLine1(random(15)+1);wait;randLine1(0);break;case3:randLine2(random(15)+1);wait;randLine2(0);break;}}第6章漢字的顯示與移動6.1漢字點陣字模存儲模式在漢字操作系統(tǒng)中的漢字是以點陣形式存儲的,以16*16點陣為例,每個漢字由16*16=256個點組成,占用16*2=32個字節(jié)單元。字節(jié)的每一位表示一個點的屬性(1表示亮點,0表示暗點)。連續(xù)的兩個字節(jié)組成該漢字點陣。6.2漢字點陣輸出方法在C語言的圖形模式下,可以對點陣進行掃描,然后配合畫點函數(shù),將漢字輸出在屏幕上。首先利用漢字點陣字模工具,計算欲輸出漢字的字模。例如想輸出“歡”字,字體為宋體,點陣大小為16*16,使用點陣字模工具計算其字模為:charhuan16S[]={/*以下是'歡'的16點陣宋體字模,32byte*/0x00,0x80,0x00,0x80,0xFC,0x80,0x05,0xFE,0x85,0x04,0x4A,0x48,0x28,0x40,0x10,0x40,0x18,0x40,0x18,0x60,0x24,0xA0,0x24,0x90,0x41,0x18,0x86,0x0E,0x38,0x04,0x00,0x00,};再調(diào)用漢字點陣輸出函數(shù)將其顯示在屏幕的指定位置上,漢字點陣和調(diào)用語句如下:voiddrawmat(char*mat,intmatsize,intx,inty,intcolor)/*漢字點陣*//**mat是字模名,matsize是字模大小,x,y是漢字顯示的坐標,color是顏色*/{inti,j,k,m;m=(matsize-1)/8+1;for(j=0;j<matsize;j++)/*顯示漢字點陣的一行*/for(i=0;i<m;i++)/*顯示六個字節(jié)*/for(k=0;k<8;k++)/*顯示一個字節(jié)*/if(mat[j*m+i]&(0x80>>k))/*測試二進制位是否為可顯示的點*/putpixel(x+i*8+k,y+j,color);/*輸出像素點*/}drawmat(huan64Z,64,100,100,7);/*調(diào)用函數(shù)輸出漢字*/6.3漢字移動技術(shù)使文字移動的方法是多種多樣的,本文使用的是目標移動,即將被移動的目標由屏幕的一個位置移動到另一個位置。如果直接一步到位移動,沒有中間過程,會使人有生硬或突然感,動感不強,為了實現(xiàn)良好的動感,必須根據(jù)目標的大小及移動距離的長短分成苦干步來實現(xiàn),每動一步先用底色覆蓋原來的目標,再將移動目標復現(xiàn)在政一位置,這樣依次到目的地,由于人眼具有視覺暫留的生理現(xiàn)象,人的肉眼見此移動過程具有真實感。很多資料中又將這種動畫設計方法叫做中間化。用此法還可以進行平移、變形、旋轉(zhuǎn)等動畫設計。第7章人機對戰(zhàn)7.1游戲初始化在介紹各種模塊初始化前,先了解一下必要的變量。structHB{inta[8][8];/*0表示無棋子、1表示黑子、2表示白子*/intread;/*8表示該黑子下棋、15表示該白子下棋*/intx,y;/*表示當前光標的位置*/ints1,s2;/*s1表示白棋分數(shù),s2表示黑棋分數(shù)*/}hb;#defineSIZE8/*定義棋盤大小*/程序?qū)⒂枚S數(shù)組a來記錄棋盤發(fā)生的所有變化。7.1.1初始化棋盤這里的初始化棋盤包括兩部分內(nèi)容:一部分是在屏幕上打印出棋盤,使用戶可以根據(jù)棋盤的格子落子;另一部分是指初始化記錄棋盤變化的二維數(shù)組。那么先來看一下如何在屏幕上顯示一個8*8的棋盤,代碼如下:voiddrawQP(void)/*畫棋盤函數(shù)*/{inti,j;for(i=0;i<=SIZE*45/2;i++){for(j=0;j<=SIZE*45;j+=45){putpixel(60+j,60+i,3);/*棋盤距離邊框60個像素*/putpixel(420-j,420-i,3);putpixel(60+i,60+j,3);putpixel(420-i,420-j,3);delay(100);/*延遲100毫秒,使打印棋盤的時候具有動畫效果*/}}} 下面對二維數(shù)組進行初始化,由于黑白棋的游戲規(guī)則是在開局前每人就有兩顆棋子在棋盤的中央,那么初始化的工作除了將二維數(shù)組清零外,還需要將中間的四個元素分別賦值1和2,并調(diào)用打印棋子的函數(shù),將棋盤中間的位置打印上四個棋子,代碼如下:for(i=0;i<SIZE;i++)/*初始化棋盤*/for(j=0;j<SIZE;j++)hb.a[i][j]=0;hb.a[3][3]=2;/*初始化開始的四個棋子*/hb.a[4][4]=2;hb.a[4][3]=1;hb.a[3][4]=1;drawQZ(getX(3),getY(3),15);drawQZ(getX(4),getY(4),15);drawQZ(getX(4),getY(3),8);drawQZ(getX(3),getY(4),8);其中g(shù)etX(int)和getY(int)這兩個函數(shù)的作用是計算出數(shù)組下標在屏幕上所對應的位置。drawQZ(int,int,int)函數(shù)的作用是在屏幕上打印棋子,前兩個參數(shù)為打印棋子的坐標,第三個參數(shù)為打印棋子的顏色。7.1.2初始化光標當棋盤初始化工作完成后,就需要為用戶初始化一個光標,以便用戶可以選擇自己想要的位置落子,打印光標的代碼如下:voiddispMouse(intx,inty,intcolor)/*顯示光標函數(shù)*/{setcolor(color);/*設置前景色*/line(x-21,y-21,x-12,y-21);/*畫線段函數(shù),四個參數(shù)分別為線段的兩個端點*/line(x-21,y-21,x-21,y-12);line(x-21,y+20,x-21,y+12);line(x-21,y+20,x-12,y+20);line(x+20,y-21,x+20,y-12);line(x+20,y-21,x+12,y-21);line(x+20,y+20,x+12,y+20);line(x+20,y+20,x+20,y+12);}該函數(shù)共有三個參數(shù),其中x和y表示準備打印的光標的位置,而color為光標的顏色。本程序?qū)㈤_局光標定位在與數(shù)組a[2][2]相對應的位置上,代碼如下:hb.x=2;hb.y=2;dispMouse(getX(hb.x),getY(hb.y),15);7.1.3初始化分數(shù) 初始化工作的最后一步便是為用戶和計算機初始化分數(shù)。黑白棋的積分規(guī)則很簡單,棋盤上自己棋子的個數(shù)便是自己的分數(shù)。由于開局前每人已經(jīng)有兩個棋子,所以這里初始化分數(shù)應為2,代碼如下:hb.s1=2;hb.s2=2;/*初始化分數(shù)*/ 分數(shù)有了就要在屏幕上顯示出來,下面是打印分數(shù)的函數(shù),代碼如下:voidprintScore(void)/*顯示分數(shù)*/{charstr1[5],str2[5];sprintf(str1,"%d",hb.s1);/*將整型轉(zhuǎn)換成字符串,以便打印分數(shù)*/sprintf(str2,"%d",hb.s2);settextstyle(0,0,2);setcolor(6);setfillstyle(SOLID_FILL,7);bar(525,200,570,250);bar(525,240,570,310);outtextxy(530,208,str1);/*文本輸出函數(shù)*/outtextxy(530,248,str2);}在游戲的過程中,每落子一次便調(diào)用打印分數(shù)的函數(shù)一次,這樣用戶可以隨時了解自己得分情況,以便選擇合理的戰(zhàn)術(shù)進行游戲。7.2用戶操作7.2.1鍵盤掃描碼在計算機中,當按下鍵盤上的任意一個鍵子后,將返回一個16位的二進制數(shù),它包括兩種不同的值。當按下“普通鍵”(例如:A、d、&、4等)時,它的低8位數(shù)存放該字符的ASCII碼。對于“特殊鍵”(例如:方向鍵、Ctrl、Alt等),低8位為0,但高8位存放的該鍵子的掃描碼。既然可以用掃描碼來表示一些特殊鍵,那么如何獲得鍵盤的掃描碼呢?可以調(diào)用C語言函數(shù)庫中的一個函數(shù)bioskey(0)。該函數(shù)的作用就是從鍵盤接收掃描碼。7.2.2控制光標移動 通過接收鍵盤掃描碼,程序可以得知用戶按了那些鍵子,在通過對這些按鍵掃描碼的分析,如果是方向鍵的掃描碼,程序就會認為是用戶移動了光標,。代碼如下:#defineUP0x4800/*定義四個方向鍵的掃描碼*/#defineDOWN0x5000#defineLEFT0x4b00#defineRIGHT0x4d00if(key==UP||key==DOWN||key==RIGHT||key==LEFT){dispMouse(getX(hb.x),getY(hb.y),0);/*用黑色覆蓋掉當前的光標*/if(key==UP&&hb.y>0)/*根據(jù)不同的方向,改變相應的坐標*/hb.y--;elseif(key==DOWN&&hb.y<(SIZE-1))hb.y++;elseif(key==LEFT&&hb.x>0)hb.x--;elseif(key==RIGHT&&hb.x<(SIZE-1))hb.x++;dispMouse(getX(hb.x),getY(hb.y),15);/*打印改變位置后的光標*/}該函數(shù)首先判斷用戶按的鍵子是否為四個方向鍵中的任意一個,在用背景色覆蓋掉當前的光標,然后在具體判斷接收到的掃描碼是屬于那個方向鍵的,7.2.3判斷落子當程序檢測到接收的鍵盤掃描碼為空格或回車時,則程序就認為用戶執(zhí)行了落子的操作,但根據(jù)黑白棋的游戲規(guī)則,并非所有空的格子都可以落子。只有在能吃掉對方棋子的位置上才可以落子。這樣就需要程序具有判斷某個位置是否能夠落子的功能。要判斷能否吃掉對方的棋子,就要利用記錄棋盤變化的二維數(shù)組。當光標移動到某個位置上時(假如光標的坐標為[3][3]),用戶按了回車或空格,首先判斷a[3][3]元素的值,如果該值為0,則表示該位置未落子,做進一步的判斷,如果值不為0,則表示該位置已經(jīng)落子(值為1表示黑子,2表示白子),這時程序不做任何反應,讓用戶繼續(xù)移動光標?,F(xiàn)在要討論的是值為0時所做的進一步判斷。請看游戲開局時的情況,如圖:7-1

圖7-1游戲開局圖7-1為游戲開局時的狀態(tài),用戶持黑棋,計算機持白棋,雙方都未落子,黑棋先走,此時用戶可以有4種選擇(白色圓圈標出),但除了上圖所標出4個可落子的位置外,如果用戶在其他位置按下回車或空格的話,程序是不錯任何反應的。那么程序如何做到這點的呢。假如用戶在上圖顯示光標的位置落子,程序會以a[2][2]元素為中心,分別向八個不同的方向(上、下、左、右、左上、右上、左下、右下)判斷,以上和右下為例,先判斷上方與a[2][2]相鄰的a[1][2]元素,由于a[1][2]位置未落子,所以值為0,表示該方向不能吃掉對方棋子,返回值為0。再來看右下方的判斷,先判斷a[3][3]元素,該位置有白子,值為2,滿足條件,繼續(xù)向右下方判斷a[4][4]的值,仍然為2,繼續(xù)判斷a[5][5],值為0,同樣也不能吃掉對方的棋子,所以也返回0值。以此類推,當判斷完八個方向后,返回值都為0,則表示該位置無法吃掉對方棋子,程序則認為用戶在該位置按下的空格或回車鍵無效。此時程序不做任何處理,等待用戶移動光標后落子在做判斷。 如果用戶將光標移動到圖7-1中“2”的位置上,再按回車時,程序仍然重新掃描八個方向,此時程序會發(fā)現(xiàn)在做右方判斷時,由于能吃掉對手一個棋子,所以返回值為1。表示該位置為有效的落子位置,判斷落子的代碼如下:intjudge1(intx,inty,intcolor,intop)/*判斷方向左斜上*/{inti=1;if(hb.a[x-1][y-1]==0||x==0||y==0||hb.a[x-1][y-1]==color)

/*去掉幾種明顯錯誤,當左上方相鄰的位置是空或者是自己的棋子時,則該方向無效,或則當前位置已經(jīng)是最上邊或最左邊時,也表示該方向無效。滿足上邊任何一個條件,都無需在繼續(xù)判斷,直接返回0值*/return0;while(hb.a[x-i][y-i]!=0&&hb.a[x-i][y-i]!=color&&x-i>=0&&y-i>=0){if(op==1){drawQZ(getX(x-i),getY(y-i),hb.read);hb.a[x-i][y-i]=color;}i++;}if(x-i>=0&&y-i>=0)return(hb.a[x-i][y-i]==color)?i-1:0;elsereturn0;}像上面這樣的函數(shù)共有8個,分別判斷8個不同的方向。由于篇幅關(guān)系,這里只給出了一個判斷左上方的函數(shù),其它方向的判斷與此雷同(其余函數(shù)名為judge2…judge8)。給出的函數(shù)功能是做左上方的判斷,共四個參數(shù),其中x和y為要判斷落子點的坐標,color為要判斷棋子的顏色,而op表示要執(zhí)行的操作,0表示僅判斷該位置是否能夠落子,1則表示吃掉對手的棋子,及對數(shù)組a中的相應元素重新賦值,表示該位置已經(jīng)是自己的棋子,并用調(diào)用畫棋子函數(shù)將吃掉對手棋子改變成自己顏色的棋子。 這8個函數(shù)是最基本的掃描棋盤操作,下面將要介紹的行動力判斷,預測對手行動等都將用到這8個函數(shù)。為了每次判斷落子的操作能夠變得簡單,這里又編寫了一個函數(shù)judgeEnter(),該函數(shù)的功能就是調(diào)用上面的8個函數(shù),然后將8個函數(shù)的返回值累加起來作為該函數(shù)的返回值,這樣當需要判斷能否落子時,只需調(diào)用該函數(shù)即可,如果返回值為0,則表示該位置無效,不能落子。否則將返回能吃掉對手棋子的個數(shù),代碼如下:intjudgeEnter(intx,inty,intcolor)/*判斷x,y位置能吃掉對方棋子個數(shù),返回0則表示不能落子,color表示棋子顏色*/{intn=0;/*變量n記錄吃掉對手棋子的個數(shù)*/if(hb.a[x][y])return0;/*如果該位置有棋子,則直接返回0*/n+=judge1(x,y,color,0);/*分別調(diào)用8個函數(shù),并累加函數(shù)返回值*/n+=judge2(x,y,color,0);n+=judge3(x,y,color,0);n+=judge4(x,y,color,0);n+=judge5(x,y,color,0);n+=judge6(x,y,color,0);n+=judge7(x,y,color,0);n+=judge8(x,y,color,0);returnn;} 有了上面這個函數(shù),很容易就可以實現(xiàn)對落子的判斷了,請看下面的代碼:if((key==ENTER||key==SPACE)&&hb.a[hb.x][hb.y]==0)

/*如果用戶按了回車或空格,并且該位置為空*/{i=hb.x;j=hb.y;if(ch=judgeEnter(hb.x,hb.y,1))/*調(diào)用判斷落子函數(shù)*/{drawLast(hb.x,hb.y,1);/*調(diào)用吃掉對手棋子的函數(shù)*/hb.read=15;/*將落子的權(quán)限交給計算機*/hb.a[i][j]=1;/*將該位置所對應的數(shù)組元素賦值為1*/hb.s1+=ch+1;/*為自己加上相應的分數(shù)*/hb.s2-=ch;/*給對手減去相應的分數(shù)*/}}7.2.4判斷游戲是否結(jié)束下面介紹如何判斷游戲結(jié)束,我們先來看一下黑白棋游戲的結(jié)束規(guī)則:當雙方都沒有行動力的時候,則為游戲結(jié)束。那么要判斷游戲是否已經(jīng)結(jié)束,就需要用到一個檢測行動力的方法。那么如何檢測自己的行動力呢?這里仍然是利用上面介紹過的8個判斷落子的函數(shù),代碼如下:intmoveTimes(intcolor)/*檢測行動力,color代表棋子顏色*/{inti,j;intn=0;/*n為統(tǒng)計共有多少個位置可以走*/for(i=0;i<SIZE;i++)/*兩層循環(huán)對棋盤進行掃描*/{for(j=0;j<SIZE;j++){if(hb.a[i][j]==0&(judge1(i,j,color,0)||judge2(i,j,color,0)||judge3(i,j,color,0)||judge4(i,j,color,0)||judge5(i,j,color,0)||judge6(i,j,color,0)||judge7(i,j,color,0)||judge8(i,j,color,0)))n++;/*如果該位置能落子,則n++*/}}returnn;} 上面這段代碼的功能為檢測行動力,如果返回值為0,則表示自己已經(jīng)沒有位置可走了,只能將落子的權(quán)限交給對手,然后對手再調(diào)用該函數(shù)檢測行動力,如果返回值也為0,則表示雙方已經(jīng)都沒有行動力了,則游戲結(jié)束。當游戲結(jié)束后,程序根據(jù)雙方得分情況,判斷是哪一方獲勝或者是和棋,然后給出相應的提示信息,代碼如下:intjudgeGameover(void)/*如果黑棋勝出返回1,白棋勝出返回2,勝負未分返回0,平手返回3*/{if(moveTimes(1)==0&&moveTimes(2)==0)/*如果雙方都沒有行動力了,則游戲結(jié)束*/if(hb.s1>hb.s2)return1;elseif(hb.s1<hb.s2)return2;elsereturn3;return0;}由于每落子一次都有可能使游戲的結(jié)束,所以在每次落子后都會調(diào)用上面這個函數(shù),來檢測游戲是否已經(jīng)結(jié)束。7.3電腦戰(zhàn)術(shù)分析在這一節(jié)中將介紹計算機是如何對棋盤進行分析,然后選擇一個合理的位置進行下棋的。7.3.1棋盤掃描想要計算機能夠與人對弈黑白棋,對棋盤的掃描是最基本的操作。前面已經(jīng)介紹了與棋盤一一對應的是一個二維數(shù)組a,那么要想對棋盤進行掃描,實際上就是對這個二維數(shù)組進行掃描,這樣對棋盤的掃描工作就比較簡單了,實際上只要使用一個兩層循環(huán)便可實現(xiàn)對二維數(shù)組的掃描。這個循環(huán)在7.2.4節(jié)中已經(jīng)出現(xiàn)過來,這里就不再累述。7.3.2判斷行動力 在2.3節(jié)黑白棋戰(zhàn)術(shù)分析中已經(jīng)提到,黑白棋的正確戰(zhàn)術(shù)應該是盡量削弱對手的行動力,讓對手全無好棋可下,同時增加自己的行動力。那么如何能讓計算機懂得這個道理呢?這就要求計算機具有“思考”的能力。首先計算機調(diào)用檢測行動力的函數(shù)moveTimes(),檢測自己的行動力,也就是將當前棋盤所有能落子的位置找出來,然后在對這些位置逐步進行分析。分析的過程就是先假設計算機在某個位置上落子,然后馬上再次調(diào)用檢測行動力函數(shù),不過這次是檢測對手的行動力。意思就是如果計算機在這里落子,看看對手的行動力如何,如果對手的行動力太大,對手有很多位置可以選擇,那么就不應該在這里落子。如此對所有能落子的位置進行檢測,找出一個能讓對手行動力變得最小的位置落子,代碼如下:min=100;/*先假設對手的行動力為一個不能達到的最大值*/for(i=0;i<SIZE;i++)/*掃描棋盤*/{for(j=0;j<SIZE;j++){if(judgeEnter(i,j,2))/*判斷該位置是否能夠落子*/{hb.a[i][j]=2;/*假設計算機在該位置落子*/if(min>(max=moveTimes(1)))/*檢測對手的行動力,并與上次假設的結(jié)果進行判斷*/{x=i;/*記錄能令對手行動力變得最小的落子位置*/y=j;min=max;}hb.a[i][j]=0;/*取消假設*/}}}if(min!=100)/*判斷min的值是否發(fā)生了變化*/{ch=judgeEnter(x,y,2);/*計算x,y位置能吃掉對手棋子的個數(shù)*/drawLast(x,y,2);/*將對手的棋子吃掉*/hb.a[x][y]=2;/*對落子點與數(shù)組對應的元素賦值*/hb.read=8;/*將落子權(quán)限交給用戶*/hb.s1-=ch;/*給用戶減去相應的分數(shù)*/hb.s2+=ch+1;/*為自己加上相應的分數(shù)*/}7.3.3四角優(yōu)先戰(zhàn)術(shù) 黑白棋有幾個很重要的點,那就是棋盤上的四個角,因為四角上的棋子是絕對不會被吃掉的。在游戲過程中絕不能輕易的讓對手進角。不讓對手進角的最簡單的辦法就是不在與四角相鄰的位置落子。這里將四角的坐標和與四角相鄰的坐標分別放到兩個數(shù)組中:intaa[4][2]={{0,0},{0,7},{7,0},{7,7}};/*四角坐標*/intbb[12][2]={{0,1},{1,0},{1,1},{0,6},{6,0},{1,6},{1,7},{7,1},{6,1},{6,6},{6,7},{7,6}};/*存儲與四角相鄰坐標*/既然四角為不會被吃掉的穩(wěn)定角,對棋局的勝負起著很重要的作用,所以在不讓對手進角的同時自己卻要努力進角。有了這個戰(zhàn)術(shù),計算機在每次掃描棋盤的前首先對四角進行判斷,如果四角能夠落子,則優(yōu)先在四角落子,此為四角優(yōu)先戰(zhàn)術(shù),代碼如下:ch=0;/*先假設四角都不能落子*/for(i=0;i<4;i++)/*對四角進行掃描*/{x=aa[i][0];y=aa[i][1];if(ch=judgeEnter(x,y,2))/*判斷四角能否落子,如果能羅則退出循環(huán)*/break;}if(ch)/*如果四個角能落子*/{drawLast(x,y,2);/*吃掉對手棋子*/hb.a[x][y]=2;hb.read=8;hb.s1-=ch;hb.s2+=ch+1;} 上面這段代碼功能是努力讓計算機進角,那么如果四角都不能進,則需對棋盤進行掃描,掃描時首先取消對與四角相鄰位置的判斷,但并非盲目的取消,如果某個角已經(jīng)被計算機所占據(jù),那么與這個角相鄰的位置就不會被取消,代碼如下:for(i=0;i<SIZE;i++)/*掃描棋盤*/{for(j=0;j<SIZE;j++){if(i==0&&j==1&&hb.a[0][0]==0)continue;/*盡量不在四個角的相鄰位置下棋*/elseif(i==1&&j==0&&hb.a[0][0]==0)continue;elseif(i==1&&j==1&&hb.a[0][0]==0)continue;elseif(i==0&&j==6&&hb.a[0][7]==0)continue;elseif(i==6&&j==0&&hb.a[0][7]==0)continue;elseif(i==1&&j==6&&hb.a[0][7]==0)continue;elseif(i==7&&j==1&&hb.a[7][0]==0)continue;elseif(i==1&&j

溫馨提示

  • 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. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論