自動掃雷程式
很多人喜歡玩Windows的掃雷程式,去年11月份寫了這個小程式,那時還在Infosys。
以下是去年在我的MSN Sapce上寫的:
5。自動掃雷過程,顯然就是對所有的非雷按鈕進行一遍訊息傳送即可。
6。效果圖:
注意:Windows的掃雷程式似乎是保證第一個按下的按鈕下面不是雷,如果是雷,它會自動重新排雷。所以要使用自動掃雷,保證其正確性,最好不要手動先去翻幾個按鈕。
以下是去年在我的MSN Sapce上寫的:
“這兩天挺無聊的,Bob的掃雷戰績越來越令人驚歎,中級達到26秒,於此情況,我不得不使出了殺手鐗——改登錄檔,將戰績定格為1秒,不過或許這樣顯得太貪心了,所以馬上被識破,於是,鄙視的眼光投了過來,似乎我成了一個“卑鄙齷鹺”,用下三爛的手段獲取勝利的人,一下子一種“窩囊的火氣”湧上心來,我決定要以技取勝,於是,上網查了一點WINDOWS掃雷程式的資料,發現原來還真容易,欣喜,馬上動手寫了個自動掃雷程式,詳情如下:
對於WIN2000,雷區的寬度資料儲存在0x10056f8,高度資料儲存在0x1005a68,雷的數目儲存在0x1005a6c,雷的佈局資料起始地址為0x1005700;
對於WINXP,分別是0x1005334、0x1005338、0x1005330、0x1005340。
如果某個按鈕下是雷,那麼這個記憶體資料對應的數值必然為0x8F,如此,離開勝利不遠了,然後用VS的SPY程式獲取到了掃雷介面第一個按鈕的座標為:(11, 54),並且獲取到了滑鼠訊息的引數lParam和wParam,OK,根據這些資料,就可以還原出暴露的雷區佈局,再將座標做一下簡單的數學轉換,那麼按下這個程式的某個按鈕,將滑鼠訊息同時發給WINDOWS掃雷程式就可以了,如此,相應的掃雷程式的那個按鈕也被按下,再加個自動進行所有非雷按鈕的MOUSE_UP事件進行一遍,不就實現了自動掃雷了嗎?為了降低速度,再加個速度調節,根據指定速度對主執行緒進行休眠,哈哈,搞定!”
起初這個軟體我是用C#寫的,後來發現在.NET中傳送大量的訊息到某個視窗時,.顯得很慢,於是用Delphi重寫了一遍,結果速度非常快。
1。首先取得作業系統的版本,以便獲知究竟從什麼記憶體地址讀雷區資料:
2。使用ReadProcessMemory(pid, Pointer(nWidthAddress), @nWidth, 4, dwNumOfBytesRead)讀取寬度資料;ReadProcessMemory(pid, Pointer(nHeightAddress), @nHeight, 4, dwNumOfBytesRead)讀取高度資料。
3。生成掃雷介面,如果按鈕下是雷,則其記憶體資料必然是0x8F:
4。對某個按鈕傳送MouseUP訊息的過程:
首先很容易查到Windows的滑鼠按鈕訊息程式碼為:
const WM_LBUTTONDOWN = $0201;
const WM_LBUTTONUP = $0202;
const WM_RBUTTONDOWN = $0204;
const WM_RBUTTONUP = $0205;
起初這個軟體我是用C#寫的,後來發現在.NET中傳送大量的訊息到某個視窗時,.顯得很慢,於是用Delphi重寫了一遍,結果速度非常快。
1。首先取得作業系統的版本,以便獲知究竟從什麼記憶體地址讀雷區資料:
procedure TfrmMain.FormCreate(Sender: TObject);
var
ver:Cardinal;
majorVer: Cardinal;
minorVer: Cardinal;
begin
ver := GetVersion();
majorVer := LOByte(ver);
minorVer := HIByte(ver);
if majorVer >= 5 then
begin
if minorVer = 0 then //Win2000
begin
nWidthAddress := $10056F8;
nHeightAddress := $1005A68;
nMinesAddress := $1005A6C;
nCellBaseAddress := $1005700;
end
else //WinXP
begin
nWidthAddress := $1005334;
nHeightAddress := $1005338;
nMinesAddress := $1005330;
nCellBaseAddress := $1005340;
end;
end
else
begin
MessageDlg('This program support only Win2000 and WinXP!', mtInformation, [mbOK], 0);
Application.Terminate;
end;
//edtSeconds.Text := IntToStr(self.traSeconds.Position);
end;
var
ver:Cardinal;
majorVer: Cardinal;
minorVer: Cardinal;
begin
ver := GetVersion();
majorVer := LOByte(ver);
minorVer := HIByte(ver);
if majorVer >= 5 then
begin
if minorVer = 0 then //Win2000
begin
nWidthAddress := $10056F8;
nHeightAddress := $1005A68;
nMinesAddress := $1005A6C;
nCellBaseAddress := $1005700;
end
else //WinXP
begin
nWidthAddress := $1005334;
nHeightAddress := $1005338;
nMinesAddress := $1005330;
nCellBaseAddress := $1005340;
end;
end
else
begin
MessageDlg('This program support only Win2000 and WinXP!', mtInformation, [mbOK], 0);
Application.Terminate;
end;
//edtSeconds.Text := IntToStr(self.traSeconds.Position);
end;
2。使用ReadProcessMemory(pid, Pointer(nWidthAddress), @nWidth, 4, dwNumOfBytesRead)讀取寬度資料;ReadProcessMemory(pid, Pointer(nHeightAddress), @nHeight, 4, dwNumOfBytesRead)讀取高度資料。
3。生成掃雷介面,如果按鈕下是雷,則其記憶體資料必然是0x8F:
for y:= 0 to nHeight - 1 do
begin
for x := 0 to nWidth - 1 do
begin
MineButtons[x, y] := TSpeedButton.Create(self);
MineButtons[x, y].Parent := self.pnlMines;
MineButtons[x, y].Width := 16;
MineButtons[x, y].Height := 16;
MineButtons[x, y].Left := x*16;
MineButtons[x, y].Top := y*16;
MineButtons[x, y].Name :='btn_' + IntToStr(x) + '_' + IntToStr(y);
MineButtons[x, y].Caption := '';
MineButtons[x, y].OnMouseUp := self.SweepMouseUp;
nCellAddress := (nCellBaseAddress) + (32 * (y+1)) + (x+1);
ReadProcessMemory(pid, Pointer(nCellAddress), @nIsMine, 1, dwNumOfBytesRead);
if nIsMine = $8f then
begin
MineButtons[x, y].Glyph := imgmine.Picture.Bitmap;
MineButtons[x, y].Tag := BUTTON_MINE;
end;
gauge.Progress := gauge.Progress + 1;
Application.ProcessMessages;
end; // for
end; // for
begin
for x := 0 to nWidth - 1 do
begin
MineButtons[x, y] := TSpeedButton.Create(self);
MineButtons[x, y].Parent := self.pnlMines;
MineButtons[x, y].Width := 16;
MineButtons[x, y].Height := 16;
MineButtons[x, y].Left := x*16;
MineButtons[x, y].Top := y*16;
MineButtons[x, y].Name :='btn_' + IntToStr(x) + '_' + IntToStr(y);
MineButtons[x, y].Caption := '';
MineButtons[x, y].OnMouseUp := self.SweepMouseUp;
nCellAddress := (nCellBaseAddress) + (32 * (y+1)) + (x+1);
ReadProcessMemory(pid, Pointer(nCellAddress), @nIsMine, 1, dwNumOfBytesRead);
if nIsMine = $8f then
begin
MineButtons[x, y].Glyph := imgmine.Picture.Bitmap;
MineButtons[x, y].Tag := BUTTON_MINE;
end;
gauge.Progress := gauge.Progress + 1;
Application.ProcessMessages;
end; // for
end; // for
4。對某個按鈕傳送MouseUP訊息的過程:
首先很容易查到Windows的滑鼠按鈕訊息程式碼為:
const WM_LBUTTONDOWN = $0201;
const WM_LBUTTONUP = $0202;
const WM_RBUTTONDOWN = $0204;
const WM_RBUTTONUP = $0205;
procedure TfrmMain.SweepMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
bbtn: TSpeedButton;
xpos: Cardinal;
ypos: Cardinal;
pos: cardinal;
begin
bbtn := (Sender as TSpeedButton);
//The coordinator are (x,y) -> y<<16 | x}
xpos := bbtn.Left + 11 + 8; //make it click on center of the button
ypos := bbtn.Top + 54 + 8;
pos:= (ypos shl 16) or xpos;
If Button = mbLeft then
Begin
bbtn.Caption:='#';
if handleMine <> 0 then
begin
SendMessage(handleMine, WM_LBUTTONDOWN, $0001, pos);
SendMessage(handleMine, WM_LBUTTONUP, $0001, pos);
end;
End
Else if Button = mbRight then
Begin
if handleMine <> 0 then
begin
if bbtn.Tag = BUTTON_NONE then
begin
bbtn.Glyph := imgFlag.Picture.Bitmap;
bbtn.Tag := BUTTON_FLAG;
end
else if bbtn.Tag = BUTTON_FLAG then
begin
bbtn.Glyph := imgQuestion.Picture.Bitmap;
bbtn.Tag := BUTTON_QUESTION;
end
else if bbtn.Tag = BUTTON_QUESTION then
begin
bbtn.Glyph := nil;
bbtn.Tag := BUTTON_NONE;
end;
SendMessage(handleMine, WM_RBUTTONDOWN, $0002, pos);
SendMessage(handleMine, WM_RBUTTONUP, $0000, pos);
end;
End;
end;
var
bbtn: TSpeedButton;
xpos: Cardinal;
ypos: Cardinal;
pos: cardinal;
begin
bbtn := (Sender as TSpeedButton);
//The coordinator are (x,y) -> y<<16 | x}
xpos := bbtn.Left + 11 + 8; //make it click on center of the button
ypos := bbtn.Top + 54 + 8;
pos:= (ypos shl 16) or xpos;
If Button = mbLeft then
Begin
bbtn.Caption:='#';
if handleMine <> 0 then
begin
SendMessage(handleMine, WM_LBUTTONDOWN, $0001, pos);
SendMessage(handleMine, WM_LBUTTONUP, $0001, pos);
end;
End
Else if Button = mbRight then
Begin
if handleMine <> 0 then
begin
if bbtn.Tag = BUTTON_NONE then
begin
bbtn.Glyph := imgFlag.Picture.Bitmap;
bbtn.Tag := BUTTON_FLAG;
end
else if bbtn.Tag = BUTTON_FLAG then
begin
bbtn.Glyph := imgQuestion.Picture.Bitmap;
bbtn.Tag := BUTTON_QUESTION;
end
else if bbtn.Tag = BUTTON_QUESTION then
begin
bbtn.Glyph := nil;
bbtn.Tag := BUTTON_NONE;
end;
SendMessage(handleMine, WM_RBUTTONDOWN, $0002, pos);
SendMessage(handleMine, WM_RBUTTONUP, $0000, pos);
end;
End;
end;
5。自動掃雷過程,顯然就是對所有的非雷按鈕進行一遍訊息傳送即可。
6。效果圖:
注意:Windows的掃雷程式似乎是保證第一個按下的按鈕下面不是雷,如果是雷,它會自動重新排雷。所以要使用自動掃雷,保證其正確性,最好不要手動先去翻幾個按鈕。
相關文章
- python寫的自動掃雷Python
- 厲害了,一個自動掃雷遊戲專案!遊戲
- 利用Python實現自動掃雷小指令碼Python指令碼
- java掃雷遊戲程式碼Java遊戲
- 掃雷程式思想講解 (轉)
- JS實現掃雷JS
- win10沒有掃雷遊戲怎麼辦_win10自帶遊戲沒有掃雷如何解決Win10遊戲
- python之掃雷小遊戲(附程式碼)Python遊戲
- 《魔窟掃雷》給掃雷遊戲指明瞭一個進化的方向遊戲
- 用ncurses庫寫掃雷
- win10有掃雷嗎?Win10系統掃雷遊戲在哪裡Win10遊戲
- 生成一個掃雷矩陣矩陣
- 掃雷小遊戲-網頁版遊戲網頁
- 經典掃雷遊戲Web版遊戲Web
- 掃雷--C語言實現C語言
- 掃雷遊戲作弊逆向菜文遊戲
- go語言實現掃雷Go
- win10如何安裝掃雷遊戲_win10系統怎麼玩掃雷Win10遊戲
- Java Swing掃雷遊戲demo分享Java遊戲
- Spring 自動掃描元件Spring元件
- win10掃雷怎麼換主題 如何更換win10的掃雷主題Win10
- 安全測試之探索 windows 遊戲掃雷Windows遊戲
- Qt學習- (掃雷專案初學)QT
- CSS3雷達掃描效果CSSS3
- 探秘掃雷遊戲的C語言實現遊戲C語言
- Android自定義View 雷達掃描效果AndroidView
- 軟體開發其實就像工兵掃雷
- 專業掃雷v1.2版破解分析
- Linux下的6個掃雷遊戲的翻版Linux遊戲
- 雷達氣象相關詞彙(一 掃描模式)模式
- Mybatis 通過掃描 自動生成別名MyBatis
- 對上次的自動掃描進行改造
- 自動化系統S模式雷達應用筆記模式筆記
- win10怎麼關閉defender自動掃描_win10關閉defender自動掃描的步驟Win10
- 通過編寫掃雷遊戲提高你的 Bash 技巧遊戲
- Python3+pygame實現Windows經典掃雷PythonGAMWindows
- vb.net使用GDI+實現掃雷小遊戲遊戲
- [JAVAFX基礎]掃雷經典入門低配版Java