實(shí)驗(yàn)題目
本章的主要內(nèi)容是設(shè)計(jì)開發(fā)一個(gè)趣味拼圖游戲,其功能是對(duì)加載的圖片進(jìn)行分割(如分割3×3矩陣或其他類型矩陣)并隨機(jī)加載到圖片框矩陣中,用戶使用鼠標(biāo)拖動(dòng)圖片框中的圖片進(jìn)行拼圖,系統(tǒng)能夠自動(dòng)判別拼圖是否成功并進(jìn)行提示。設(shè)計(jì)過程包括項(xiàng)目分析、界面設(shè)計(jì)、代碼編寫和運(yùn)行調(diào)試。
實(shí)驗(yàn)方案

界面設(shè)計(jì)


功能展示
1.查看原圖

2.單邊切割任意邊數(shù)


3.普通模式拼圖(正計(jì)時(shí)+步數(shù)統(tǒng)計(jì))

擴(kuò)展功能
(1)挑戰(zhàn)模式難度選擇
設(shè)計(jì)思路:設(shè)計(jì)了三個(gè)難度,分別對(duì)應(yīng)的是不同的倒計(jì)時(shí)限制和單邊切割數(shù)。簡(jiǎn)單模式(2×2切割,10s倒計(jì)時(shí));一般模式(4×4切割,30s倒計(jì)時(shí));簡(jiǎn)單模式(6×6切割,60s倒計(jì)時(shí));需要在代碼中單獨(dú)設(shè)置一個(gè)變量來記錄模式。



(2)步數(shù)統(tǒng)計(jì)
設(shè)計(jì)思路:?jiǎn)为?dú)設(shè)置一個(gè)變量count,每次移動(dòng)計(jì)數(shù),顯示在文本框里,成功后清零即可。
(3)時(shí)間控制
設(shè)計(jì)思路:主要是用到了timer控件,因?yàn)樘魬?zhàn)模式和普通模式分別對(duì)應(yīng)了正計(jì)時(shí)和倒計(jì)時(shí)兩種表示,但基本原理是一樣的。為了保證timer控件的開啟,還新增了“開始游戲”按鈕。



