程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> windows SDK的C語言黑白棋開發

windows SDK的C語言黑白棋開發

編輯:關於C語言

最近在做數據結構的課程設計,選擇了難度最大的黑白棋開發,因為已經決定使用純C進行開發,所以之前朋友們說使用MFC開發就果斷不去做了。網上有很多黑白棋的源碼,不過大部分C語言的源碼不是調用graphic庫開發就是使用C++進行MFC開發,極少有像我這樣用著純C調用著Windows API進行開發的例子,所以既然自己痛苦了那麼久,如果以後有人也想和我一樣痛苦,我這裡分享一下我的經驗,就算不能從技術上幫到他,也能從心理上安慰一下他。廢話不多說,直接來談我的設計吧。

實現方式:

因為上次的C語言課設我就使用了Graphics庫進行了dos圖形界面的實現,所以這次數據結構的實驗我想使用不同的實現方式,就采取了純C調用SDK函數進行設計windows程序,但我還沒有形成完整的面向對象的思想,所以在一開始就放棄了使用MFC編寫程序。其實MFC也就是把windows的API用class進行封裝了再使用,在網上能找到很多使用MFC寫的黑白棋程序,但極少能有使用純C直接調用windows API寫的程序,我想這一點應該是一個突破。當然我並不是說使用MFC寫程序不如SDK編程,只是為了將來更好的學習MFC,眼下我有必要掌握SDK編程,這樣可以幫助我更加了解MFC Classes的結構,而MFC沒有提供的API功能自己可以調用API來實現,當MFC Classes不合我的需求時我可以方便的更改其Class。總之最後我決定采取SDK編程。

知識儲備:

因為之前我編寫windows程序的經歷就只有寫過一個對話框程序的俄羅斯方塊,那個邏輯相比黑白棋要簡單很多,所以這次其實我還是得從頭開始學習編寫windows程序。我需要了解事件驅動的過程,需要了解windows一些基本的API 功能,還需要了解windows的消息處理機制,同時我還需要保持頭腦清醒去設計我的程序邏輯,當然,這些知識大部分都能在MSDN中查詢到,所以這個暑假MSDN我看了很久。

難點疑問:

因為在windows程序的編譯器環境下調試起來比一般的程序調試要困難,雖然斷點可以隨便打,但想要攔截消息卻不是那麼容易,而且由於windows編程經驗不足,導致在編程時走了很多彎路,本來可以不發送消息的地方我還特意顯示的調用API發送消息,比如繪制主窗口的地方,當窗口被移動或是被擋住時,程序會自動向窗口句柄發送WM_PAINT消息,因為之前不知道這點,在程序設計時自己顯示調用函數發送這個消息,結果導致界面不停閃爍。這類問題很多,相信老師明白我說的意思。相比較而言黑白棋邏輯的設計反倒顯得簡單點,因為網上有很多資料可供查閱,光黑白棋的下子算法就有一大堆,什麼基本搜索算法,α-β剪枝算法,主要變化搜索算法,Zobrist散列算法,MTD(f)算法,迭代加深搜索算法等等,有很多這方面的資料可以查閱,但同時我也看到了我的不足,對於這些算法,看雖然看的懂,但讓我自己設計恐怕無法設計出這些巧妙的算法,還有些算法我甚至現在無法明白究竟是什麼意思,比如模擬退火算法,神經網絡算法等等。數據結構就是算法的基礎,可見我還有很多需要學習的地方。

資源設計:

本程序是windows下的程序,必然需要尋找資源,如圖片,聲音等等。這次我在網上下載了大量的黑白棋圖片和聲音資源,最終采取了一組黑白棋的資源,用VC++的資源編輯器編輯進了工程:

clip_image002

然後我自己創建了多個對話框和菜單也作為資源進行編輯:

1、關於黑白棋的對話框:

clip_image004

2、開局選項對話框:

clip_image006

3、進入英雄榜對話框:

clip_image008

4、幫助對話框:

clip_image010

5、英雄榜對話框:

clip_image012

6、設置對話框:

clip_image014

7、輸棋對話框:

clip_image016

8、贏棋對話框:

clip_image018

9、平棋對話框:

 

clip_image002[4]

10、菜單:

clip_image004[4]

模塊設計:

