【Demo】拼图小游戏 winform (一) 简单的拖动拼图

3 篇文章 1 订阅

简单的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

  • 8
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
C#拼图游戏WinForm是一款基于Windows窗体应用程序的拼图游戏。玩家需要将一张图片分割成若干个小块,然后通过交换这些小块的位置,最终将图片拼合成完整的一张图片。以下是实现拼图游戏的基本步骤: 1. 加载图片:使用C#的Image类加载一张图片,并将其分割成若干个小块。 2. 显示小块:将分割后的小块显示在窗体上,可以使用PictureBox控件来显示。 3. 交换小块:当玩家点击两个相邻的小块时,交换它们的位置。 4. 判断游戏是否结束:当所有小块的位置都正确时,游戏结束。 5. 提供重置功能:当玩家想要重新开始游戏时,可以提供一个重置按钮,将所有小块重新随机排列。 以下是一个简单C#拼图游戏WinForm的代码示例: ``` public partial class Form1 : Form { private const int ROWS = 3; // 行数 private const int COLS = 3; // 列数 private const int BLOCK_SIZE = 100; // 小块大小 private PictureBox[,] blocks = new PictureBox[ROWS, COLS]; // 存储小块的数组 private Image image; // 原始图片 private Image[,] images = new Image[ROWS, COLS]; // 存储分割后的小块图片的数组 private Point emptyBlock; // 空白小块的位置 public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { // 加载图片 image = Image.FromFile("picture.jpg"); SplitImage(); // 显示小块 for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { blocks[i, j] = new PictureBox(); blocks[i, j].Location = new Point(j * BLOCK_SIZE, i * BLOCK_SIZE); blocks[i, j].Size = new Size(BLOCK_SIZE, BLOCK_SIZE); blocks[i, j].Image = images[i, j]; blocks[i, j].Click += Block_Click; Controls.Add(blocks[i, j]); } } // 随机排列小块 ShuffleBlocks(); } private void SplitImage() { int blockWidth = image.Width / COLS; int blockHeight = image.Height / ROWS; for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { images[i, j] = new Bitmap(blockWidth, blockHeight); Graphics g = Graphics.FromImage(images[i, j]); g.DrawImage(image, new Rectangle(0, 0, blockWidth, blockHeight), new Rectangle(j * blockWidth, i * blockHeight, blockWidth, blockHeight), GraphicsUnit.Pixel); } } } private void ShuffleBlocks() { Random random = new Random(); for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { int x = random.Next(ROWS); int y = random.Next(COLS); // 交换小块 Image tempImage = images[i, j]; images[i, j] = images[x, y]; images[x, y] = tempImage; // 记录空白小块的位置 if (images[i, j] == null) { emptyBlock = new Point(j, i); } } } UpdateBlocks(); } private void UpdateBlocks() { for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { blocks[i, j].Image = images[i, j]; } } } private void Block_Click(object sender, EventArgs e) { PictureBox block = (PictureBox)sender; Point blockLocation = new Point(block.Location.X / BLOCK_SIZE, block.Location.Y / BLOCK_SIZE); // 判断是否与空白小块相邻 if (Math.Abs(blockLocation.X - emptyBlock.X) + Math.Abs(blockLocation.Y - emptyBlock.Y) == 1) { // 交换小块 images[emptyBlock.Y, emptyBlock.X] = block.Image; images[blockLocation.Y, blockLocation.X] = null; emptyBlock = blockLocation; UpdateBlocks(); // 判断游戏是否结束 if (IsGameEnd()) { MessageBox.Show("游戏结束!"); } } } private bool IsGameEnd() { for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { if (images[i, j] != null && (i != images[i, j].Height / BLOCK_SIZE || j != images[i, j].Width / BLOCK_SIZE)) { return false; } } } return true; } private void btnReset_Click(object sender, EventArgs e) { ShuffleBlocks(); } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值