Hãy đăng kí để sử dụng hết chức năng của thư viện. VTTML sưu tầm những bài viết hay từ cộng đồng mạng và tập hợp thành những chuyên mục để giúp chọn lọc và có thể giúp ích các bạn dể dàng tìm kiếm.
Hãy đăng kí để sử dụng hết chức năng của thư viện. VTTML sưu tầm những bài viết hay từ cộng đồng mạng và tập hợp thành những chuyên mục để giúp chọn lọc và có thể giúp ích các bạn dể dàng tìm kiếm.
Bạn có muốn phản ứng với tin nhắn này? Vui lòng đăng ký diễn đàn trong một vài cú nhấp chuột hoặc đăng nhập để tiếp tục.



 
Trang ChínhXEM NHANHTìm kiếmLatest imagesĐăng kýĐăng Nhập

 

  [C#] Viết chương trình ghép hình đơn giản

Go down 
Tác giảThông điệp
dokylan
Đại Tướng



Posts : 1456
Điểm Số : 4289
Join date : 24/08/2010
Age : 32
Đến từ : Cà Mau

 [C#] Viết chương trình ghép hình đơn giản Empty
Bài gửiTiêu đề: [C#] Viết chương trình ghép hình đơn giản    [C#] Viết chương trình ghép hình đơn giản Empty18/09/10, 04:59 pm

 [C#] Viết chương trình ghép hình đơn giản Ghephinh1
I) Giới thiệu

Đây là một trờ chơi đơn giản khá quen thuộc, để tạo được một game dạngnày đòi hỏi bạn phải có một chút kĩ năng, biết vận dụng những kiến thứcC# và thuật toán căn bản.
Trò chơi là một khung ảnh hình vuông bao gồm các ảnh nhỏ ghép lại và một ô trống để bạn có thể di chuyển các ô khác.
Luật chơi khá đơn giản, bạn chỉ cần sắp xếp các ô vuông hình (đã bị xáotrộn) về lại hình ban đầu. Để sắp xếp bạn chỉ được di chuyển các ôvuông này theo 4 hướng (N-E-W-S) bằng cách thế với vị trí ô trống (ô cómàu gray trong hình).
Thoạt nhìn bạn có thể hơi phức tạp, tuy nhiên bạn sẽ thấy nó khá dễ dàng sau khi đọc và hiểu hướng dẫn cách làm sau đây.
I) Phân tích

Trong ví dụ này bạn có thể đoán được là ta sẽ tạo một mảng cácPictureBox để chứa các phần ảnh nhỏ của bức ảnh lớn. Ngoài ra, bạn sẽphải dùng một phương pháp nào đó để trộn các khung ảnh nhỏ này. Ở đâybạn có thể trộn theo một quy luật nào đó, lẽ dĩ nhiên điều này làm chotrò chơi trở nên kém hấp dẫn nếu chơi lại những lần sau. Vì thế có lẽtốt hơn ta sẽ dùng cách trộn ngẫu nhiên.
Để di chuyển các khung ảnh nhỏ (từ đây ta sẽ gọi tắt là khung ảnh) trò chơi sẽ cung cấp 2 cách thức: một là nhấn vào mũi tên tương ứng trên form, hai là sử dụng 4 nút mũi tên trên bàn phím.
Với bước kiểm tra xem người chơi đã sắp xếp hoàn thành chưa, cách đơngiản nhất là lặp qua mảng các khung ảnh và so sánh vị trí của nó với vịtrí chính xác lẽ ra nó phải đứng. Bạn có thể dùng một mảng số để lưu vịtrí các khung ảnh này lại, tuy nhiên tại sao ta lại không tận dụngthuộc tính tagcủa đối tượng để lưu nhỉ. Bạn có thể chọn lựa 1 trong 2 cách này hoặccách thứ 3 nếu bạn thích, tuy nhiên trong bài này ta sẽ lưu trong tag.
II) Thiết kế:

1) Giao diện:

