C#实现拼图小游戏
作者:林子xxx
这篇文章主要为大家详细介绍了C#实现拼图小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
本文实例为大家分享了C#实现拼图小游戏的具体代码,供大家参考,具体内容如下
1.首先布置好界面。
标题栏,菜单栏,状态栏,以及放置图片框的panel。
2.定义图片框类
/// <summary> /// 图片框类,包含虚拟XY位置 /// </summary> public class PictureBoxEx : PictureBox { private Point _xy ; private Point _inxy; /// <summary> /// 初始XY位置 /// </summary> public Point inxy { get { return _inxy; } // set { _inxy = value; } } /// <summary> /// 当前XY位置 /// </summary> public Point xy { get { return _xy; } set { _xy = value; } } public PictureBoxEx(Point txy) : base() { _inxy=_xy = txy; } /// <summary> /// 判断是否回到初始位置 /// </summary> /// <returns>true:回到初始位置</returns> public bool judge() { return (_xy.X == _inxy.X) && (_xy.Y == _inxy.Y); } }
每个分割的图片都是PictureBoxEx对象,保存在list或者矩阵中。
3.载入图片,随机乱序排布
/// <summary> /// 生成PictureBoxEx ,排布在panel上 /// </summary> /// <param name="img">原图</param> /// <param name="random">是否打乱显示</param> private void initPbx(Image img, bool random) { pbxs.Clear();//清除图片框列表 panelMain.Controls.Clear();//清除panel包含的控件 byte[] rands = new byte[column*row] ; //保存随机乱序一维数组 if (random) { try { generateDisorderArray(ref rands); } catch { MessageBox.Show("生成乱序错误!"); } } srcBmp = new Bitmap(srcImg); Size rbmpSize = new System.Drawing.Size(srcBmp.Width / column, srcBmp.Height / row); int bw = srcBmp.Width / column, bh = srcBmp.Height / row; int rw = panelMain.ClientSize.Width / column, rh = panelMain.ClientSize.Height / row; int cnt = 0; for (int i = 0; i < column; i++)//行 { pbxs.Add( new List<PictureBoxEx>() ); for (int j = 0; j < row; j++)//列 { PictureBoxEx pb = new PictureBoxEx( new Point(i,j)); pb.Size = new System.Drawing.Size(rw,rh); pb.BorderStyle = BorderStyle.None; pb.Dock = DockStyle.None; pb.BackgroundImageLayout = ImageLayout.Stretch; panelMain.Controls.Add(pb); pb.Location = new Point(rw*i,rh*j); pbxs[i].Add(pb); Bitmap tbmp = new Bitmap(rw, rh); Graphics g = Graphics.FromImage(tbmp); Point bmppt; if (random) { //一维转二维 int ri = rands[cnt] % column; int rj = (rands[cnt] / column) % row; bmppt = new Point(bw * ri, bh * rj); pb.xy = new Point(ri, rj); cnt++; } else { bmppt = new Point(bw * i, bh * j); } g.DrawImage(srcBmp, pb.ClientRectangle, new Rectangle( bmppt , rbmpSize), GraphicsUnit.Pixel); g.DrawRectangle( Pens.Red ,pb.ClientRectangle); if (!random) { g.DrawString(pb.xy.ToString(), new Font(System.Drawing.SystemFonts.DefaultFont.Name, 10),new SolidBrush(Color.Red), new PointF(1.0f, 1.0f)); } g.Dispose(); pb.BackgroundImage = tbmp; //为实现拖动图片,加入3个鼠标事件函数 pb.MouseDown += new MouseEventHandler(pb_MouseDown); pb.MouseMove += new MouseEventHandler(pb_MouseMove); pb.MouseUp += new MouseEventHandler(pb_MouseUp); if (random) { isStartGame = true; lab_canplay.BackColor = Color.Green; } else { isStartGame = false; lab_canplay.BackColor = Color.Red; } } } }
生成随机乱序数组函数:单纯的随机数组是不行的,因为随机不一定乱序。
/// <summary> /// 生成随机乱序数组,洗牌 FisherYates Shuffle /// 随机不一定无序,所以还需要检查无序的度 /// </summary> public void generateDisorderArray(ref byte[] arr ) { byte len = (byte)arr.Length; if (len == 1U) { arr[0] = 0; } else if (len == 2U) { arr[0] = 1; arr[1] = 0; } else { for (byte i = 0; i < len; i++) { arr[i] = i; } byte[] rands = new byte[len * 4]; rng.GetBytes(rands); for (int j = len-1; j >=0; j--) { int idx = (int)(BitConverter.ToUInt32(rands, j * 4) % (byte)(j + 1)); SwapValue<byte>(ref arr[idx], ref arr[j]); } //下面简单检查无序度 List<byte> defs = new List<byte>(); for (byte a=0; a < len;a++ ) { if (a == arr[a]) defs.Add(a); //记录位置 } //有一半在原位置,则不够无序,首尾换位 if ( defs.Count > 1 && defs.Count >= (len/2) ) { for (byte i = 0; i < defs.Count/2; i++) { SwapValue<byte>(ref arr[defs[i]], ref arr[defs[defs.Count - 1 - i]]); } } } } /// <summary> /// 交换数值 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="a"></param> /// <param name="b"></param> public static void SwapValue<T>(ref T a, ref T b) { T temp=a ; a=b ; b=temp ; }
4.图片拖动交换
/// <summary> /// 交换图片,位置信息 /// </summary> /// <param name="srcXY">源位置</param> /// <param name="dstXY">目的位置</param> private void SwapPbx(Point srcXY, Point dstXY) { PictureBoxEx pba = pbxs[srcXY.X ][ srcXY.Y]; PictureBoxEx pbb = pbxs[dstXY.X ][ dstXY.Y]; if (srcXY.X == dstXY.X && srcXY.Y == dstXY.Y) { pba.Location = startloc; } else { pba.Location = startloc; var img = pba.BackgroundImage; pba.BackgroundImage = pbb.BackgroundImage ; pbb.BackgroundImage = img; var temp = pba.xy; pba.xy = pbb.xy; pbb.xy = temp; } } /// <summary> /// 像素点位置转化为虚拟XY坐标 /// </summary> /// <param name="pt">像素点位置</param> /// <param name="sz">所在的范围</param> /// <returns>虚拟XY坐标</returns> private Point PointToXY(Point pt, Size sz) { Size s = sz; Point p = pt; int rw = s.Width / column; int rh = s.Height / row; return new Point(p.X / rw, p.Y / rh); }
三个鼠标事件函数
private void pb_MouseUp(object sender, MouseEventArgs e) { if (isDrag) { isDrag = false; Point upxy = PointToXY(((Control)sender).Parent.PointToClient(Control.MousePosition), ((Control)sender).Parent.Size); SwapPbx(startxy, upxy); gameSteps++; toolStripLab_Step.Text = "步数:" + gameSteps; { if (judgeResult(pbxs))//拼图OK { toolStripLab_Tip.Text = "完成拼图"; DialogResult res = new FormOK( "完成拼图!\r使用步数:" + gameSteps ).ShowDialog(); if (res == DialogResult.Abort) { this.Close(); } else if (res == DialogResult.OK) { if (srcImg != null) { initPbx(srcImg, true); isStartGame = true; } } enableNumud(true); gameSteps = 0; } } } } private void pb_MouseMove(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left && isDrag) { Point mousePos = Control.MousePosition; mousePos.Offset(mouse_offset.X, mouse_offset.Y); ((Control)sender).Location = ((Control)sender).Parent.PointToClient(mousePos); } } private void pb_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left && pbxs.Count > 0 && isStartGame ) { isDrag = true; enableNumud( false ); startloc = ((Control)sender).Location; mouse_offset = new Point(-e.X, -e.Y); ((Control)sender).BringToFront(); Point pp = ((Control)sender).Parent.PointToClient(Control.MousePosition); startxy = PointToXY(pp, ((Control)sender).Parent.Size); } }
5.判断是否成功
/// <summary> /// 判断是否成功 /// </summary> /// <param name="pbxs">图片矩阵</param> /// <returns>是否归位了</returns> private bool judgeResult(List<List<PictureBoxEx>> pbxs) { bool res = true; foreach (var i in pbxs) { foreach (var j in i) { if (!j.judge()) { res = false; return res; } } } return res; }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。