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