1. 程式人生 > >【Demo】拼圖小遊戲 winform (一) 簡單的拖動拼圖

【Demo】拼圖小遊戲 winform (一) 簡單的拖動拼圖

簡單的Demo,可以用於學習Image的處理、winform裡的拖動事件,也可以用於廣大學生黨的作業 (其實這就是幫學生黨解決的作業,只不過後來又調整了下……),因為是Demo,所以程式碼也就隨便了些,下面是執行時的截圖,弄個妹子賞眼點,遊戲方式就是將隨機打亂的圖片拖動到待拼圖區域,如果位置一致時,在滑鼠鬆開,圖片就會被繪製到待拼圖區域,同時在隨機打亂的圖片中移除這一塊區域

首先是圖片相關的部分:圖片等比例縮放+分割,以下是相關程式碼

    public static class Helpers
    {
        /// <summary>
        /// 獲取等比例縮放的圖片(高寬不一致時獲取最中間部分的圖片)
        /// </summary>
        /// <param name="fromImage"></param>
        /// <param name="width">要獲取的寬度</param>
        /// <param name="height">要獲取的高度</param>
        /// <returns></returns>
        public static Image AdjImageToFitSize(this Image fromImage, int width, int height)
        {
            Bitmap bitmap = new Bitmap(width, height);
            Graphics graphics = Graphics.FromImage(bitmap);
            Point point = new Point(0, 0);
            Point point2 = new Point(width, 0);
            Point point3 = new Point(0, height);
            Point[] destPoints = new Point[] { point, point2, point3 };
            Rectangle rect = GetImageRectangle(fromImage);
            graphics.DrawImage(fromImage, destPoints, rect, GraphicsUnit.Pixel);
            Image image = Image.FromHbitmap(bitmap.GetHbitmap());
            bitmap.Dispose();
            graphics.Dispose();
            return image;
        }
        private static Rectangle GetImageRectangle(Image fromImage)
        {//居中位置獲取
            int x = 0;
            int y = 0;
            int height = fromImage.Height;
            int width = fromImage.Width;
            if (fromImage.Height > fromImage.Width)
            {
                height = fromImage.Width;
                y = (fromImage.Height - fromImage.Width) / 2;
            }
            else
            {
                width = fromImage.Height;
                x = (fromImage.Width - fromImage.Height) / 2;
            }
            return new Rectangle(x, y, width, height);
        }

        /// <summary>
        /// 將圖片切割成小圖片,圖片順序為先水平後垂直
        /// </summary>
        /// <param name="fromImage"></param>
        /// <param name="cx">x方向切割數</param>
        /// <param name="cy">y方向切割數</param>
        /// <returns></returns>
        public static Image[] SplitToSmallImages(this Image fromImage, int cx, int cy)
        {
            Image[] imgs = new Image[cx * cy];
            int nWidth = fromImage.Width / cx;
            int nHeight = fromImage.Height / cy;
            Bitmap image = new Bitmap(nWidth, nHeight);
            Graphics graphics = Graphics.FromImage(image);
            for (int i = 0; i < cy; i++)
            {
                for (int j = 0; j < cx; j++)
                {
                    graphics.DrawImage(fromImage, 0, 0, new Rectangle(j * nWidth, i * nHeight, nWidth, nHeight), GraphicsUnit.Pixel);
                    Image img = Image.FromHbitmap(image.GetHbitmap());
                    int idx = j + i * cx;
                    img.Tag = idx;
                    imgs[idx] = img;
                }
            }
            return imgs;
        }
    }
然後各種點選、拖動互動的就不多說了,可以自行去下載程式碼後檢視,因為圖片分割的時候是分割成了一維陣列,這裡就說下如何根據索引編號獲取對應的二維陣列,下面是相關程式碼片段,上面的程式碼中在切割圖片時已經採用了先水平後垂直的方式,那根據索引獲取二維位置也就只要這樣就行了,即水平位置的計算方式為 索引號%每行分割塊數,垂直位置的計算方式為 索引號/每行分割塊數,當然下面的程式碼中不是通過索引來獲取x,y進行對比,而是根據x,y獲取對應索引
            int idx = (int)e.Data.GetData(typeof(int));
            Point p = this.pnl_DragOn.PointToClient(new Point(e.X, e.Y));
            int x = p.X / this.SideLength;//計算x方向上的位置
            int y = p.Y / this.SideLength;//計算y方向上的位置
            if (idx == x + this.ImgNumbers * y)//判斷圖片位置是否與計算出來的位置一致
            {
                Graphics graphics = this.pnl_DragOn.CreateGraphics();
                graphics.DrawImage(this._dragPic.Image, x * this.SideLength, y * this.SideLength);
                this._dragPic.Image = null;//圖片放置後,移除Box上的Image
                if (!this._splitPictureBoxes.Any(pb => pb.Image != null))
                {
                    MessageBox.Show("恭喜你,圖片拼好了");
                }
            }

原始碼下載,在Program.cs裡面Application.Run(new RandomPictureForm1())執行即為此部落格對應Demo