Bạn đã tìm hiểu sơ qua cách thức hoạt động của chương trình. Bây giờbạn hãy bắt tay thực hiện bằng cách mở một IDE hỗ trợ lập trình C# vàtạo giao diện như trên.
Mô tả chức năng các control:
-mnOpen (Mở file ảnh) : load file ảnh từ đĩa vào chương trình.
-mnStart (Bắt đầu) :Tiến hành xáo trộn các khung ảnh để bắt đầu
-mnReset (Chơi lại) : Khôi phục các khung ảnh về vị trí ban đầu.
-Các mũi tên trên form là các Label tương ứng với các hướng di chuyển
2) Viết mã nguồn:

Trước hết hãy đọc và cố gắng nhớ những biến sau để chắc rằng bạn khôngphải quay lại tra lý lịch khi bắt gặp chúng xuất hiện đâu đó trên conđường bằng phẳng bạn sắp đi tới.



///
/// ảnh gốc
///

private Bitmap ImageFile;
///
/// Kích thước của 1 khung ảnh
///

private int cellSize;
///
/// Số lượng khung hình theo chiều ngang và dọc của khung hình lớn(hình vuông)
///

private const int CELL_COUNT = 5;
///
/// Vị trí của khung hình trống
///

private int emptyCellIndex = CELL_COUNT * CELL_COUNT – 1;
///
/// Mảng các khung hình
///

private PictureBox[] picCell = new PictureBox[CELL_COUNT * CELL_COUNT];
Tôi thường có thói quen cho các thuộc tính này lên đầu lớp và bao chúng lại với tên Properties, vậy nếu bạn đã nhớ chúng rồi thì hãy thêm 2 dòng in đậm sau vào trước và sau đoạn mã trên:
#region Properties
// ….
#endregion

Trong chương trình này bạn phải dùng một Panel để chứa các khung ảnh, hãy tạo ra các khung ảnh của bạn và thêm chúng vào panel



for (int i = 0; i < picCell.Length; i++)
{
picCell[i] = new PictureBox();
panelPicture.Controls.Add(picCell[i]);
}



Chúng ta sẽ tiếp tục bằng hàm load ảnh từ file vào các khung ảnh, hãy xem đoạn mã sau

///
/// Nạp ảnh từ file, tính toán kích thước và phân chia ảnh
///

