实例介绍
【实例简介】
【实例截图】
【核心代码】
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;
namespace LilacFlower
{
public partial class Form1 : Form
{
/// 图块移动委托
public delegate void MoveMode(PictureItem box, Point to);
/// 胜利事件
public event EventHandler WinNow;
/// 存放图片的文件目录名称
private const string PicturePath = "Image";
/// 图块每一次移动的距离
private const int MoveSize = 8;
/// 画笔宽度
private const int PenSize = 2;
private static readonly Color BoxMouseInColor = Color.Red;
private static readonly Color BoxMouseOutColor = Color.LightGreen;
/// 图片格式
private const string PictureFormat = "*.jpg *.png *.gif";
private List<FileInfo> _fileList = new List<FileInfo>(); //提供创建、复制、删除、移动和打开文件的实例方法
private PictureItem[,] _pictureArray; //整个图所分成的二维模块数组表达形式
private Point _nullBox = new Point(0, 0);// 是那个空白的格子的位置
private bool _drawNumber;// 是否在图片上绘制数字
private bool _gameStart;// 游戏是否已经开始了
public Form1()
{
InitializeComponent();
// 窗体相关设置
this.Text = "拼图游戏(LilacFlower)";
// 去掉最大化按钮
this.MaximizeBox = false;
// 禁止拉伸窗口
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
// 默认选择 简单(3*3)
this.difficultySelection.SelectedIndex = 0;
// 显示背景
this.mainPanel.BackColor = Color.Wheat;
// 双缓冲绘图
this.DoubleBuffered = true;
// 加载图片
LoadPicture(0);
this._drawNumber = false;
this._gameStart = false;
// 胜利
this.WinNow = new EventHandler(Form1_WinNow);
}
/// 胜利
void Form1_WinNow(object sender, EventArgs e)
{
// 胜利后被调用
MessageBox.Show("You Win!");
this._gameStart = false;
}
/// 从Image目录下加载所有图片目前支持3种格式(*.jpg,*.gif,*.png)
private void LoadPicture(int startListBoxIndex)
{
// 第一次运行创建Image目录
if (!Directory.Exists(PicturePath))
{
Directory.CreateDirectory(PicturePath);
}
DirectoryInfo directory = new DirectoryInfo(PicturePath);
// 获取Image目录下所有图片文件
this._fileList = new List<FileInfo>();
foreach (var item in PictureFormat.Split(' '))
{
this._fileList.AddRange(directory.GetFiles(item));
}
this.pictureShowListBox.Items.Clear();
// ListBox 初始化
foreach (var item in this._fileList)
{
this.pictureShowListBox.Items.Add(item.Name);
}
this.pictureShowListBox.SelectedIndex = startListBoxIndex;
}
/// lpictureShowListBox上面的图片选择发生变化
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
var file = _fileList[this.pictureShowListBox.SelectedIndex];
try
{
// 显示模型图片
this.modePicture.Image = Image.FromFile(file.FullName);
}
catch
{
MessageBox.Show("图片加载失败!请检查路径" file.FullName "图片是否正确!");
}
}
/// 增加图片
private void addPicturebtn_Click(object sender, EventArgs e)
{
// 显示打开文件对话框
OpenFileDialog dlg = new OpenFileDialog();
dlg.Filter = "jpg文件|*.jpg|png图片|*.png|gif图片|*.gif";
// 按下确定
if (DialogResult.OK == dlg.ShowDialog())
{
try
{
// 把文件拷贝到 Image目录下
File.Copy(dlg.FileName, PicturePath "\\" System.IO.Path.GetFileName(dlg.FileName));
NewPicture(PicturePath "\\" System.IO.Path.GetFileName(dlg.FileName));
}
catch (Exception ex)
{
// 文件拷贝失败
MessageBox.Show("文件复制失败!" ex.Message);
}
}
dlg.Dispose();
}
/// 新增加一张图片
private void NewPicture(string path)
{
var file = new FileInfo(path);
this._fileList.Add(file);
this.pictureShowListBox.Items.Add(file.Name);
}
/// 点击开始 GameStart!
private void startbtn_Click(object sender, EventArgs e)
{
if (!this._gameStart)
{
this._gameStart = true;
}
else if (DialogResult.No == MessageBox.Show("是否需要重新开始一盘?", "重新开始", MessageBoxButtons.YesNo))
{
return;
}
// 销毁之前的图片资源
foreach (var item in this.mainPanel.Controls)
{
var box = item as PictureItem;
box.Image.Dispose();
box.Image = null;
}
this.mainPanel.Controls.Clear();
// 横竖的图块个数 ?*?
int num = this.difficultySelection.SelectedIndex * 2 3;
// 显示在mainPAanel上的图块的大小
int size = (this.mainPanel.Height - 3) / num;
// 加载图块图片
Bitmap bmp = this.modePicture.Image as Bitmap;
// 真实image所分成的小块图片的大小
int boxHeight = bmp.Height / num;
int boxWidth = bmp.Width / num;
this._pictureArray = new PictureItem[num, num];
Pen inp = new Pen(BoxMouseInColor, PenSize);
Pen outp = new Pen(BoxMouseOutColor, PenSize);
for (int i = 0; i < num; i )
{
for (int j = 0; j < num; j )
{
// 删掉左上角那个
if (i == 0 && j == 0)
continue;
// 图块 的相关设置
_pictureArray[i, j] = new PictureItem();
var box = _pictureArray[i, j];
box.Location = new Point(size * i 2, size * j 2);
box.Size = new Size(size, size);
// 设置图片的特效
box.SetBitmap(DivisionPicture(bmp, boxWidth * i, boxHeight * j, boxWidth, boxHeight, inp, -1),
DivisionPicture(bmp, boxWidth * i, boxHeight * j, boxWidth, boxHeight, outp, -1),
DivisionPicture(bmp, boxWidth * i, boxHeight * j, boxWidth, boxHeight, inp, i * num j),
DivisionPicture(bmp, boxWidth * i, boxHeight * j, boxWidth, boxHeight, outp, i * num j));
box.SizeMode = PictureBoxSizeMode.StretchImage; //指定图像拉伸方式适合
box.At = new Point(i, j);
box.SetRightPoint(i, j);
box.ShowNumber = _drawNumber;
// 添加图片的点击函数
box.Click = new EventHandler(box_Click);
this.mainPanel.Controls.Add(box);
}
}
// 随机打乱这些图块来
Random r = new Random(System.DateTime.Now.Millisecond);
for (int i = 0; i < 200; i )
{
// 随机拿2个图快
var box1 = this.mainPanel.Controls[r.Next(0, num * num - 2)] as PictureItem;
var box2 = this.mainPanel.Controls[r.Next(0, num * num - 2)] as PictureItem;
if (box1 == box2)
continue;
// 交换他们的位置
var tempAt = box1.At;
var tempLoca = box1.Location;
box1.At = box2.At;
box1.Location = box2.Location;
box2.At = tempAt;
box2.Location = tempLoca;
}
this._nullBox = new Point(0, 0);
inp.Dispose();
outp.Dispose();
}
/// 任意一个图块被点击
void box_Click(object sender, EventArgs e)
{
// 获取被点击的图块
PictureItem box = sender as PictureItem;
// 如果旁边是能点击的,移动该box位置
int xL = this._nullBox.X - box.At.X;
int yL = this._nullBox.Y - box.At.Y;
if ((xL == 0 && yL == -1) || (xL == 0 && yL == 1) || (xL == -1 && yL == 0) || (xL == 1 && yL == 0))
{
MoveTo(box, _nullBox);
}
}
/// 将box图块移动到to位置
private void MoveTo(PictureItem box, Point to)
{
// 使用多线程来完成 匿名函数
Thread start = new Thread(() =>
{
lock (this)
{
if (this.InvokeRequired)//判断是否要调用下面的Invoke方法
{
// 考虑到跨线程访问控件的值安全性 使用该方法
this.BeginInvoke(new MoveMode(MoveBox), box, to);//用指定的参数异步执行委托
}
else
{
MoveBox(box, to);
}
}
}
);
// 开始运行
start.Start();
}
/// 移动图块
private void MoveBox(PictureItem box, Point to)
{
// 计算 to位置的像素点屏幕坐标
int x = box.Size.Width * to.X;
int y = box.Size.Height * to.Y;
int xL = box.Location.X - x;
int yL = box.Location.Y - y;
int size = (int)Math.Sqrt(xL * xL yL * yL);
// 缓缓的从本身位置移动到 to位置
while (size > 5)
{
box.Location = new Point(box.Location.X - MoveSize * xL / size, box.Location.Y - MoveSize * yL / size);
xL = box.Location.X - x;
yL = box.Location.Y - y;
size = (int)Math.Sqrt(xL * xL yL * yL);
Thread.Sleep(1);
}
box.Location = new Point(x, y);
// 交换图块和空白位置的坐标
var temp = this._nullBox;
this._nullBox = box.At;
box.At = temp;
// 判断移动完毕后图块是否正确!
if (IsOver() && WinNow != null)
{
WinNow(this, new EventArgs());
}
}
/// 截取bmp图片中的一部分,并在图片四周画上方框
/// <param name="bmp">被截取的图片</param>
/// <param name="width">截取的长度</param>
/// <param name="heigth">截取的宽度</param>
private Bitmap DivisionPicture(Bitmap bmp, int x, int y, int width, int height, Pen p, int number)
{
Bitmap b = new Bitmap(width, height);
// g上的绘图将直接绘制到位图b上
Graphics g = Graphics.FromImage(b);
g.DrawImage(bmp, new Rectangle(0, 0, width, height), new Rectangle(x, y, width, height), GraphicsUnit.Pixel);
g.DrawRectangle(p, new Rectangle(1, 1, width - 2, height - 2));
// 需要绘制数字
if (number >= 0)
{
g.DrawString(number.ToString(), new System.Drawing.Font("楷体", width / 5, FontStyle.Bold), Brushes.Red, new PointF(width / 2 - width / 10, height / 2 - width / 10));
}
g.Dispose();
return b;
}
/// 点击图片,选择是否显示图块数字
private void modePicture_Click(object sender, EventArgs e)
{
this._drawNumber = !this._drawNumber;
this.Text = this._drawNumber ? "拼图游戏(LilacFlower)显示数字" : "拼图游戏(LilacFlower)";
foreach (var item in this.mainPanel.Controls)
{
var box = item as PictureItem;
box.ShowNumber = this._drawNumber;
}
}
/// 是否图块排放正确
private bool IsOver()
{
foreach (var item in this.mainPanel.Controls)
{
var box = item as PictureItem;
// 图块摆放不正确
if (box.At != box.RightAt)
return false;
}
return true;
}
}
/// 图块
public class PictureItem : PictureBox
{
private Bitmap _mouseOutBitmap;// 默认图片
private Bitmap _mouseInBitmap; // 鼠标移入的图片
private Bitmap _mouseOutBitmapContainsNumber;// 包含数字的默认图片
private Bitmap _mouseInBitmapContainsNumber;// 包含数字的鼠标移入图片
/// 是否显示图片数字
private bool _showNumber;
public bool ShowNumber
{
get
{
return this._showNumber;
}
set
{
this._showNumber = value;
this.PictureItem_MouseLeave(this, new EventArgs());
}
}
/// 图块所在的位置
public Point At
{
get;
set;
}
/// 图块的正确位置 用于判断图块是否在正确位置上
public Point RightAt
{
protected set;
get;
}
public PictureItem()
{
// 鼠标移入图片方框颜色变化
this.MouseEnter = new EventHandler(PictureItem_MouseEnter);
// 鼠标移出使用默认图片
this.MouseLeave = new EventHandler(PictureItem_MouseLeave);
}
/// 鼠标离开
void PictureItem_MouseLeave(object sender, EventArgs e)
{
if (!this._showNumber)
{
this.Image = this._mouseOutBitmap;
}
else this.Image = this._mouseOutBitmapContainsNumber;
}
/// 鼠标移入
void PictureItem_MouseEnter(object sender, EventArgs e)
{
if (!this._showNumber)
{
this.Image = this._mouseInBitmap;
}
else this.Image = this._mouseInBitmapContainsNumber;
}
/// 设置图块的图片
public void SetBitmap(Bitmap msIn, Bitmap msOut, Bitmap numMsIn, Bitmap numMsOut)
{
this._mouseInBitmap = msIn;
this._mouseOutBitmap = msOut;
this._mouseOutBitmapContainsNumber = numMsOut;
this._mouseInBitmapContainsNumber = numMsIn;
this.Image = msOut; //默认显示image是不带数字的鼠标离开的图像
}
/// 设置图块的正确位置
public void SetRightPoint(int x, int y)
{
this.RightAt = new Point(x, y);
}
}
}
好例子网口号:伸出你的我的手 — 分享!
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明


网友评论
我要评论