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;         }

推荐阅读