實(shí)驗(yàn)總結(jié)
本次實(shí)驗(yàn)代碼體量較小,但是代碼難度較高,理解起來相當(dāng)復(fù)雜?;A(chǔ)部分主要參考書上代碼以及網(wǎng)上的內(nèi)容。拓展部分主要參考網(wǎng)上的內(nèi)容自行理解加以修正。整體碰見以下問題,現(xiàn)加以分析:
1.在參考書上的代碼敲上去以后,發(fā)現(xiàn)缺失一部分代碼,所以上網(wǎng)上查找相關(guān)的代碼,后來參考網(wǎng)上的代碼完成實(shí)驗(yàn)的基本操作。
2.在拓展部分出現(xiàn)計(jì)時(shí)功能,查找相關(guān)計(jì)時(shí)的控件以及使用方式得以解決,在同學(xué)的建議下將挑戰(zhàn)模式的計(jì)時(shí)變成倒計(jì)時(shí)更符合實(shí)驗(yàn)的功能。
3.在制作時(shí),還有很重要的是對(duì)txt_step,txt_time1,txt_time2的清空操作,不恰當(dāng)?shù)脑捰脩趔w驗(yàn)很不好。
4.看到同學(xué)們?cè)黾恿艘纛l(每次移動(dòng)圖片都會(huì)有聲音,成功也有聲音提醒)。初步了解下原理發(fā)現(xiàn)和加圖片差不多,但沒有做出來,希望以后有機(jī)會(huì)可以試一下。
源碼展示
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Media;
namespace myPuzzle
{
public partial class Form_Main : Form
{
public Form_Main()
{
InitializeComponent();
InitGame();
}
PictureBox[] pictureList = null;
SortedDictionary<string, Bitmap> PictureLocationDictDict = new SortedDictionary<string,Bitmap>();
Point[] pointList = null;
SortedDictionary<string, PictureBox> PictureBoxLocationDict = new SortedDictionary<string, PictureBox>();
int second=0;
int count = 0;
int dif = 0;
PictureBox currentPictureBox = null;
PictureBox haveToPictureBox = null;
Point oldLocation = Point.Empty;
Point newLocation = Point.Empty;
Point mouseDownPoint = Point.Empty;
Rectangle rect = Rectangle.Empty;
bool isDrag = false;
public string originalpicpath;
private int ImgNumbers
{
get
{
return (int)this.numericUpDown1.Value;
}
}
private int SideLength
{
get
{
return 600 / this.ImgNumbers;
}
}
private void InitRandomPictureBox()
{
pnl_Picture.Controls.Clear();
pictureList = new PictureBox[ImgNumbers * ImgNumbers];
pointList = new Point[ImgNumbers * ImgNumbers];
for (int i=0;i<this.ImgNumbers;i++)
{
for(int j=0;j<this.ImgNumbers;j++)
{
PictureBox pic = new PictureBox();
pic.Name = "pictureBox" + (j + i * ImgNumbers + 1).ToString();
pic.Location = new Point(j * SideLength, i * SideLength);
pic.Size = new Size(SideLength, SideLength);
pic.Visible = true;
pic.BorderStyle = BorderStyle.FixedSingle;
pic.MouseDown += new MouseEventHandler(pictureBox_MouseDown);
pic.MouseMove += new MouseEventHandler(pictureBox_MouseMove);
pic.MouseUp += new MouseEventHandler(pictureBox_MouseUp);
pnl_Picture.Controls.Add(pic);
pictureList[j + i * ImgNumbers] = pic;
pointList[j + i * ImgNumbers] = new Point(j * SideLength, i * SideLength);
}
}
}
public void Flow(string path,bool disorder)
{
InitRandomPictureBox();
Image bm = CutPicture.Resize(path, 600, 600);
CutPicture.BitMapList = new List<Bitmap>();
for(int y=0;y<600;y+=SideLength)
{
for(int x=0;x<600;x+=SideLength)
{
Bitmap temp = CutPicture.Cut(bm, x, y, SideLength, SideLength);
CutPicture.BitMapList.Add(temp);
}
}
ImportBitMap(disorder);
}
/// 打亂數(shù)據(jù)
public Point[] DisOrderLocation()
{
Point[] tempArray = (Point[])pointList.Clone();
for (int i = tempArray.Length - 1; i > 0; i--)
{
Random rand = new Random();
int p = rand.Next(i);
Point temp = tempArray[p];
tempArray[p] = tempArray[i];
tempArray[i] = temp;
}
return tempArray;
}
public void ResetPictureLocation()
{
Point[] temp = DisOrderLocation();
int i = 0;
foreach (PictureBox item in pictureList)
{
item.Location = temp[i];
i++;
}
}
public void ImportBitMap(bool disorder)
{
try
{
int i = 0;
foreach(PictureBox item in pictureList)
{
Bitmap temp = CutPicture.BitMapList[i];
item.Image = temp;
i++;
}
if (disorder)
ResetPictureLocation();
}
catch(Exception exp)
{
Console.WriteLine(exp.Message);
}
}
public void InitGame()
{
//if(!Directory.Exists(Application.StartupPath.ToString() + "\\picture"))
{
Directory.CreateDirectory(Application.StartupPath.ToString() + "\\Picture");
//Properties.Resources.默認(rèn).Save(Application.StartupPath.ToString() + "\\Picture\\1.jpg");
Properties.Resources._1.Save(Application.StartupPath.ToString() + "\\Picture\\1.jpg");
Properties.Resources._2.Save(Application.StartupPath.ToString() + "\\Picture\\2.jpg");
Properties.Resources._3.Save(Application.StartupPath.ToString() + "\\Picture\\3.jpg");
Properties.Resources._4.Save(Application.StartupPath.ToString() + "\\Picture\\4.jpg");
Properties.Resources._5.Save(Application.StartupPath.ToString() + "\\Picture\\5.jpg");
Properties.Resources._0.Save(Application.StartupPath.ToString() + "\\Picture\\0.jpg");
}
Random r = new Random();
int i = r.Next(6);
originalpicpath = Application.StartupPath.ToString() + "\\Picture\\" + i.ToString() + ".jpg";
Flow(originalpicpath, true);
}
public PictureBox GetPictureBoxByLocation(int x,int y)
{
PictureBox pic = null;
foreach(PictureBox item in pictureList)
{
if(x>item.Location.X&&y>item.Location.Y&&item.Location.X+SideLength>x&&item.Location.Y+SideLength>y)
{
pic = item;
}
}
return pic;
}
private void Pnl_Picture_MouseDown(object sender, MouseEventArgs e)
{
}
//通過hashcode獲取picture,用mouseeventargs之后獲取相對(duì)于picture的坐標(biāo)不是相對(duì)窗體
public PictureBox GetPictureBoxByHashCode(string hascode)
{
PictureBox pic = null;
foreach (PictureBox item in pictureList)
{
if (hascode == item.GetHashCode().ToString())
{
pic = item;
}
}
return pic;
}
private void pictureBox_MouseDown(object sender, MouseEventArgs e)
{
if(timer1.Enabled==false)
{
MessageBox.Show("請(qǐng)點(diǎn)擊開始游戲!");
}
else
{
oldLocation = new Point(e.X, e.Y);
currentPictureBox = GetPictureBoxByHashCode(sender.GetHashCode().ToString());
MoseDown(currentPictureBox, sender, e);
}
}
private void MoseDown(PictureBox pic,object sender, MouseEventArgs e)
{
if(e.Button==MouseButtons.Left)
{
oldLocation = e.Location;
rect = pic.Bounds;
}
}
private Point getPointToForm(Point p)
{
return this.PointToClient(pictureList[0].PointToScreen(p));
}
private void pictureBox_MouseMove(object sender, MouseEventArgs e)
{
if(e.Button==MouseButtons.Left)
{
isDrag = true;
rect.Location = getPointToForm(new Point(e.Location.X - oldLocation.X,e.Location.Y - oldLocation.Y));
this.Refresh();
}
}
private void reset()
{
mouseDownPoint = Point.Empty;
rect = Rectangle.Empty;
isDrag = false;
}
private void pictureBox_MouseUp(object sender, MouseEventArgs e)
{
oldLocation = new Point(currentPictureBox.Location.X, currentPictureBox.Location.Y);
if(oldLocation.X+e.X>600||oldLocation.Y+e.Y>600||oldLocation.X+e.X<0||oldLocation.Y+e.Y<0)
{
return;
}
haveToPictureBox = GetPictureBoxByLocation(oldLocation.X + e.X, oldLocation.Y + e.Y );
newLocation = new Point(haveToPictureBox.Location.X, haveToPictureBox.Location.Y);
haveToPictureBox.Location = oldLocation;
PictureMouseUp(currentPictureBox,sender ,e);
if(Judge())
{
if (rad_true.Checked)
{
timer1.Stop();
MessageBox.Show("挑戰(zhàn)成功!");
second = 0;
txt_time.Text = "";
InitGame();
}
else
{
timer1.Stop();
MessageBox.Show("成功!");
second = 0;
txt_time2.Text = "";
txt_step.Text = "";
InitGame();
}
}
}
private void PictureMouseUp(PictureBox pic, object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
if(isDrag)
{
isDrag = false;
pic.Location = newLocation;
count++;
if (rad_false.Checked) txt_step.Text = count.ToString();
this.Refresh();
}
reset();
}
}
public bool Judge()
{
bool result = true;
int i = 0;
foreach(PictureBox item in pictureList)
{
if(item.Location!=pointList[i])
{
result = false;
}
i++;
}
return result;
}
private void Btn_import_Click(object sender, EventArgs e)
{
OpenFileDialog new_picture = new OpenFileDialog();
if (new_picture.ShowDialog()==DialogResult.OK)
{
//lab_result.Text = "";
}
originalpicpath = new_picture.FileName;
CutPicture.PicturePath = new_picture.FileName;
Flow(CutPicture.PicturePath, true);
}
private void Btn_Changepic_Click(object sender, EventArgs e)
{
Random r = new Random();
int i = r.Next(6);
originalpicpath = Application.StartupPath.ToString() + "\\Picture\\" + i.ToString() + ".jpg";
Flow(originalpicpath, true);
}
private void Btn_Reset_Click(object sender, EventArgs e)
{
Flow(originalpicpath, true);
second = 0;
txt_time.Text = "";
}
private void Btn_Originalpic_Click(object sender, EventArgs e)
{
Form_Original original = new Form_Original();
original.picpath = originalpicpath;
original.ShowDialog();
}
private void Label1_Click(object sender, EventArgs e)
{
}
private void Button1_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
}
private void Timer1_Tick(object sender, EventArgs e)
{
if (rad_true.Checked)
{
//second = 0;
second--;
txt_time.Text = (dif+second).ToString();
if (dif+second == 0)
{
timer1.Stop();
MessageBox.Show("挑戰(zhàn)失??!");
second = 0;
txt_time.Text = "";
//txt_time2.Text = "";
InitGame();
}
}
else if (rad_false.Checked)
{
//second = 0;
second++;
txt_time2.Text = second.ToString();
}
}
private void Rad_false_CheckedChanged(object sender, EventArgs e)
{
//timer1.Enabled = true;
}
private void Rad_true_CheckedChanged(object sender, EventArgs e)
{
option.Text = "簡(jiǎn)單";
//timer1.Enabled = true;
}
private void Btn_start_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
}
private void NumericUpDown1_ValueChanged(object sender, EventArgs e)
{
}
private void Option_SelectedIndexChanged(object sender, EventArgs e)
{
if (option.Text == "簡(jiǎn)單")
{
dif = 10;
numericUpDown1.Value = 2;
Flow(originalpicpath, true);
}
if (option.Text == "一般")
{
dif = 30;
numericUpDown1.Value = 4;
Flow(originalpicpath, true);
}
if (option.Text == "困難")
{
dif = 60;
numericUpDown1.Value = 6;
Flow(originalpicpath, true);
}
}
}
}
Form_Original.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace myPuzzle
{
public partial class Form_Original : Form
{
public string picpath;
public Form_Original()
{
InitializeComponent();
}
private void Form_original_Load(object sender, EventArgs e)
{
//pb_Original.Image = CutPicture.Resize(picpath, 600, 600);
}
private void Form_Original_Load_1(object sender, EventArgs e)
{
pb_Original.Image = CutPicture.Resize(picpath, 600, 600);
}
}
}