Пример #1
0
        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);
        }
Пример #2
0
        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);
        }