///
void LoadPicture(string fileName)
{
if (!System.IO.File.Exists(fileName))
{
MessageBox.Show(“Không tìm thấy file \n” + fileName);
return;
}
try
{
mnStart.Enabled = true;
mnReset.Enabled = true;
// Tạo ảnh bitmap từ file
Bitmap bmp = new Bitmap(fileName);
// Kích thước lớn nhất của ảnh (width , height)
float maxSize;
float width,height;
maxSize = bmp.Size.Width > bmp.Size.Height ? bmp.Size.Width : bmp.Size.Height;
// Lấy kích thước ảnh
width = bmp.Size.Width;
height = bmp.Size.Height;
// hệ số để tăng giảm kích thước ảnh cho phù hợp
float heso=350/maxSize;

if (heso > 0)
{
// Thay đổi kích thước ảnh
width *= heso;
height *= heso;
}

// Nạp ảnh vào với kích thước mới được tính toán
ImageFile = new Bitmap(bmp,new Size((int)width,(int)height));

// Lấy kích thước lớn nhất của ảnh dựa vào chiều cao và chiều rộng
int imageSize = (ImageFile.Width < ImageFile.Height) ? ImageFile.Width : ImageFile.Height;
// Cắt ảnh cho vừa với số lượng khung hình
imageSize = imageSize – imageSize % CELL_COUNT;
// Tính độ rộng của 1 khung ảnh (khung ảnh có dạng hình vuông)
cellSize = imageSize / CELL_COUNT;
// Hiển thị các khung ảnh
mnReset_Click(null, null);

// Tính kích thước của panel chứa các khung ảnh
int size = cellSize * CELL_COUNT;
panelPicture.Size = new Size(size, size);
// Thay đổi kích thước form theo kích thước ảnh
this.Size = new Size(size+200, size+100);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}

Các đoạn code tôi đã chú thích khá chi tiết nên có lẽ không cần giảithích nhiều, tuy nhiên nếu bạn suy nghĩ và đặt ra 1 câu hỏi nào đó,biết đâu nó có thể giúp chúng ta phát hiện ra vài điều lý thú ở đây.

Tiếp đến chúng ta sẽ viết lệnh để cắt bức ảnh gốc thành các khung ảnhnhỏ và thêm vào các PictureBox. Chúng ta sẽ cho thao tác này vào mnReset
// Khôi phục vị trí các khung ảnh về trạng thái ban đầu
private void mnReset_Click(object sender, EventArgs e)
{
// Phương pháp:
// cắt file ảnh gốc ra thành các phần nhỏ
// mỗi phần cho vào một khung ảnh (pictureBox)
// Xếp vị trí của khung ảnh trên form
// sử dụng thuộc tính tag của PictureBox để lưu lại số thứ tự (index) của khung ảnh
// Số thứ tự xác định vị trí thật sự của khung ảnh
// và là cơ sở để kiểm tra xem người chơi có xếp đúng vị trí ko
if (ImageFile != null)
{
// Số thự tự các khung ảnh
int cellIndex = 0;
for (int j = 0; j < CELL_COUNT; j++)
{
for (int i = 0; i < CELL_COUNT; i++)
{
try
{
// Tạo khung hình chữ nhật để cắt ảnh từ file ảnh gốc
// có vị trí cắt từ cột i dòng j
// và kích thước bằng với khung ảnh (cellSize)
Rectangle imageRect = new Rectangle(i * cellSize, j * cellSize, cellSize, cellSize);
// Xóa ảnh cũ của khung ảnh
picCell[cellIndex].Image = null;
// Không gán ảnh vào khung ảnh cuối cùng (khung ảnh trống dùng để di chuyển)
if (cellIndex != picCell.Length – 1)
// Gán ảnh vào khung ảnh, hàm Clone của đối tượng Bitmap sẽ cắt ra một phần
// ảnh dựa vào vị trí và kích thước khung chữ nhật ta truyền vào
picCell[cellIndex].Image = ImageFile.Clone(imageRect, PixelFormat.DontCare);
// Xếp vị trí cho khung ảnh, bằng vị trí cột, dòng
picCell[cellIndex].Location = new Point( i * cellSize, j * cellSize + 1);
// Tăng kích thước khung ảnh lên 1 để có đường biên giữa các khung ảnh
picCell[cellIndex].Size = new Size(cellSize + 1, cellSize + 1);
// Lưu số thứ tự của khung ảnh lại
picCell[cellIndex].Tag = cellIndex.ToString();
// Tăng số thứ tự
cellIndex++;
}
catch (Exception)
{
}
}
}
}

mnStart.Enabled = true;

// khung ảnh trống có vị trí cuối cùng
emptyCellIndex = CELL_COUNT * CELL_COUNT – 1;

}

Để hoán đổi vị trí các bức ảnh ta dùng cách hoán vị thuộc tính Image vàTag của hai PictureBox, như vậy các PictureBox vẫn giữ nguyên vị tríindex trên panel, chỉ có index trong Tag thay đổi. Ở đây ta cho vàotrong sự kiện của mnStart
// xáo trộn ngẫu nhiên vị trí các khung ảnh
private void mnStart_Click(object sender, EventArgs e)
{
mnStart.Enabled = false;
mnReset.Enabled = true;
// đối tượng bitmap tạm dùng cho việc hoán vị 2 khung ảnh
Bitmap bmp;

Random rnd = new Random();
// giá trị random lớn nhất bằng tổng số khung ảnh -1
// để ko xét đến khung ảnh trống
int maxValue = CELL_COUNT * CELL_COUNT-1;
// số lần xáo trộn khung ảnh = maxValue
for (int i = 0; i < maxValue; i++)
{
// index của khung ảnh nguồn và đích sẽ hoán vị
int indexSource = rnd.Next(maxValue);
int indexDest = rnd.Next(maxValue);
// nếu bằng nhau thì bỏ qua
if (indexSource == indexDest)
continue;

try
{
// lưu lại ảnh của khung ảnh nguồn
bmp = (Bitmap)picCell[indexSource].Image;
// lưu tag của khung ảnh nguồn
bmp.Tag= picCell[indexSource].Tag.ToString();

// bắt đầu hoán vị 2 khung ảnh
picCell[indexSource].Image = picCell[indexDest].Image;
picCell[indexSource].Tag = picCell[indexDest].Tag;
picCell[indexDest].Image = bmp;
picCell[indexDest].Tag = bmp.Tag;
}
catch (Exception)
{
}
}
}
Với phần mã để di chuyển các khung ảnh, bạn chỉ cần làm tương tự nhưphần hoán vị ảnh bên trên. Ví dụ khi người chơi nhấn mũi tên xuống thìcông việc ta phải bắt chương trình làm là lấy vị trí khung ảnh phíatrên ô trống và hoán vị nó với ô trống, tương tự với các hướng còn lại.
Để tạo phím tắt khi người chơi sử dụng bàn phím, bạn hãy override hàm ProcessDialogKey của đối tượng Form, phần lệnh đó có thể trông tương tự như sau:

protected override bool ProcessDialogKey(Keys keyData)
{
if (keyData == Keys.Up)
lblMove_Click(lblUp, EventArgs.Empty);
else if(keyData==Keys.Down)
lblMove_Click(lblDown, EventArgs.Empty);
else if (keyData == Keys.Left)
lblMove_Click(lblLeft, EventArgs.Empty);
else if (keyData == Keys.Right)
lblMove_Click(lblRight, EventArgs.Empty);

return base.ProcessDialogKey(keyData);
}

Để xác định hướng di chuyển khi người dùng nhấn phím, bạn hãy tạo ra một enum có tên là Direction với 4 hướng di chuyển.

public enum Direction { Left, Right, Up, Down };

Nhiều người có thói quen sử dụng sử dụng biến kiểu int hoặc string chocác mục đích dạng này, nhưng để là chương trình trong sáng và dễ dàngthay đổi, tốt nhất bạn hãy tạo 1 enum như trên.
Bạn cũng cần chú ý đến việc kiểm tra tính hợp lệ của việc di chuyển.Chẳng hạn nếu như ô trống ở hàng trên cùng thì hãy chắc chắn rằng việcngười dùng nhấn mũi tên xuống không ném vào mắt họ một ngoại lệ nào đó.

Mọi việc có vẻ như đã hoàn tất, chúng ta sẽ kết thúc phần hướng dẫnthiết kế này bằng hàm kiểm tra người chơi đã sắp xếp xong chưa. Hàm nàykhông phức tạp và bạn có thể tự viết lấy. Với mỗi nước di chuyển củangười chơi, đừng bỏ lỡ việc kiểm tra họ đã sắp xếp hoàn thành bức tranhchưa.

///
/// Hàm kiểm tra thắng
///

///
private bool CheckFinish()
{
for (int i = 0; i < picCell.Length; i++)
{
// Nếu có ít nhất 1 ảnh sai ít nhất vị trí thì trả về fasle
if (picCell[i].Tag.ToString() != i.ToString())
return false;
}
return true;
}
I)Phần kết

