文/jorge
其實我不玩網(wǎng)絡(luò)游戲的,所以對于外掛類程序也沒什么好或壞的感覺,甚至平時基本不會想到這個概念。這個實驗項目一開始稱為“掃雷助手”,而究其技術(shù)含量,與現(xiàn)在真正實用的游戲外掛程序也沒有可比性。設(shè)計它的意義,無非在于對某些Windows API的的進一步熟悉,使從未涉足過此領(lǐng)域的新手(當(dāng)初的我自己)能夠揭開某些“神秘的面紗”。之所以選擇“掃雷”這個最經(jīng)典的小游戲進行hack,一方面,使這個項目更貼近生活,更容易被理解,另一方面也可以最大化本人的成就感^_^,畢竟,在新手中,對掃雷的hack的探索似乎從來都沒有停止過,從早期的修改.ini文件和注冊表,到后來的Esc和xyzzy,無不體現(xiàn)著一代代人對這個目標(biāo)的不懈追求^_^。而對于我們這些搞專業(yè)的來說,則應(yīng)該有專業(yè)一點的方式,要有點技術(shù)含量!于是我做了這個叫MineAssistant的項目。
它的原理說來也不難,無非實時地替人做兩件事:1。把一定是雷的方塊標(biāo)上雷的記號,2。把一定不是雷的方塊點擊開。至于輕易判斷不了是不是雷的,還得靠你的運氣。其實,掃雷游戲中,這兩項最簡單的操作絕對是占了絕大多數(shù)時間的,不妨看看實測的效果:我使用掃雷外掛的紀(jì)錄是:初級、中級都1秒,高級4秒。(和修改注冊表的相比還是差了一點,不過那個一點技術(shù)含量都沒有,呵呵)
顯然,這個實現(xiàn)過程涉及到了從一個程序操作另一個程序的窗口。這必須使用Windows API,主要的有下面幾個:
 FindWindow
 GetDC
 GetPixel
 PostMessage
稍微有點基礎(chǔ)的看也看得出來,本人對于掃雷進程的內(nèi)部數(shù)據(jù)是一無所知的,對于當(dāng)前雷區(qū)的狀態(tài)信息的取得,都是通過最淺顯最笨的方法,就是直接讀取屏幕像素。而反饋的操作,也都是通過PostMessage簡單的發(fā)送一條信息來模仿鼠標(biāo)點擊。這樣,本程序就自然的分成了兩個層次,一個是與掃雷窗口的接口層,一個是實現(xiàn)判斷的算法層。若是有基礎(chǔ)的人,在提示到這以后,應(yīng)該就可以自己來實現(xiàn)它了^_^,但就本人的經(jīng)驗來看,還有一個難點,就是如何從一個個像素的取值來分析出每個方塊是什么狀態(tài)。難不成用模式識別?!!別緊張,當(dāng)初本人看了別人寫的象棋對戰(zhàn)程序,也忐忑地問了一句:難道要用人工智能?對方笑答,沒那么嚴(yán)重,說這個算法你也寫得出來。——實際上,只要檢查每個方塊上一兩個特定位置像素,就可以得知這個方塊的性質(zhì)。當(dāng)然,怎樣找到這一兩個像素的位置,還是要費一番周折的。為此,我寫了好幾個臨時程序,專門用來測量“掃雷”窗口的各種尺寸參數(shù)。基本原理是,用FindWindow和GetDC得到掃雷窗口的HDC,然后把整個畫面寫到一個.bmp文件中去,再用Windows畫圖將其打開,用放大鏡放到最大倍數(shù),然后……一個個像素地數(shù)!另外,還用ResHacker把掃雷程序中的位圖資源提取出來,把小方塊中所有像素用程序進行掃描,以找到方塊內(nèi)某個特定像素,靠其顏色足以區(qū)分各種方塊(未挖開的空白,未挖開的插旗,未挖開的問號,和挖開的1~8的數(shù)字,和挖開的空白)。在這其中我郁悶地發(fā)現(xiàn),任何一個像素都不可能完全區(qū)分它們,因為掃雷窗口上的顏色總共還沒有那么多種。引入第二個像素是不可避免的,于是我用另一個位置的像素,首先區(qū)分是挖開的還是沒挖開的,才算解決了這個問題。
另外,關(guān)于開發(fā)工具的選擇。“程序員就像男人,編程語言就像女人,一般男人都想要很多女人,可沒幾個男人能真正了解一個女人”,這句話引自CSDN首頁上曾看到的網(wǎng)友評論,本人當(dāng)初也曾有過少年輕狂的時候,要了不少“女人”,以為女人越多真的越牛X,導(dǎo)致現(xiàn)在還對不少編程語言都一知半解。在做這個程序的時候,最了解的是Delphi,所以就用Delphi實現(xiàn)了。現(xiàn)在想來,Delphi確實是做此類程序的較好的選擇。它和Windows底層有良好的互操作性,唯一不便則是,從MSDN中看到的WinAPI的聲明都是C的,在Delphi中要稍微變換一下長相,而這些資料則是Borland所缺乏的。另外,再吹毛求疵一點,就是Delphi屏蔽了太多底層細節(jié),使很多初學(xué)者冷丁與HDC等概念打交道時會陌生。但一般來說,這更像是使用者的毛病,而不是開發(fā)工具的。另外,C++也是個好選擇,如果拿到今天,也許我更愿意用C++去實現(xiàn)它,C++配上wxWidgets,用來開發(fā)Windows應(yīng)用程序真不是鬧著玩的。但我一定不會喜歡用java來實現(xiàn)它的,原因我想不必說大家也知道!
好,現(xiàn)在用Delphi開始掃雷外掛的開發(fā)之旅。首先,來看一下前面提到的,本人跋山涉水啊,翻山越嶺啊,費盡心思搜集來的掃雷窗口資料。所有資料取自Windows xp下帶的掃雷“版本5.1”。注意,WinXP下的掃雷與Win9x中的,窗口圖形有點細微差別,這足以使該外掛在Win9x下無法正確運行。不過我最終還是不打算加進判斷OS版本并采用兩套不同參數(shù)的代碼了,畢竟只是個實驗項目!
實測數(shù)據(jù)(單位為像素):
=================================================================
每個小方塊:寬=16,高=16
雷區(qū)的最大可能大小:寬=30個方塊, 高=24個方塊
從雷區(qū)的四邊,到窗口客戶區(qū)的四邊,各有間隔,分別為:左=12,右=8,上=55,下=8
在每一個方塊內(nèi),如下兩個像素可用來判斷該方塊的性質(zhì)(坐標(biāo)為相對方塊左上角得值):
 首先判斷(0,0)處,若為clWhite,則為未挖開的方塊,若為clGray,則為挖開的。
 若是未挖開的方塊,可再判斷(5,4),對應(yīng)關(guān)系如下:
  clSilver:空白
  clRed:插旗
  clBlack:問號
 若是挖開的方塊,可再判斷(7,4),對應(yīng)關(guān)系如下:
  clSilver:空白(相當(dāng)于數(shù)字0)
  clBlue:數(shù)字1
  clGreen:數(shù)字2
  clRed:數(shù)字3
  clNavy:數(shù)字4
  clMaroon:數(shù)字5
  clTeal:數(shù)字6
  clBlack:數(shù)字7
  clGray:數(shù)字8
=================================================================
另外,雷區(qū)上方的“重開始”按鈕的狀態(tài)也是很重要的數(shù)據(jù),對于它的判斷,后面遇到的時候有詳述。
新聞熱點
疑難解答