【Demo】拼图小游戏 winform (二) 只能在空格区域移动的拼图

与第一篇一样,同属简单Demo,这个在开始做的时候,想的是将PictureBox拖动到另一个PictureBox上,如果PictureBox没图片,就将Image传递,但想法是简单的,事实是复杂的:首先PictureBox不支持DragEnter和DragDrop事件,所以后面将图片的载体换成了Panel;其次图片全随机打乱不行,第一行的最后一张图片是不能随机的,必须为特定图片(当然这是因为这个Demo是所有小图都存在的,其实也可以做成随机取消一块图片的拼图游戏,只要在此Demo上做些调整);最后还有如何确认Panel是否允许拖动的问题。游戏玩法就是在小图片上按住鼠标拖动到空白区域(只有临近空白的几个方块允许拖动,只要将源码中一行代码取消注销掉,就可以取消掉这个限制),下面是运行时的截图,同样弄了个妹子赏眼点

技术分享

与前一篇Demo相比,现在分割出来的小图片载体Panel既要接受MouseDown事件,又要接受DragEnter以及DragDrop事件,在MouseDown事件中确认该图片是否允许拖动,而是否允许拖动的判断逻辑就是:当前点击的Panel的Tag是否不为null(这里用Tag来判断是否空白区域),并且该Panel的上下左右四块区域是否有空白区域或为边界,至于索引如何换算成二维数组位置与第一篇中的规则一样,下面即为MouseDown事件执行的代码

      private void panel_MouseDown(object sender, MouseEventArgs e)
        {
            Panel panel = (Panel)sender;
            if (panel.Tag != null)
            {
                bool allowed;
                if (panel.Name.Contains('_'))
                {//非emptyPanel
                    int idx = int.Parse(panel.Name.Split('_')[1]);
                    int x = idx % this.ImgNumbers;//换算成x方向上第几块
                    int y = idx / this.ImgNumbers;//换算成y方向上第几块
                    //只要上下左右四个方向上是否有一个Panel是允许拖动的,就可以拖动
                    allowed = this.AllowDragDrop(x - 1, y) || this.AllowDragDrop(x + 1, y) || this.AllowDragDrop(x, y - 1) || this.AllowDragDrop(x, y + 1);
                }
                else
                {//emptyPanel只需要判断第N-1块是不是为空
                    allowed = this._splitPanels[this.SpecialIndex].Tag == null;
                }
                //allowed = true;//取消注释可以任意位置调整拼图
                if (allowed)
                {
                    this._dragPanel = panel;
                    panel.DoDragDrop(this._dragPanel.Tag, DragDropEffects.Move | DragDropEffects.Copy);
                }
            }
        }
对于AllowDragDrop,这里单独说明:if判断该x,y是否能够获取到对应Panel,如果获取不到,则代表已出了临界范围,肯定不能拖动;如果能取到Panel,这里又分两种情况,一种是第一行额外增加的专用于显示特定图片的Panel,还有就是正常分割出来的Panel,如果Panel对应的Tag为null,则代表该Panel为空白区域
        /// <summary>
        /// 判断特定的panel是否允许拖动
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        private bool AllowDragDrop(int x, int y)
        {
            bool allowed = true;
            if (x < 0 || y < 0 || y >= this.ImgNumbers || (x >= this.ImgNumbers && y > 0))
            {//不存在panel
                allowed = false;
            }
            else
            {
                if (x >= this.ImgNumbers && y == 0)
                {
                    allowed = this._emptyPanel.Tag == null;
                }
                else
                {
                    allowed = this._splitPanels[x + y * this.ImgNumbers].Tag == null;
                }
            }
            return allowed;
        }
最后的DragDrop事件这里就不多说了,跟文章开头说的一样,直接传递Image并修正Tag,同时修正AllowDrop属性
      void panel_DragDrop(object sender, DragEventArgs e)
        {
            Panel panel = (Panel)sender;
            panel.Tag = this._dragPanel.Tag;
            panel.BackgroundImage = this._splitImages[(int)panel.Tag];
            panel.AllowDrop = false;
            this._dragPanel.Tag = null;
            this._dragPanel.AllowDrop = true;
            this._dragPanel.BackgroundImage = null;

            if (this._emptyPanel.Tag == null && !this._splitPanels.Any((p) => string.Format("pnl_{0}", p.Tag) != p.Name))
            {//空Panel不再包含tag,并且Panel对应Tag顺序正确
                this._emptyPanel.AllowDrop = false;
                MessageBox.Show("恭喜你,图片拼好了");
            }
        }
源码下载,在Program.cs里面Application.Run(new RandomPictureForm2())运行即为此博客对应Demo


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。