年前無心看到一個用Python寫的小桌面程序,能夠自動玩掃雷的遊戲,以爲挺有意思,決定用C#也作一個。【真實狀況是:我知道Python最近比較火,很是適合搞爬蟲、大數據、機器學習之類的,但如今連桌面程序都用Python作了嗎?還給不給.NET程序員活路了?簡直不能忍!】git
春節期間正好有閒就搞了一下,先下載了一個第三方的掃雷遊戲,實現功能之後以爲下載的這個掃雷遊戲分辨率過低了,也很差看,因此又本身作了一個掃雷遊戲,湊成一套。程序員
源碼下載地址:https://github.com/seabluescn/AutoMineSweepergithub
須要提早說明的是,這兩個程序是獨立的,之間沒有任何接口與聯繫,自動掃雷的程序經過讀取屏幕信息獲取遊戲狀態,並模擬鼠標操做來進行遊戲。下面就幾個相關技術點和你們分享一下。算法
一、獲取應用程序窗口數組
[DllImport("user32.dll")] private static extern int GetWindowRect(IntPtr hwnd, out Rect lpRect); private Rect GetWindowRect() { Process[] processes = Process.GetProcesses(); Process process = null; for (int i = 0; i < processes.Length - 1; i++) { process = processes[i]; if (process.MainWindowTitle == "MineSweeper") { break; } } Rect rect = new Rect(); GetWindowRect(process.MainWindowHandle, out rect); return rect; }
二、屏幕截圖機器學習
Rect rect = GetWindowRect(); int left = rect.Left; int top = rect.Top; int centerleft = 21; //偏移 int centertop = 93; int centerwidth = 300; int centerheight = 300; Bitmap bitmapCenter = new Bitmap(centerwidth, centerheight); using (Graphics graphics = Graphics.FromImage(bitmapCenter)) { graphics.CopyFromScreen(left + centerleft, top + centertop, 0, 0, new Size(centerwidth, centerheight)); this.pictureBox1.Image?.Dispose(); this.pictureBox1.Image = bitmapCenter; }
截圖後,根據圖片上固定位置的顏色信息判斷該位置的狀態,最終造成一個數組。學習
三、模擬鼠標點擊測試
[DllImport("user32")] private static extern int mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo); const int MOUSEEVENTF_MOVE = 0x0001; //移動鼠標 const int MOUSEEVENTF_LEFTDOWN = 0x0002; //模擬鼠標左鍵按下 const int MOUSEEVENTF_LEFTUP = 0x0004; //模擬鼠標左鍵擡起 const int MOUSEEVENTF_RIGHTDOWN = 0x0008; //模擬鼠標右鍵按下 const int MOUSEEVENTF_RIGHTUP = 0x0010; //模擬鼠標右鍵擡起 const int MOUSEEVENTF_MIDDLEDOWN = 0x0020; //模擬鼠標中鍵按下 const int MOUSEEVENTF_MIDDLEUP = 0x0040; //模擬鼠標中鍵擡起 const int MOUSEEVENTF_ABSOLUTE = 0x8000; //標示是否採用絕對座標 int clickPointX = X * 65535 / Screen.PrimaryScreen.Bounds.Width; int clickPointY = Y * 65535 / Screen.PrimaryScreen.Bounds.Height; //移動鼠標 mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, clickPointX, clickPointY, 0, 0); //左鍵點擊 mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); //右鍵點擊 mouse_event(MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
四、遊戲算法大數據
得到遊戲狀態後,須要判斷下一步操做,是點開某個位置仍是右鍵標記某個位置,算法循環遍歷全部方塊,一共三步:this
1)基礎算法
基礎算法1:對於已經翻開的塊,中心數字和周圍已經標記的雷數一致,其周圍全部未知位置都不是雷,左鍵點開
基礎算法2:對於已經翻開的塊,中心數字=未知位置數量+周圍已經標記的雷數 :其周圍全部未知位置均爲雷,右鍵標記
2)高一級算法
先計算全部已翻開的塊,其周圍未知塊含雷的數量之和。
算法1:對於已經翻開的塊,若是周圍未知塊超過2個,其中有一個未知塊:中心數字-雷==其餘位置塊組合雷數總和:該未知塊必不是雷
算法2:對於已經翻開的塊,若是周圍未知塊超過2個,其中有一個未知塊:數字-雷-其餘位置塊組合雷數=1:該未知塊必是雷
3)實在沒有找到合適的點,只能隨機點開
對全部未知的點,計算一下週圍雷的機率,選擇機率最小的點開。
經測試,程序對目標狀態的識別率爲100%,智能程度還不錯,比通常人玩的好,無聊時能夠看它玩一天。