与第一篇一样,同属简单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