连连看外挂1.0
??????? 一時興起,決定寫個連連看的外掛玩玩...于是斷斷續(xù)續(xù)經(jīng)過幾個晚上的努力基本呈現(xiàn)雛形...之前也看過一些外掛技術(shù)的文章,確實(shí)這里面的技術(shù)深不可測,第一次寫就搞個簡單的吧,以后再慢慢改進(jìn)。
??????? 最簡單的外掛莫過于器械式的,也就是通過界面分析,然后去模擬一些鼠標(biāo)或者鍵盤動作。連連看外掛就可以通過這種方式去寫。整個外掛基本分為以下幾步完成:
1. 獲取界面信息,當(dāng)然最主要的是方格信息,有了這個其實(shí)足夠?qū)懸粋€連連看外掛了,但是為了功能更強(qiáng)大,我另外獲取了其他一些界面元素,比如其他玩家的速度(剩下的方格速),開始按鈕的位置等等。
2. 連連看算法的實(shí)現(xiàn),其實(shí)這個是比較簡單的。基本可以分為兩種:兩條X連線+一條Y連線、兩條Y連線+一條X連線。當(dāng)然也包括了各種特殊情況。比如一條X一條Y等等。
3. 鼠標(biāo)事件的模擬。
1. 獲取界面信息
??????? 這部分工作其實(shí)是最繁瑣的,只能依靠不斷的調(diào)式去完成,我在這個過程使用到了系統(tǒng)鉤子,在一定程度上簡化了這個過程。首先要獲得的是每個方格的信息,QQ連連看中一共有11×19個方格數(shù),一共有44(好像45)種不同的圖案,這個基本可以靠肉眼獲得。
??????? 接下來的事情就需要代碼去完成了,主要包括起始點(diǎn),每個方格的長和寬,可以唯一區(qū)分每種圖案的N個像素點(diǎn)。首先需要獲得一個大概的數(shù)值,我寫了一個系統(tǒng)的鼠標(biāo)鉤子,主要完成的功能是通過鼠標(biāo)在QQ連連看窗口的點(diǎn)擊,獲得該點(diǎn)的client端坐標(biāo)和顏色值。基本代碼如下:
??????? 另外在def文件中需要將InstallHook跟UnInstallHook導(dǎo)出。另外注意到在InstallHook中需要一個參數(shù)HWND,這個參數(shù)需要在調(diào)用這個DLL的客戶端代碼中獲得。方法自然是用EnumWindows函數(shù)去枚舉桌面上的所有窗口然后找到連連看窗口。
??????? 通過這個方式,然后加上一些簡單的調(diào)式,或者如下四個數(shù)據(jù):
??????? 接下的需要做的也是最重要的就是在每個方格上取N個點(diǎn)來唯一的表示一種圖案。那么N應(yīng)該是多少呢?自然是越少越好,程序才能跑的快。之前我也是隨機(jī)的在方塊上取4-5個點(diǎn),但是仔細(xì)一算一共209個小方塊,那需要調(diào)用1000+次GetPixel,這大大影響了程序的運(yùn)行速度。如果能用一個唯一的點(diǎn)的顏色會表示一個圖案自然最好,但是這個似乎找起來有難度。不管三七二十一,我先取了中心點(diǎn)再說,看看究竟能區(qū)分多少方塊。為了這個我再次使用到了鉤子,這次的鉤子我需要完成這件事情:在QQ連連看窗口上用鼠標(biāo)右擊某個圖案,然后可以獲得這個圖案上特定點(diǎn)的位置,跟前一個鉤子不同的主要是MouseProc函數(shù):
??????? 當(dāng)然還要加上之前獲得的4個常量才能通過編譯。不難看出在這個MouseProc中我們使用了兩個點(diǎn)唯一的區(qū)分一個圖案,一個中心點(diǎn)一個中心點(diǎn)偏上10個像素。但是其實(shí)這并不是一開始就獲得的結(jié)果,起初我就取了一個中心點(diǎn),然后通過不斷的測試,找到QQ連連看中每一種圖案中心點(diǎn)的顏色值,結(jié)果發(fā)現(xiàn)中心點(diǎn)可以區(qū)分出44種不同圖案中的39種,另外5種圖案中共有兩種顏色值。如下圖所示,紅顏色的兩個圖案中心點(diǎn)像素值相同,藍(lán)顏色的三個圖案中心點(diǎn)像素也相同。
????????
??????? 有了這個結(jié)果基本可以斷定兩個點(diǎn)可以唯一的區(qū)分一個圖案,我隨意的取了中心點(diǎn)上方的10個像素的點(diǎn)作為第二個點(diǎn),經(jīng)過上述鉤子程序的測試該點(diǎn)可以區(qū)分該5個點(diǎn)。為了盡量的加快程序速度,我并不是簡單的每次選取所有圖案的兩個點(diǎn),而是當(dāng)必要的時候,也就是碰到中心點(diǎn)不能區(qū)分的時候再次去讀取第二個點(diǎn)的像素值。為此,我使用了一個CellColor類唯一代表一個圖案,提供了一點(diǎn)基本的操作:
??????? 下面的函數(shù)用來從QQ連連看窗口中獲取一個圖案的CellColor:
??????? 到目前為止,最需要的東西我們已經(jīng)得到。已經(jīng)足夠?qū)懗鲆粋€最基本功能的連連看外掛。但是在完成最基本功能的同時我又突發(fā)奇想希望能完成這么一個功能:我的外掛可以根據(jù)其他對手的速率動態(tài)的調(diào)整自己的速度。有了這個想法,我需要獲得更多的界面信息,當(dāng)然主要是其他玩家分?jǐn)?shù)(剩余方格數(shù)量),但是這可不是一個簡單的活,雖然游戲窗口上明明白白寫著一個100,但是我怎么才能獲得這個數(shù)值呢?首先,我還是通過系統(tǒng)鉤子的方法再加上嚴(yán)格的測試得到了每個玩家窗口中的包含分?jǐn)?shù)的小矩形,通過截屏的方法我獲得了玩家分?jǐn)?shù)中從0到9的所有數(shù)值的特征點(diǎn),放大后如下所示:
???????
我所需要做的就是找到那么幾個點(diǎn)唯一的確定這些數(shù)字,理論上可能4,5個就可以做到,然后一個人找啊找,結(jié)果發(fā)現(xiàn)這還真不是一件容易的活,反正vs在手,這還不是小菜一碟...
??????? 寫了程序才知道至少需要六個點(diǎn)才能區(qū)分這些個數(shù)字,怪不得我找了半年沒找到,還好即使調(diào)轉(zhuǎn)方向。除了這些信息之外,我還獲得了開始按鈕坐標(biāo)等信息(實(shí)現(xiàn)自動開始,保障程序的連續(xù)運(yùn)行)。OK,萬事俱備了,來看看我們的收獲吧:
??????? 到此為止第一步基本完成。
?
2. 連連看算法的實(shí)現(xiàn)
??????? 這個部分分為兩部分,第一部分是遍歷整個數(shù)組找到兩個相同的圖案,第二部分檢查這兩個圖案是否連通。在介紹這部分工作之前需要簡單介紹一下表示每個方塊的數(shù)據(jù)結(jié)構(gòu)及這些數(shù)據(jù)結(jié)構(gòu)的填充:
??????? 不難看出,g_AllCells保存了所有方格信息,而g_CellNum保存了自己的剩余方格數(shù)。接下來就可以遍歷g_AllCells這個數(shù)組找到圖案相同的方塊并檢查是否連通。
第一部分代碼如下:
??????? 第二部分其實(shí)也就一個函數(shù)的實(shí)現(xiàn): CanbeDeleted
??????? 這個函數(shù)包含了兩部分:檢查X-Y-X連通及Y-X-Y連通。當(dāng)然包括X-Y等其他特殊情況。兩部分代碼基本完全一致,不難看懂。
??????? 到目前為止,大部分工作已經(jīng)完成了。接下來我們需要模擬鼠標(biāo)的點(diǎn)擊事件。
3. 鼠標(biāo)事件的模擬
??????? 整個程序有兩個地方需要模擬鼠標(biāo)點(diǎn)擊,第一當(dāng)然是去消掉那些方塊,第二我們用于模擬點(diǎn)擊開始按鈕,這樣我們就可以保證程序連續(xù)運(yùn)行,實(shí)現(xiàn)真正的掛機(jī)。分別采用了如下的方法:
??????? 好了,到此為止程序已經(jīng)可以跑起來了...并且可以實(shí)現(xiàn)秒殺了...但是在我的外掛中另外還實(shí)現(xiàn)了其他一些簡單的功能。從下面的截圖中我們可以看出來程序的其他一些功能。
???????
??????? 我們可以看到程序可以有手動和自動兩種方式運(yùn)行。我們可以在程序運(yùn)行的時候動態(tài)地拖動滾動條來更改程序運(yùn)行速度,當(dāng)然我們需要采用多線程編寫。手動調(diào)整速度的實(shí)現(xiàn)比較簡單,我們只需根據(jù)滾動條的位置計算出一個較為合理的等待時間,然后調(diào)用sleep函數(shù)就可以了。自動方式較為復(fù)雜,我需要根據(jù)其他玩家的速度動態(tài)調(diào)整我的速度,雖然功能是實(shí)現(xiàn)了,基本可以保證贏得看不出來,但是還是有很多地方需要改進(jìn)。
??????? 另外需要說明的是,雖然這個外掛是基于無道具版本寫的,但是具有一定的處理道具的能力。我的實(shí)現(xiàn)方式如下:每次找到兩個可以消掉的方塊后先進(jìn)行鼠標(biāo)模擬點(diǎn)擊,然后從界面上獲得自己的剩余方格數(shù)量與程序內(nèi)部的方格數(shù)量g_CellNum進(jìn)行比較,如果發(fā)現(xiàn)兩個不符則說明遇到障礙、禁手、或者鏡子等道具,等待一定時間后重新獲取界面各種信息繼續(xù)運(yùn)行,這樣在一定程度上保證了程序的持續(xù)運(yùn)行性。但是改版本暫時不能處理重列功能,當(dāng)遇到無解的時候需要手動重列。雖然要實(shí)現(xiàn)這個功能不難,但是考慮到該版本是使用了模擬鼠標(biāo)的方法實(shí)現(xiàn)的,很難做到完美,就在下一個版本中增加這個功能了。
??????? 另外再開發(fā)的時候還遇到了一個難點(diǎn),就是如何判斷輸贏。每次消掉兩個后程序會等待一個時間然后再繼續(xù)消掉下兩個,但是在這段時間中對手可能已經(jīng)贏了,游戲結(jié)束,但是我的程序確還在"消掉"。這顯然不是我們期望的,因?yàn)樵谡麄€程序中,我沒有使用sleep函數(shù)去等待。而是在每次等待的時間內(nèi)不斷的去查看其它玩家的剩余方塊數(shù),如果檢測到零則說明游戲結(jié)束,其他玩家已經(jīng)勝利。如下函數(shù)幫我實(shí)現(xiàn)了這個目的:
??????? 通過這種方式,我可以基本地判斷出游戲的勝負(fù)。但是還有一種情況暫時無法處理,就是當(dāng)遇到其他玩家也使用外掛并且都是用秒殺的時候,這時勝負(fù)很難判斷。程序會經(jīng)常判斷錯誤。在以后的版本中會進(jìn)行改進(jìn)。
遇到的問題:
1. 在HOOK中使用MessageBox似乎有問題,當(dāng)用鼠標(biāo)右擊的時候有偶然性。不是每次都能彈出。網(wǎng)上查了一下好像也說在HOOK中不易使用MessageBox。具體原因有待研究...
2. 在多線程中使用InstallHook好像不能正常使用HOOK,沒找到什么原因,因?yàn)樵谶@個外掛中使用到了多線程來保證界面的可交互性,當(dāng)我在開始按鈕點(diǎn)擊的相應(yīng)函數(shù)中調(diào)用InstallHook可以正常使用,但是在AfxBeginThread函數(shù)啟動的新線程中調(diào)用InstallHook好像不能正常使用HOOK。
3. 開始我的程序全部使用了CWindowDC作為獲取像素值的DC,后來改為用::GetPixel(g_GameDC,...),但是發(fā)現(xiàn)用這兩種方法獲取的同一個點(diǎn)的像素值不同,不知道是不是正常現(xiàn)象。
4. 在模擬鼠標(biāo)點(diǎn)擊開始按鈕的時候我開始也使用了::SendMessage()函數(shù)去給游戲窗口發(fā)送消息,但是沒有成功。后來只能選擇用mouse_event來實(shí)現(xiàn)這個功能。但是在這個程序中mouse_event函數(shù)比起::SendMessage()函數(shù)有不足之處。我們需要保持窗口處于最頂層然后進(jìn)行點(diǎn)擊,造成了很多不便。不知道是何原因,可能還需要深入了解外掛知識。
希望在今后的學(xué)習(xí)中能找到這些問題的原因及解決方法。
程序存在的問題:
目前來說程序還存在很多問題:
1. 沒有強(qiáng)大的道具處理能力。在出現(xiàn)道具的情況下程序有時會失靈(我的錯...有bug沒解掉T_T)。
2. 在運(yùn)行時需要將游戲窗口置于在前端,要不然也會有問題。因?yàn)橐@取顏色、用mouse_event等都需要將游戲窗口置前。
3. 在遇到更強(qiáng)大的外掛的時候秒殺拼不過人家...郁悶...這個估計跟外掛的類型有關(guān)了...等待下一個版本的完成(通過偽造數(shù)據(jù)包的方法應(yīng)該會更快更強(qiáng)大)。
4. 本來以為能解決前面三個問題程序就比較完美了,沒想到在寫這篇文章的時候花生米找我玩連連看,牛人啊,開口就讓我調(diào)半秒。一玩果然不虧zju連連看老大啊,速度相當(dāng)快。他提出了很多建設(shè)性意見,可以更好的偽裝。原來大牛們看外掛有自己的一套啊。趕緊記下來,在以后的版本中改進(jìn)改進(jìn):1.高手都用重列和指南針。本來以為用指南針會影響高手速度,原來不是的,高手都是重列完馬上指南針然后可以連擊下去。見識了見識了。2. 很多外掛不符合人眼規(guī)則,就是不消近的消遠(yuǎn)的。一直以為高手外連連看都狂點(diǎn)狂點(diǎn),想不到還有心思研究這個。牛啊。另外他還跟我說了一個秘密哈哈,全中國的連連看高手都在無道具場3和10。果然是高手,唉,真的見識了。下次再寫一個厲害一點(diǎn)的讓他去鑒定哈哈。
5. 今天在測試的時候又遇到了一個新的問題...在vista下不能用...唉...問題多多,期待下一個版本的完成吧...
在整個程序中也遇到了一些問題,至今還未解決,暫且一一列出:
總結(jié)
- 上一篇: 超好用的卸载软件 —— Geek
- 下一篇: go语言读取xls表格xls文件操作替代