C#实现拼图小游戏

 更新时间:2022年08月19日 11:31:54   作者:林子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;
        }

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

相关文章

  • C#实现的三种模拟自动登录和提交POST信息的方法

    C#实现的三种模拟自动登录和提交POST信息的方法

    这篇文章主要介绍了C#实现的三种模拟自动登录和提交POST信息的方法,分别列举了WebBrowser、WebClient及HttpWebRequest实现自动登录及提交POST的相关实现技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-11-11
  • 解析C# 程序结构

    解析C# 程序结构

    在我们学习 C# 编程语言的基础构件块之前,让我们先看一下 C# 的最小的程序结构,以便作为接下来章节的参考
    2021-07-07
  • C#实现获取计算机信息的示例代码

    C#实现获取计算机信息的示例代码

    这篇文章主要为大家详细介绍了C#实现获取计算机软硬件信息的相关知识,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考下
    2024-01-01
  • C#中ArrayList的使用方法

    C#中ArrayList的使用方法

    这篇文章主要介绍了
    2013-12-12
  • C#实现判断当前操作用户管理角色的方法

    C#实现判断当前操作用户管理角色的方法

    这篇文章主要介绍了C#实现判断当前操作用户管理角色的方法,涉及C#针对系统用户判断的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-08-08
  • 深入解析C#中的交错数组与隐式类型的数组

    深入解析C#中的交错数组与隐式类型的数组

    这篇文章主要介绍了深入解析C#中的交错数组与隐式类型的数组,隐式类型的数组通常与匿名类型以及对象初始值设定项和集合初始值设定项一起使用,需要的朋友可以参考下
    2016-01-01
  • c# 绘制中国象棋棋盘与棋子

    c# 绘制中国象棋棋盘与棋子

    这篇文章主要介绍了c# 绘制中国象棋棋盘与棋子,文中实例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07
  • asp.net页面中如何获取Excel表的内容

    asp.net页面中如何获取Excel表的内容

    在浏览网页时,一定会看到我们需要保存的信息,我们比较常用的方法就是拖动鼠标,选中我们需要的内容,然后ctrl+c,然后在保持到excel当中去,那么如何用asp.net获取excel表的内容呢,下面小编就给大家介绍asp.net获取excel表的内容,需要的朋友可以参考下
    2015-08-08
  • 基于WPF实现面包屑控件的示例代码

    基于WPF实现面包屑控件的示例代码

    这篇文章主要为大家详细介绍了如何基于WPF实现简单的面包屑控件,文中的示例代码讲解详细,对我们学习或工作有一定帮助,感兴趣的小伙伴可以了解一下
    2023-05-05
  • C#获得MAC地址(网卡序列号)的实现代码

    C#获得MAC地址(网卡序列号)的实现代码

    这篇文章主要介绍了C#获得MAC地址的实现代码,需要的朋友可以参考下
    2014-02-02

最新评论