开发者

C#实现拼图小游戏

开发者 https://www.devze.com 2022-12-01 14:11 出处:网络 作者: 林子xxx
本文实例为大家分享了C#实现拼图小游戏的具体代码,供大家参考,具体内容如下1.首先布置好界面。标题栏,菜单栏,状态栏,以及放置图片框的panel。2.定义图片框类///summary///图片框类...

本文实例为大家分享了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对象,保存在phplist或者矩阵中。

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
          {
            bmp编程客栈pt = 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个鼠标事件函数
          phttp://www.devze.comb.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>
  开发者_JAVA开发  /// <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 = startlojsc;
      }
      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;
    }

C#实现拼图小游戏

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号