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; }
以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。
推薦閱讀:
- C#自定義畫刷原理解析
- C#微信公眾號開發之用戶上下文WeixinContext和MessageContext
- C#模擬實現鼠標自動點擊與消息發送功能
- 詳解C#如何實現讀寫ini文件
- C#實現截圖幫助類