Thật thú vị là bạn có thể dễ dàng tạo cho mình một trò chơi có ích vàhấp dẫn, nếu sử dụng một chút sáng tạo, bạn có thể làm cho trò chơithêm phần hấp dẫn bằng các tính năng cơ bản khác như cho phép thay đổikích thước, số lượng khung ảnh, đếm giờ, lưu số điểm cao nhất…
Trong dịp tới, tôi sẽ trình bày cách tạo một trò chơi ghép ảnh khácbằng cách dùng chuột kéo thả. Và như bạn có thể đoán, cách thực hiện nócũng bắt nguồn từ trò chơi này.

nguồn: vn-zoom
Về Đầu Trang Go down
http://vttml.cdrom.tv
 
[C#] Viết chương trình ghép hình đơn giản
Về Đầu Trang 
Trang 1 trong tổng số 1 trang
 Similar topics
-
» Chương trình C# đơn giản
» Phần mềm đóng gói chương trình viết bằng Java thành file exe
» Hiren's BootCD 15.0 'lên đời' hàng loạt chương trình
» Shadow Defender 1.1.0.275 - Chương trình đóng băng máy tính
» Chương trình tạo Flash dành cho người không chuyên

Permissions in this forum:Bạn không có quyền trả lời bài viết
 :: Góc Học Tập :: Lập Trình :: C#-
Chuyển đến