我對這個黑白棋程序做過兩次模塊設計,第一次我分了4個模塊,主模塊,繪圖模塊,邏輯控制模塊,結束處理模塊,後來我發現這樣的設計太過於拘泥於軟件成型的過程,而且我的程序不是一個非常大的工程,整個程序只有約2000行代碼左右,所以我省去了前期的模塊設計,直接進行編碼,最終只有一個main.c的主模塊程序,其他的邏輯功能實現全部交由main.h來實現,在global.h中定義了全局變量,resource.h文件是資源編輯器自動生成的文件,記錄了各種資源的ID宏定義。

clip_image006[4]

AI設計:

電腦黑白棋最核心的部分就是搜索算法,它實際反映了黑白棋程序的算棋過程。搜索算法的好壞,將直接影響著程序的算棋速度和棋力。下面我們就從最基本的搜索算法開始。

對於圖1所示的局面,白棋有三步棋可下:D6、F4、F6,黑白棋程序將如何找出最佳的棋步呢?

clip_image007
圖1 白先,三步棋可下

其實程序的算棋過程和人類棋手很相似,它先對當前局面所有能下的棋步進行搜索,計算出每種棋步變化之後的局面,並根據各種局面結果,從中找出對自己最有利的一步棋。我們先來看看程序算一步棋的情況。在圖1中,如果白棋分別下D6、F4、F6後,將形成圖2、圖3、圖4三種局面。

clip_image008[4]
圖2 黑先,估值為0

clip_image009
圖3 黑先,估值為+6

clip_image010[4]
圖4 黑先,估值為0

程序將對這三個局面分別進行評估,看看局面是優勢還是劣勢?這個局面評估過程一般由估值函數來完成。估值函數將根據盤面上棋子的分布情況,給出一個表示局面優劣程度的評估數值,這就稱為估值。一般來說,估值為正時,表示局面處於優勢,正值越大,優勢越大;反之,負值表示劣勢。例如,圖3的局面對於黑棋而言略占優勢,程序可能會給出+6的估值;而對於圖2和圖4,由於局面對雙方均勢,估值都是0。由於局面的優劣是相對的,對於一方來說是優勢的局面,換從另一方角度來看就會是完全相反的結果。

估值可以有不同的取值范圍,許多程序的估值是取值[-64, +64],以便直觀地表示對終局比分的評估,如“估值為+6”則表示當前局面具有勝6子的優勢。

通過對這三步棋所形成的局面進行評估,程序就可得到各步棋的估值見圖5)。由於這時下棋方是白棋,F4這步棋的估值就成了負值。換句話說,F4這步棋對白棋不利。

clip_image011
圖5 白先,三步棋的估值

很顯然,面對各種可能的棋步及其估值,下棋方最終會選擇估值最大、也就是對自己最有利的那步棋。因此,白棋會選擇下D6或F6,而不會下F4。程序的搜索過程就是將估值極大化,從而找出最佳棋步。

本程序的AI我設計為三個等級,第一個等級的AI采用的是最簡單的估值函數,使用的是模板估值,而且模板是固定的,棋盤上各個地方的值是確定的,所以這個等級的AI沒有隨機性,有確定的走法,人很容易就能夠贏了它;第二個等級的AI采用的是翻轉能夠贏得棋子最多的那步落子,如果出現有多處翻轉的棋子一樣多的情況就設置隨機量,從中任選一個。這樣設計的棋力也是十分低的,因為了解黑白棋的人都知道,黑白棋的關鍵在於誰先能搶占到4個角落,因為角落一旦被搶到就不會再改變顏色了,所以角落的值應該最高,還有邊的分值應該也很高,而且邊的各處分值也應該不一樣,這在我的估值模板中有所體現。第三個等級的AI本來是想采用深層搜索多步來實現更加精確的估值,並采用α-β剪枝算法來進行優化的,但時間不足,所以沒有完善它。

函數調用關系圖:

clip_image002[6]

主界面:

clip_image002[8]

 

由於代碼太長,所以我這裡就不貼出來了,需要的朋友可以留下聯系方式。如果正好有做過黑白棋設計的朋友可以和我交流下,我過段時間也想試下MFC設計。

本文出自 “菜鳥浮出水” 博客,請務必保留此出處http://rangercyh.blog.51cto.com/1444712/394825

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved