private void Recognize() { //常量 int MaxX = 20; int MaxY = 12; int RectWidth = 30; //获取窗口位置 Rect rect = GetWindowRect(); int left = rect.Left; int top = rect.Top; //获取游戏状态(笑脸) GameState gameState = GetGameState(); //非游戏状态 if (gameState != GameState.Ready) { ShowDebugInfo("\r\nGame over!"); this.timer.Enabled = false; return; } //截取游戏主要区域 int width = rect.Right - rect.Left; int height = rect.Bottom - rect.Top; int centerleft = 21; int centertop = 93; int centerwidth = MaxX * RectWidth; int centerheight = MaxY * RectWidth; 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; } //识别 MineState[,] MineMap = new MineState[MaxX, MaxY]; for (int x = 0; x < MaxX; x++) { for (int y = 0; y < MaxY; y++) { Color center = bitmapCenter.GetPixel(x * RectWidth + RectWidth / 2, y * RectWidth + RectWidth / 2); if (center.R == 220 && center.G == 220 && center.B == 220) { MineMap[x, y] = MineState.Unknow; } else if (center.R == 233 && center.G == 233 && center.B == 233) { MineMap[x, y] = MineState.None; } else if (center.R == 90 && center.G == 219 && center.B == 117) { MineMap[x, y] = MineState.One; } else if (center.R == 8 && center.G == 126 && center.B == 33) { MineMap[x, y] = MineState.Two; } else if (center.R == 36 && center.G == 70 && center.B == 243) { MineMap[x, y] = MineState.Three; } else if (center.R == 27 && center.G == 48 && center.B == 155) { MineMap[x, y] = MineState.Four; } else if (center.R == 178 && center.G == 82 && center.B == 209) { MineMap[x, y] = MineState.Five; } else if (center.R == 228 && center.G == 141 && center.B == 28) { MineMap[x, y] = MineState.Six; } else if (center.R == 192 && center.G == 30 && center.B == 227) { MineMap[x, y] = MineState.Seven; } else if (center.R == 218 && center.G == 8 && center.B == 186) { MineMap[x, y] = MineState.Eight; } else if (center.R == 244 && center.G == 35 && center.B == 50) { MineMap[x, y] = MineState.Mine; } else { ShowDebugInfo($"\r\nRecognize Error!({x},{y}):{center.R},{center.G},{center.B}"); this.timer.Enabled = false; return; } } } //绘制识别结果 Bitmap bitmapDebug = new Bitmap(centerwidth, centerheight); using (Graphics graphics = Graphics.FromImage(bitmapDebug)) { string s = ""; for (int x = 0; x < MaxX; x++) { for (int y = 0; y < MaxY; y++) { switch (MineMap[x, y]) { case MineState.Unknow: s = "?"; break; case MineState.None: s = "0"; break; case MineState.One: s = "1"; break; case MineState.Two: s = "2"; break; case MineState.Three: s = "3"; break; case MineState.Four: s = "4"; break; case MineState.Five: s = "5"; break; case MineState.Six: s = "6"; break; case MineState.Seven: s = "7"; break; case MineState.Eight: s = "8"; break; case MineState.Mine: s = "9"; break; default: s = "X"; break; } graphics.DrawString(s, new Font("宋体", 12), Brushes.Black, x * RectWidth, y * RectWidth); } } this.pictureBox2.Image?.Dispose(); this.pictureBox2.Image = bitmapDebug; } //下面开始计算应该点击的点 List <ClickEvent> clickEventList = new List <ClickEvent>(); bool FindGoodPoint = false; //如果找到合适的点,就完成本次运算 //第一步:基础算法...计算点击位置 Debug.WriteLine("1基础算法..."); for (int x = 0; x < MaxX; x++) { for (int y = 0; y < MaxY; y++) { int MineCount = (int)MineMap[x, y]; if (MineCount >= 1) { List <BoxLocation> unknowBoxs = SearchMines(x, y, MaxX, MaxY, MineState.Unknow, MineMap); //附近未开盒子 List <BoxLocation> MineBoxs = SearchMines(x, y, MaxX, MaxY, MineState.Mine, MineMap); //附件已确定的雷 if (unknowBoxs.Count > 0) { //主要算法1:数字和周围已经标记的雷数一致,所有未知位置都不是雷,左键点开 if (MineBoxs.Count == MineCount) { clickEventList.Clear(); foreach (var box in unknowBoxs) { clickEventList.Add(new ClickEvent(box.LocationX, box.LocationY, ClickType.LeftClick)); } FindGoodPoint = true; break; } //主要算法2:中心数字=未知位置数量+周围已经标记的雷数 :所有未知位置为雷,右键标记 if (MineBoxs.Count + unknowBoxs.Count == MineCount) { clickEventList.Clear(); foreach (var box in unknowBoxs) { clickEventList.Add(new ClickEvent(box.LocationX, box.LocationY, ClickType.RightClick)); } FindGoodPoint = true; break; } } } } if (FindGoodPoint) { break; } } //第二步:补充算法.....第一次没有计算出合适的点,用复杂算法再算一次 if (!FindGoodPoint) { Debug.WriteLine("2补充算法...."); //计算 List <UnknowBoxSum> UnknowBoxSumList = new List <UnknowBoxSum>(); for (int locx = 0; locx < MaxX; locx++) { for (int locy = 0; locy < MaxY; locy++) { int MineCount = (int)MineMap[locx, locy]; if (MineCount >= 1 && MineCount <= 6) { List <BoxLocation> unknowBoxs = SearchMines(locx, locy, MaxX, MaxY, MineState.Unknow, MineMap); //附近未开盒子 List <BoxLocation> MineBoxs = SearchMines(locx, locy, MaxX, MaxY, MineState.Mine, MineMap); //附件已确定的雷 if (unknowBoxs.Count >= 2) { UnknowBoxSum unknowBoxSum = new UnknowBoxSum(); unknowBoxSum.Boxes = unknowBoxs; unknowBoxSum.Sum = MineCount - MineBoxs.Count; UnknowBoxSumList.Add(unknowBoxSum); } } } } Debug.WriteLine($"UnknowBoxSumList={UnknowBoxSumList.Count}"); if (UnknowBoxSumList.Count > 0) { //匹配 for (int locx = 0; locx < MaxX; locx++) { for (int locy = 0; locy < MaxY; locy++) { int MineCount = (int)MineMap[locx, locy]; if (MineCount >= 1 && MineCount <= 8) { List <BoxLocation> unknowBoxs = SearchMines(locx, locy, MaxX, MaxY, MineState.Unknow, MineMap); //附近未开盒子 List <BoxLocation> MineBoxs = SearchMines(locx, locy, MaxX, MaxY, MineState.Mine, MineMap); //附件已确定的雷 if (unknowBoxs.Count >= 2) { foreach (var UnknowBoxSum in UnknowBoxSumList) { if (unknowBoxs.Count - UnknowBoxSum.Boxes.Count == 1) { if (UnknowBoxSum.MatchBox(unknowBoxs)) //先判断是否匹配 { //数字-雷==Sum:必不是雷 if ((MineCount - MineBoxs.Count - UnknowBoxSum.Sum) == 0) { //取出 BoxLocation box = UnknowBoxSum.GetNotBelongBox(unknowBoxs); Debug.WriteLine($"Match(必不是雷):({locx},{locy})->({box.LocationX},{box.LocationY})"); clickEventList.Add(new ClickEvent(box.LocationX, box.LocationY, ClickType.LeftClick)); FindGoodPoint = true; break; } //数字-减雷-Sum=1:必是雷 if ((MineCount - MineBoxs.Count - UnknowBoxSum.Sum) == 1) { //取出 BoxLocation box = UnknowBoxSum.GetNotBelongBox(unknowBoxs); Debug.WriteLine($"Match(必是雷):({locx},{locy})->({box.LocationX},{box.LocationY})"); clickEventList.Add(new ClickEvent(box.LocationX, box.LocationY, ClickType.RightClick)); FindGoodPoint = true; break; } } } } } } if (FindGoodPoint) { break; } } if (FindGoodPoint) { break; } } } } //第三步:实在没有找到合适的点,只能随机点开 if (!FindGoodPoint) { Debug.WriteLine("3随机点开..."); float[,] ProbabilityMap = new float[MaxX, MaxY]; //计算最小概率 float MinProbability = 1; for (int x = 0; x < MaxX; x++) { for (int y = 0; y < MaxY; y++) { if (MineMap[x, y] == MineState.Unknow) { ProbabilityMap[x, y] = CalcProbability(x, y, MaxX, MaxY, MineMap); if (ProbabilityMap[x, y] < MinProbability) { MinProbability = ProbabilityMap[x, y]; } } } } Debug.WriteLine($"MinProbability={MinProbability}"); //取出最小概率的点 for (int x = 0; x < MaxX; x++) { for (int y = 0; y < MaxY; y++) { if (MineMap[x, y] == MineState.Unknow && Math.Abs(ProbabilityMap[x, y] - MinProbability) < 0.001) { clickEventList.Add(new ClickEvent(x, y, ClickType.LeftClick)); } } } /* * foreach (var clickEvent in clickEventList) * { * Debug.WriteLine($"selected clickEvent:{clickEvent}"); * } */ int Count = clickEventList.Count; ShowDebugInfo($"\r\nRandom Select:Count={Count}"); if (Count == 0) { ShowDebugInfo("\r\n clickEventList.Count == 0,I can't do anything!"); this.timer.Enabled = false; return; } else { if (Count == 1) { ClickEvent clickEvent = clickEventList[0]; } else { Random random = new Random(); ClickEvent clickEvent = clickEventList[random.Next(Count)]; clickEventList.Clear(); clickEventList.Add(clickEvent); } } } //点击屏幕 ClickScreen(RectWidth, left, top, centerleft, centertop, clickEventList); }
private void Recognize() { //Không đổi //Nhận trạng thái trò chơi GameState gameState = GetGameState(); //Trạng thái không phải trò chơi if (gameState != GameState.Ready) { ShowDebugInfo("\r\nGame over!"); if (chkAutoRestart.Checked) { StartGame(); } else { this.timer.Enabled = false; return; } } //Xác định ví trí của trò chơi //Chiều ngang max ô là : int MaxX = 30; //Chiều dọc max ô là : int MaxY = 16; //chu vi : int RectWidth = 16; // Tọa độ ô đầu tiên bên trái int left = 12; // Tọa độ ô đầu tiên bên trên int top = 55; // chiều ngang bao nhiêu ô( tính pixel ) int width = 16; // chiều dọc có bao nhiêu ô ( tính pixel ) int height = 16; // vị trí trung tâm ô đầu tiên int centerleft = 20; int centertop = 63; // bỏ ảnh vào ô this.pictureBox1.Image?.Dispose(); dm.FreePic("info.bmp"); dm.DeleteFile("info.bmp"); dm.Capture(14, 56, 495, 313, "info.bmp"); this.pictureBox1.Image = Image.FromFile("info.bmp"); // //Xác định ma trận MineState[,] MineMap = new MineState[MaxX, MaxY]; for (int x = 0; x < MaxX; x++) { for (int y = 0; y < MaxY; y++) { // unknow là chưa khám phá , do trung tâm trùng màu trắng với ô None ( ô không có gì ) nên để lệch pixel if (dm.CmpColor(12 + x * width, 63 + y * height, "ffffffff", 1.0) == 0) { MineMap[x, y] = MineState.Unknow; } if (dm.CmpColor(20 + x * width, 63 + y * height, "0000ff", 1.0) == 0) { MineMap[x, y] = MineState.One; } if (dm.CmpColor(20 + x * width, 63 + y * height, "008000", 1.0) == 0) { MineMap[x, y] = MineState.Two; } if (dm.CmpColor(20 + x * width, 63 + y * height, "ff0000", 1.0) == 0) { MineMap[x, y] = MineState.Three; } if (dm.CmpColor(20 + x * width, 63 + y * height, "000080", 1.0) == 0) { MineMap[x, y] = MineState.Four; } if (dm.CmpColor(20 + x * width, 63 + y * height, "800000", 1.0) == 0) { MineMap[x, y] = MineState.Five; } if (dm.CmpColor(20 + x * width, 63 + y * height, "008080", 1.0) == 0) { MineMap[x, y] = MineState.Six; } // chưa rảnh làm , chia 2 thằng này do nó trùng với mine nên gây lỗi // if (dm.CmpColor(22 + x * width, 63 + y * height, "000000" , 1.0) == 0) { MineMap[x, y] = MineState.Seven; } // if (dm.CmpColor(20 + x * width, 63 + y * height, "808080", 1.0) == 0) { MineMap[x, y] = MineState.Eight; } if (dm.CmpColor(20 + x * width, 63 + y * height, "000000", 1.0) == 0) { MineMap[x, y] = MineState.Mine; } //tương tự unknow tìm pixel trong ô cho nó có đặc trưng riêng if (dm.CmpColor(12 + x * width, 63 + y * height, "c0c0c0", 1.0) == 0) { MineMap[x, y] = MineState.None; } } } //Vẽ vào ô - thấy thừa quá nên bỏ //Bitmap bitmapDebug = new Bitmap(255, 185); //using (Graphics graphics = Graphics.FromImage(bitmapDebug)) //{ // string s = ""; // for (int x = 0; x < MaxX; x++) // for (int y = 0; y < MaxY; y++) // { // switch (MineMap[x, y]) // { // case MineState.Unknow: s = "?"; break; // case MineState.None: s = "0"; break; // case MineState.One: s = "1"; break; // case MineState.Two: s = "2"; break; // case MineState.Three: s = "3"; break; // case MineState.Four: s = "4"; break; // case MineState.Five: s = "5"; break; // case MineState.Six: s = "6"; break; // case MineState.Seven: s = "7"; break; // case MineState.Eight: s = "8"; break; // case MineState.Mine: s = "9"; break; // default: s = "X"; break; // } // graphics.DrawString(s, new Font("Arial", 8), Brushes.Black, x * 8, y * 11); // } // this.pictureBox2.Image?.Dispose(); // this.pictureBox2.Image = bitmapDebug; //} List <ClickEvent> clickEventList = new List <ClickEvent>(); bool FindGoodPoint = false; //Nếu tìm thấy một điểm thích hợp, việc tính toán được hoàn thành //Bước 1: Thuật toán cơ bản ... // Debug.WriteLine("1 thuật toán cơ bản ..."); for (int x = 0; x < MaxX; x++) { for (int y = 0; y < MaxY; y++) { int MineCount = (int)MineMap[x, y]; if (MineCount >= 1) { List <BoxLocation> unknowBoxs = SearchMines(x, y, MaxX, MaxY, MineState.Unknow, MineMap); //Chưa mở gần đó List <BoxLocation> MineBoxs = SearchMines(x, y, MaxX, MaxY, MineState.Mine, MineMap); //mỏ xác định if (unknowBoxs.Count > 0) { //Thuật toán chính 1: if (MineBoxs.Count == MineCount) { clickEventList.Clear(); foreach (var box in unknowBoxs) { clickEventList.Add(new ClickEvent(box.LocationX, box.LocationY, ClickType.LeftClick)); } FindGoodPoint = true; break; } //Thuật toán chính 2: if (MineBoxs.Count + unknowBoxs.Count == MineCount) { clickEventList.Clear(); foreach (var box in unknowBoxs) { clickEventList.Add(new ClickEvent(box.LocationX, box.LocationY, ClickType.RightClick)); } FindGoodPoint = true; break; } } } } if (FindGoodPoint) { break; } } //Bước 2: Bổ sung thuật toán ..... Lần đầu tiên không tính được điểm phù hợp, hãy sử dụng thuật toán phức tạp để tính lại. if (!FindGoodPoint) { //Tính toán List <UnknowBoxSum> UnknowBoxSumList = new List <UnknowBoxSum>(); for (int locx = 0; locx < MaxX; locx++) { for (int locy = 0; locy < MaxY; locy++) { int MineCount = (int)MineMap[locx, locy]; if (MineCount >= 1 && MineCount <= 6) { List <BoxLocation> unknowBoxs = SearchMines(locx, locy, MaxX, MaxY, MineState.Unknow, MineMap); //Chưa mở gần đó List <BoxLocation> MineBoxs = SearchMines(locx, locy, MaxX, MaxY, MineState.Mine, MineMap); //Mỏ đã được xác định if (unknowBoxs.Count >= 2) { UnknowBoxSum unknowBoxSum = new UnknowBoxSum(); unknowBoxSum.Boxes = unknowBoxs; unknowBoxSum.Sum = MineCount - MineBoxs.Count; UnknowBoxSumList.Add(unknowBoxSum); } } } } // Debug.WriteLine($"UnknowBoxSumList={UnknowBoxSumList.Count}"); if (UnknowBoxSumList.Count > 0) { //Trận đấu for (int locx = 0; locx < MaxX; locx++) { for (int locy = 0; locy < MaxY; locy++) { int MineCount = (int)MineMap[locx, locy]; if (MineCount >= 1 && MineCount <= 8) { List <BoxLocation> unknowBoxs = SearchMines(locx, locy, MaxX, MaxY, MineState.Unknow, MineMap); //Chưa mở gần đó List <BoxLocation> MineBoxs = SearchMines(locx, locy, MaxX, MaxY, MineState.Mine, MineMap); //Mỏ đã được xác định if (unknowBoxs.Count >= 2) { foreach (var UnknowBoxSum in UnknowBoxSumList) { if (unknowBoxs.Count - UnknowBoxSum.Boxes.Count == 1) { if (UnknowBoxSum.MatchBox(unknowBoxs)) //Đầu tiên xác định xem nó có khớp không { //Số mìn == Tổng: không phải mìn if ((MineCount - MineBoxs.Count - UnknowBoxSum.Sum) == 0) { BoxLocation box = UnknowBoxSum.GetNotBelongBox(unknowBoxs); // Debug.WriteLine($"Match(Không có bơm ):({locx},{locy})->({box.LocationX},{box.LocationY})"); clickEventList.Add(new ClickEvent(box.LocationX, box.LocationY, ClickType.LeftClick)); FindGoodPoint = true; break; } //Số giảm trừ-Sum = 1: if ((MineCount - MineBoxs.Count - UnknowBoxSum.Sum) == 1) { //Đưa ra BoxLocation box = UnknowBoxSum.GetNotBelongBox(unknowBoxs); // Debug.WriteLine($"Match(á bơm ):({locx},{locy})->({box.LocationX},{box.LocationY})"); clickEventList.Add(new ClickEvent(box.LocationX, box.LocationY, ClickType.RightClick)); FindGoodPoint = true; break; } } } } } } if (FindGoodPoint) { break; } } if (FindGoodPoint) { break; } } } } //Bước 3: không tìm thấy một vị trí phù hợp, chỉ có thể mở ngẫu nhiên if (!FindGoodPoint) { // Debug.WriteLine("3Mở ngẫu nhiên..."); float[,] ProbabilityMap = new float[MaxX, MaxY]; //Tính xác suất tối thiểu float MinProbability = 1; for (int x = 0; x < MaxX; x++) { for (int y = 0; y < MaxY; y++) { if (MineMap[x, y] == MineState.Unknow) { ProbabilityMap[x, y] = CalcProbability(x, y, MaxX, MaxY, MineMap); if (ProbabilityMap[x, y] < MinProbability) { MinProbability = ProbabilityMap[x, y]; } } } } // Debug.WriteLine($"MinProbability={MinProbability}"); //Lấy điểm với xác suất nhỏ nhất for (int x = 0; x < MaxX; x++) { for (int y = 0; y < MaxY; y++) { if (MineMap[x, y] == MineState.Unknow && Math.Abs(ProbabilityMap[x, y] - MinProbability) < 0.001) { clickEventList.Add(new ClickEvent(x, y, ClickType.LeftClick)); } } } /* * foreach (var clickEvent in clickEventList) * { * Debug.WriteLine($"selected clickEvent:{clickEvent}"); * } */ int Count = clickEventList.Count; //ShowDebugInfo($"\r\nRandom Select:Count={Count}"); if (Count == 0) { //ShowDebugInfo("\r\n clickEventList.Count == 0,I can't do anything!"); this.timer.Enabled = false; return; } else { if (Count == 1) { ClickEvent clickEvent = clickEventList[0]; } else { Random random = new Random(); ClickEvent clickEvent = clickEventList[random.Next(Count)]; clickEventList.Clear(); clickEventList.Add(clickEvent); } } } // Click ClickScreen(RectWidth, left, top, centerleft, centertop, clickEventList); }