Tài liệu Lập trình hướng đối tượng - Bài thực hành số 0.1: Viết chương trình giải phương trình bậc 2: Trang 1 
MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG 
Bài thực hành số 0.1 : Viết chương trình giải phương trình bậc 2 
I. Mục tiêu : 
 Giúp SV ôn lại qui trình viết 1 ứng dụng VC# ₫ơn giản, hệ thống lại các vấn ₫ề chính 
của phần mềm này, ₫ể các chương còn lại giải quyết chúng. 
II. Nội dung : 
 Xây dựng chương trình nhỏ giải phương trình bậc 2 có dạng ax^2 + bx + c = 0 chạy ở 
chế ₫ộ textmode (console). 
III. Chuẩn ₫ầu ra : 
 Sinh viên nắm vững và viết thành thạo các ứng dụng nhỏ chạy ở chế ₫ộ textmode. 
IV. Qui trình : 
1. Chạy VS .Net, chọn menu File.New.Project ₫ể hiển thị cửa sổ New Project. 
2. Mở rộng mục Visual C# trong TreeView "Project Types", chọn mục Windows, chọn icon 
"Console Application" trong listbox "Templates" bên phải, thiết lập thư mục chứa Project 
trong listbox "Location", nhập tên Project vào textbox "Name:" (td. GPTB2), click button 
OK ₫ể tạo Project theo các thông số ₫ã khai báo. 
3. Ngay sau khi Project vừa ₫ược tạo ra, cửa sổ soạn code cho chương t...
                
              
                                            
                                
            
 
            
                 150 trang
150 trang | 
Chia sẻ: Khủng Long | Lượt xem: 1498 | Lượt tải: 0 
              
            Bạn đang xem trước 20 trang mẫu tài liệu Lập trình hướng đối tượng - Bài thực hành số 0.1: Viết chương trình giải phương trình bậc 2, để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên
Trang 1 
MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG 
Bài thực hành số 0.1 : Viết chương trình giải phương trình bậc 2 
I. Mục tiêu : 
 Giúp SV ôn lại qui trình viết 1 ứng dụng VC# ₫ơn giản, hệ thống lại các vấn ₫ề chính 
của phần mềm này, ₫ể các chương còn lại giải quyết chúng. 
II. Nội dung : 
 Xây dựng chương trình nhỏ giải phương trình bậc 2 có dạng ax^2 + bx + c = 0 chạy ở 
chế ₫ộ textmode (console). 
III. Chuẩn ₫ầu ra : 
 Sinh viên nắm vững và viết thành thạo các ứng dụng nhỏ chạy ở chế ₫ộ textmode. 
IV. Qui trình : 
1. Chạy VS .Net, chọn menu File.New.Project ₫ể hiển thị cửa sổ New Project. 
2. Mở rộng mục Visual C# trong TreeView "Project Types", chọn mục Windows, chọn icon 
"Console Application" trong listbox "Templates" bên phải, thiết lập thư mục chứa Project 
trong listbox "Location", nhập tên Project vào textbox "Name:" (td. GPTB2), click button 
OK ₫ể tạo Project theo các thông số ₫ã khai báo. 
3. Ngay sau khi Project vừa ₫ược tạo ra, cửa sổ soạn code cho chương trình ₫ược hiển thị. 
Hiệu chỉnh code của file Program.cs ₫ể có nội dung như sau : 
using System; 
namespace GPTB2 { 
 class Program { 
 //₫ịnh nghĩa các biến cần dùng 
 static double a, b, c; 
 static double delta; 
 static double x1, x2; 
 //₫ịnh nghĩa hàm nhập 3 thông số a,b,c của phương trình bậc 2 
 static void NhapABC() { 
 String buf; 
 Console.Write("Nhập a : "); buf= Console.ReadLine(); 
 a = Double.Parse(buf); 
 Console.Write("Nhập b : "); buf = Console.ReadLine(); 
 b = Double.Parse(buf); 
 Console.Write("Nhập c : "); buf = Console.ReadLine(); 
 c = Double.Parse(buf); 
 } 
 //₫ịnh nghĩa hàm tính nghiệm của phương trình bậc 2 
 static void GiaiPT() { 
 //tính biệt số delta của phương trình 
 delta = b * b - 4 * a * c; 
 if (delta >= 0) //nếu có nghiệm thực 
 { 
 x1 = (-b + Math.Sqrt(delta)) / 2 / a; 
 x2 = (-b - Math.Sqrt(delta)) / 2 / a; 
 } 
 } 
Trang 2 
 //₫ịnh nghĩa hàm xuất kết quả 
 static void XuatKetqua() { 
 if (delta < 0) 
 //báo vô nghiệm 
 Console.WriteLine("Phương trình vô nghiệm"); 
 else //báo có 2 nghiệm 
 { 
 Console.WriteLine("Phương trình có 2 nghiệm thực : "); 
 Console.WriteLine("X1 = " + x1); 
 Console.WriteLine("X2 = " + x2); 
 } 
 } 
 //₫ịnh nghĩa chương trình (hàm Main) 
 static void Main(string[] args) { 
 NhapABC(); //nhập a,b,c 
 GiaiPT(); //giải phương trình 
 XuatKetqua(); //xuất kết quả 
 //chờ người dùng ấn Enter ₫ể ₫óng cửa sổ Console lại. 
 Console.Write("Ấn Enter ₫ể dừng chương trình : "); 
 Console.Read(); 
 } 
 } //kết thúc class 
} //kết thúc namespace 
4. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Hãy thử nhập 1 bộ ba 
(a,b,c) của phương trình bậc 2 nào ₫ó ₫ể chương trình giải và xem kết quả có ₫úng 
không. 
5. Lặp lại bước 4 cho nhiều phương trình bậc 2 khác nhau. Hãy thử nhập a = 0 xem chương 
trình phản ứng thế nào ? Nếu chương trình bị lỗi, hãy phân tích và xác ₫ịnh lỗi rồi tìm 
cách sửa lỗi ₫ể chương trình có thể xử lý ₫úng trường hợp người dùng nhập a = 0. 
Trang 1 
MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG 
Bài thực hành số 0.2 : Viết chương trình thực hiện giải thuật lặp 
I. Mục tiêu : 
 Giúp SV ôn lại qui trình viết 1 ứng dụng VC# ₫ơn giản, hệ thống lại các vấn ₫ề chính 
của phần mềm này, ₫ể các chương còn lại giải quyết chúng. 
II. Nội dung : 
 Xây dựng chương trình nhỏ chạy ở chế ₫ộ textmode (console), tính 3 hàm số theo 
công thức lặp sau ₫ây : 
S1(x) = 1 + x + x2/2! + x3/3! + ... + xn/n! 
S2(x) = 1 - x + x2/2! - x3/3! + ... + (-1)nxn/n! 
S3(x) = 1 + sin(x) + sin(2x) + ... + sin(nx) 
III. Chuẩn ₫ầu ra : 
 Sinh viên nắm vững và viết thành thạo các ứng dụng nhỏ chạy ở chế ₫ộ textmode. 
IV. Phân tích : 
Điểm chung của 3 hàm S1, S2, S3 là dùng cùng công thức lặp có dạng sau : 
S(x) = 1 + ∑∞
=1n
ne 
trong ₫ó mỗi thành phần en phụ thuộc vào x và n, en thường nhỏ dần khi n tăng lên ₫ến khi ₫ủ 
nhỏ (nhỏ hơn sai số epsilon qui ₫ịnh) thì ta bỏ ₫i : 
- ₫ối với S1(x) thì en = xn/n! 
- ₫ối với S2(x) thì en = (-1)nxn/n! 
- ₫ối với S3(x) thì en = sin(nx) 
Thuật giải lặp ₫ể tính công thức trên gồm các bước sau : 
1. Lúc ₫ầu, thiết lập S = 1 và n = 1 
2. Tính en, tích lũy en vào S. 
3. Kiểm tra en < epsilon. Nếu thỏa thì dừng, nếu không thì tăng n 1 ₫ơn vị và thực hiện lại 
bước 2. 
Lập trình chẳng qua là dịch thuật giải ở dạng ngôn ngữ tự nhiên thành ngôn ngữ lập trình cho 
máy hiểu và thực thi tự ₫ộng dùm con người khi cần. Sau ₫ây là qui trình ₫iển hình ₫ể viết 
chương trình nhỏ thực hiện 3 công thức lặp trên bằng VC# : 
V. Qui trình : 
1. Chạy VS .Net, chọn menu File.New.Project ₫ể hiển thị cửa sổ New Project. 
2. Mở rộng mục Visual C# trong TreeView "Project Types", chọn mục Windows, chọn icon 
"Console Application" trong listbox "Templates" bên phải, thiết lập thư mục chứa Project 
trong listbox "Location", nhập tên Project vào textbox "Name:" (td. TínhLap), click button 
OK ₫ể tạo Project theo các thông số ₫ã khai báo. 
3. Ngay sau khi Project vừa ₫ược tạo ra, cửa sổ soạn code cho chương trình ₫ược hiển thị. 
Hiệu chỉnh code của file Program.cs ₫ể có nội dung như sau : 
using System; 
using System.Collections.Generic; 
using System.Text; 
namespace TinhLap 
{ 
Trang 2 
 class Program 
 { 
 //₫ịnh nghĩa hằng gợi nhớ miêu tả sai số mong muốn 
 const double EPSILON = 0.0000001; 
 //₫ịnh nghĩa hàm tính n! 
 static long giaithua(int n) 
 { 
 if (n <= 1) return 1; 
 return n*giaithua(n-1); 
 } 
 //₫ịnh nghĩa hàm tính thành phần x^n/n! 
 static double EnS1(double x, int n) 
 { 
 return (Math.Pow(x,n))/giaithua(n); 
 } 
 //₫ịnh nghĩa hàm tính công thức S1(x) 
 static double S1(double x) 
 { 
 //1. Lúc ₫ầu, thiết lập S = 1 và n = 1 
 double S = 1; 
 int n = 1; 
 double En; 
 do { 
 //2. Tính En, tích lũy En vào S 
 En = EnS1(x,n); 
 S = S + En; 
 n++; 
 } while (Math.Abs(En) >= EPSILON); //3. Lặp bước 2 nếu En >= epsilon 
 //gởi kết quả về lệnh gọi hàm này 
 return S; 
 } 
 //₫ịnh nghĩa hàm tính thành phần (-1)^nx^n/n! 
 static double EnS2(double x, int n) 
 { 
 return Math.Pow(-1,n)*Math.Pow(x,n)/giaithua(n); 
 } 
 //₫ịnh nghĩa hàm tính công thức S2(x) 
 static double S2(double x) 
 { 
 //1. Lúc ₫ầu, thiết lập S = 1 và n = 1 
 double S = 1; 
 int n = 1; 
 double En; 
 do { 
 //2. Tính En, tích lũy En vào S 
Trang 3 
 En = EnS2(x,n); 
 S = S + En; 
 n = n + 1; 
 } while (Math.Abs(En) >= EPSILON); //3. Lặp bước 2 nếu En >= epsilon 
 //gởi kết quả về lệnh gọi hàm này 
 return S; 
 } 
 //₫ịnh nghĩa hàm tính công thức S3(x) 
 static double S3(double x) 
 { 
 //1. Lúc ₫ầu, thiết lập S = 1 và n = 1 
 double S = 1; 
 int n = 1; 
 double En; 
 do { 
 //2. Tính En, tích lũy En vào S 
 En = Math.Sin(n*x); 
 S = S + En; 
 n++; 
 } while (Math.Abs(En) >= EPSILON); //3. Lặp bước 2 nếu En >= epsilon 
 //gởi kết quả về lệnh gọi hàm này 
 return S; 
 } 
 //chương trình chính thử dùng các hàm ₫ược viết 
 static void Main(string[] args) 
 { 
 double x; 
 String buf; 
 //yêu cầu người dùng nhập x 
 Console.Write("Nhập x : "); buf = Console.ReadLine(); 
 x = Double.Parse(buf); 
 //gọi thử hàm S1(x) 
 Console.WriteLine("S1(" + x + ")= "+ S1(x)); 
 //gọi thử hàm S2(x) 
 Console.WriteLine("S2(" + x + ")= " + S2(x)); 
 //gọi thử hàm S3(x) 
 Console.WriteLine("S3(" + x + ")= " + S3(x)); 
 } 
 } 
} 
4. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Hãy thử nhập 1 giá trị x 
nào ₫ó (nằm trong miền hội tự của hàm) ₫ể chương trình tính 3 hàm S1(x), S2(x), S3(x) 
hiển thị kết quả. 
5. Lặp lại bước 4 cho nhiều giá trị x khác nhau và kiếm tra xem chương trình chạy ₫úng 
không. 
Trang 1 
MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG 
Bài thực hành số 0.3 : Viết chương trình xử lý ₫a thức 
I. Mục tiêu : 
 Giúp SV ôn lại qui trình viết 1 ứng dụng VC# ₫ơn giản, tập trung vào việc sử dụng các 
kiểu dữ liệu cơ bản ₫ịnh sẵn. 
II. Nội dung : 
 Xây dựng chương trình nhỏ chạy ở chế ₫ộ textmode (console), thực hiện các yêu cầu 
sau : 
1. miêu tả kiểu ₫ể lưu giữ từng toán hạng của ₫a thức gồm 2 thông tin : hệ số 
và số mũ. 
2. sắp xếp danh sách các toán hạng của ₫a thức theo thứ tự giảm dần của số 
mũ, phương pháp sắp xếp là Insertion Sort. 
3. chuẩn hóa ₫a thức : mỗi số mũ chỉ xuất hiện trong ₫a thức 1 lần. 
Thí dụ có ₫a thức gốc R(x)= x^3 + x^2 + x + 2x^2 + 2x + 2 
sau khi chuẩn hóa thành R(x)= x^3 + 3x^2 + 3x + 2 
4. Nhân 2 ₫a thức. 
III. Chuẩn ₫ầu ra : 
 Sinh viên nắm vững và viết thành thạo các ứng dụng nhỏ chạy ở chế ₫ộ textmode và 
biết cách dùng các kiễu dữ liệu cơ bản ₫ịnh sẵn khi cần. 
IV. Phân tích : 
1. Ta dùng kiểu struct ₫ể miêu tả thông tin về mỗi số hạng của ₫a thức như sau : 
struct Sohang { 
 public int somu; //số mũ 
 public float heso; //hệ số 
}; 
2. Ý tưởng sắp xếp danh sách theo giải thuật "Insertion Sort" như sau : 
Lặp xác ₫ịnh vị trí ₫úng cho từng số hạng i (từ 0 tới n) của ₫a thức : 
 - Lặp tìm số hạng có số mũ lớn nhất từ vị trí i tới n 
 - Hoán vị nó với số hạng i 
Từ thuật giải ₫ược viết bằng ngôn ngữ tự nhiên ở trên, ta sẽ dịch nó thành hàm SortItems() 
₫ược viết bằng VC# như trong mã nguồn dưới ₫ây. 
3. Chuẩn hóa ₫a thức : ₫ược thực hiện thông qua 2 bước chính : 
- sắp xếp ₫a thức theo thứ tự số mũ giảm dần (gọi hàm SortItems() ở bước 2). 
- duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng các số hạng liên tiếp có cùng số mũ lại 
thành 1 số hạng. 
Từ thuật giải ₫ược viết bằng ngôn ngữ tự nhiên ở trên, ta dịch nó thành hàm Chuanhoa() 
₫ược viết bằng VC# như trong mã nguồn dưới ₫ây. 
4. Nhân ₫a thức : ₫ược thực hiện thông qua 2 bước chính : 
- lặp nhân từng số hạng của ₫a thức 1 với tất cả các số hạng của ₫a thức 2. Kết quả 
₫ược lưu vào ₫a thức kết quả. 
- Chuẩn hóa ₫a thức kết quả. 
Trang 2 
Từ thuật giải ₫ược viết bằng ngôn ngữ tự nhiên ở trên, ta dịch nó thành hàm Nhan() ₫ược viết 
bằng VC# như trong mã nguồn dưới ₫ây. 
V. Qui trình : 
1. Chạy VS .Net, chọn menu File.New.Project ₫ể hiển thị cửa sổ New Project. 
2. Mở rộng mục Visual C# trong TreeView "Project Types", chọn mục Windows, chọn icon 
"Console Application" trong listbox "Templates" bên phải, thiết lập thư mục chứa Project 
trong listbox "Location", nhập tên Project vào textbox "Name:" (td. Dathuc), click button 
OK ₫ể tạo Project theo các thông số ₫ã khai báo. 
3. Ngay sau khi Project vừa ₫ược tạo ra, cửa sổ soạn code cho chương trình ₫ược hiển thị. 
Hiệu chỉnh code của file Program.cs ₫ể có nội dung như sau : 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
namespace Dathuc { 
class Program { 
//₫ịnh nghĩa kiểu miêu tả 1 số mũ 
private struct Sohang { 
 public float heso; //hệ số 
 public int somu; //số mũ 
 public Sohang(float h, int s) { heso = h; somu = s; } 
}; 
//hàm sắp xếp ₫a thức theo thứ tự số mũ giảm dần 
static void SortItems (Sohang[] dathuc, int soluong) { 
//₫ịnh nghĩa các biến cần dùng 
int i,j, max; 
Sohang temp; 
 //Lặp xác ₫ịnh vị trí ₫úng cho từ số mũ 
 for (i = 0; i < soluong-1; i++) { 
 //Tìm phần tử có số mũ lớn nhất từ vị trí i 
 max = i; 
 for (j = i + 1; j < soluong; j++) 
 if (dathuc[max].somu < dathuc[j].somu) 
 max = j; 
 //hoán vị phần tử có số mũ lớn nhất về vị trí i 
 temp = dathuc[i]; 
 dathuc[i] = dathuc[max]; 
 dathuc[max] = temp; 
 } 
} 
//hàm chuẩn hóa ₫a thức, mỗi số mũ chỉ có 1 phần tử 
static int Chuanhoa (Sohang[] dathuc, int soluong) { 
//₫ịnh nghĩa các biến cần dùng 
int i,j; 
Sohang[] temp = new Sohang[soluong]; 
Trang 3 
 //sắp xếp thự tự các phần tử trong ₫a thức 
 SortItems(dathuc,soluong); 
 //Lặp việc gộp các phần tử có số mũ giống nhau 
 j = 0; temp[0] = dathuc[0]; 
 i = 1; 
 while (i < soluong) 
 if (temp[j].somu == dathuc[i].somu) { 
 temp[j].heso += dathuc[i].heso; 
 i++; 
 } else { 
 j++; 
 temp[j] = dathuc[i]; 
 i++; 
 } 
 //copy kết quả về dathuc gốc 
 for (i =0; i <= j ; i++) 
 dathuc[i] = temp[i]; 
 //return số phần tử trong ₫a thức chuẩn hóa 
 return j+1; 
} 
//hàm in ₫a thức ₫ể kiểm tra 
static void Indathuc(Sohang[] dathuc, int soluong) { 
int i; 
 if (soluong == 0) return; 
 //in phần tử ₫ầu tiên của ₫a thức 
 Console.Write(dathuc[0].heso + "x^" + dathuc[0].somu + " "); 
 //lặp in từng phần tử còn lại của ₫a thức 
 for (i = 1; i < soluong; i++) 
 if (dathuc[i].heso <0) 
 Console.Write(dathuc[i].heso+ "x^"+ dathuc[i].somu + " "); 
 else 
 Console.Write("+ " + dathuc[i].heso + "x^"+ dathuc[i].somu + " "); 
 //in ký tự xuống dòng 
 Console.WriteLine(); 
} 
//hàm nhân 2 ₫a thức 
static void Nhan (Sohang[] dathuc1, int soluong1, Sohang[] dathuc2, int soluong2, ref 
Sohang[] dathuc3, ref int soluong3) { 
//₫ịnh nghĩa các biến cần dùng 
int i,j,k; 
 //cấp phát bộ nhớ chứa ₫a thức kết quả 
 dathuc3 = new Sohang[soluong1*soluong2]; 
 k = 0; 
 //lặp nhân từng số hạng của ₫a thức 1 
 for (i=0; i <soluong1; i++) 
 //với tất cả các số hạng của ₫a thức 2 
 for (j = 0; j <soluong2; j++) { 
 dathuc3[k].somu = dathuc1[i].somu+dathuc2[j].somu; 
Trang 4 
 dathuc3[k].heso = dathuc1[i].heso*dathuc2[j].heso; 
 k++; 
 } 
 //chuẩn hóa ₫a thức kết quả 
 soluong3 = Chuanhoa (dathuc3,k); 
} 
//chương trình chính thử dùng các hàm chức năng 
static void Main(string[] args) { 
 Sohang[] dathuc1 = new Sohang[] { new Sohang(1,3), new Sohang(1,2), new 
Sohang(1,1),new Sohang(-2,2),new Sohang(2,1),new Sohang(2,0)}; 
 //1. thử sắp xếp và in ra ₫ể kiểm tra 
 Console.WriteLine("Đa thức gốc là : "); 
 Indathuc(dathuc1,6); 
 SortItems(dathuc1,6); 
 Console.WriteLine("Đa thức ₫ược sort là : "); 
 Indathuc(dathuc1,6); 
 Sohang[] dathuc2 = new Sohang[] { new Sohang(1,3), new Sohang(1,2), new Sohang(1,1), 
new Sohang(-2,2), new Sohang(2,1),new Sohang(2,0)}; 
 //2. thử chuẩn hóa ₫a thức và in ra ₫ể kiểm tra 
 Console.WriteLine("Đa thức gốc là : "); 
 Indathuc(dathuc2,6); 
 int somu = Chuanhoa(dathuc2,6); 
 Console.WriteLine("Đa thức ₫ược chuẩn hóa là : "); 
 Indathuc(dathuc2,somu); 
 //3. thử nhân 2 ₫a thức và in ra ₫ể kiểm tra 
 Sohang[] dathuc3 = new Sohang[] { new Sohang(1,3), new Sohang(1,2), new Sohang(1,1), 
new Sohang(-2,2), new Sohang(2,1),new Sohang(2,0)}; 
 Sohang[] dathuc4 = new Sohang[] { new Sohang(1,3), new Sohang(1,2), new Sohang(1,1), 
new Sohang(-2,2), new Sohang(2,1),new Sohang(2,0)}; 
 Sohang[] dathuc5 = new Sohang[1]; 
 int soluong=1; 
 Nhan(dathuc3, 6, dathuc4, 6, ref dathuc5, ref soluong); 
 Console.WriteLine("Đa thức kết quả là : "); 
 Indathuc(dathuc5, soluong); 
 //4. chờ người dùng ấn Enter ₫ể ₫óng cửa sổ Console lại. 
 Console.Write("Ấn Enter ₫ể dừng chương trình : "); 
 Console.Read(); 
}//hết hàm Main 
}//hết class Program 
}//hết namespace 
4. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Hãy kiểm tra kết quả hiển 
thị của chương trình. 
5. Thử hiệu chỉnh lại nội dung các ₫a thức trong mã nguồn rồi chạy lại phần mềm ₫ể kiểm 
tra kết quả. 
6. Hãy suy nghĩ và hiệu chỉnh lại phần mềm ₫ể có thể nhập ₫a thức từ người dùng. 
Trang 1 
MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG 
Bài thực hành số 1.1 : Viết chương trình sắp 8 con hậu 
I. Mục tiêu : 
 Giúp SV ôn lại qui trình viết 1 ứng dụng VC# ₫ơn giản, tập trung vào việc sử dụng các 
kiểu dữ liệu cơ bản ₫ịnh sẵn như struct và array. 
II. Nội dung : 
 Xây dựng chương trình nhỏ chạy ở chế ₫ộ textmode (console), thực hiện các yêu cầu 
sau : 
1. tìm tất cả phương án ₫ể sắp 8 con hậu vào bàn cờ 8x8 ô sao cho chúng 
không thể ăn ₫ược nhau (thỏa mãn ₫ồng thời các ₫iều kiện chúng không 
trên cùng hàng, cùng cột hay cùng ₫ường chéo). 
2. in các phương án dạng ma trận 2 chiều ₫ể người dùng xem dễ dàng. 
III. Chuẩn ₫ầu ra : 
 Sinh viên nắm vững và viết thành thạo các ứng dụng nhỏ chạy ở chế ₫ộ textmode và 
biết cách dùng các kiễu dữ liệu cơ bản ₫ịnh sẵn, nhất là kiểu struct và array, khi cần. 
IV. Phân tích : 
1. Ta dùng thuật giải backtracking ₫ể tìm các phương án sắp 8 con hậu như sau : 
 + Lặp tìm vị trí con hậu ở từng cột, từ trái sang phải : 
- Nếu sắp ₫ược cho cột c thì tăng c 1 ₫ơn vị ₫ể tiếp tục cột kế tiếp, nếu cột c ₫ã vượt 
qua MAX thì ₫ã tìm ₫ược 1 cách mới. 
- Nếu không sắp ₫ược cho cột c thì giảm c 1 ₫ơn vị ₫ể thử tiếp các khả năng còn lại 
của cột cũ này. Nếu c <0 thì hết cách. 
2. Để lưu vết xử lý trên từng cột, ta dùng biến array hang[MAX], mỗi phần tử hang[c] chứa chỉ 
số hàng ₫ã xử lý lần cuối trước ₫ây (-1 : chưa, MAX : hết). 
Từ thuật giải ₫ược viết bằng ngôn ngữ tự nhiên ở trên, ta dịch nó thành chương trình ₫ược viết 
bằng VC# như trong mã nguồn dưới ₫ây. 
V. Qui trình : 
1. Chạy VS .Net, chọn menu File.New.Project ₫ể hiển thị cửa sổ New Project. 
2. Mở rộng mục Visual C# trong TreeView "Project Types", chọn mục Windows, chọn icon 
"Console Application" trong listbox "Templates" bên phải, thiết lập thư mục chứa Project 
trong listbox "Location", nhập tên Project vào textbox "Name:" (td. Sap8Conhau), click 
button OK ₫ể tạo Project theo các thông số ₫ã khai báo. 
3. Ngay sau khi Project vừa ₫ược tạo ra, cửa sổ soạn code cho chương trình ₫ược hiển thị. 
Hiệu chỉnh code của file Program.cs ₫ể có nội dung như sau : 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
namespace Sap8Conhau 
{ 
 class Program 
 { 
Trang 2 
 //₫ịnh nghĩa các thuộc tính dữ liệu 
 const int MAX = 7; //chỉ số max của hàng và cột 
 static int cachso = 0; //số cách sắp ₫ã tìm ₫ược 
 static int[] hang = new int[MAX+1]; //danh sách chỉ số hàng ₫ã thử trong từng cột 
 static int c; //vị trị cột ₫ang sắp 
 //Điểm nhập của chương trình 
 static void Main(string[] args) 
 { 
 // khởi ₫ộng trạng thái xuất phát 
 for (c = 0; c <= MAX; c++) hang[c] = -1; 
 cachso = 0; 
 //bắt ₫ầu ₫ặt con hậu ở cột 0 vào hàng 0 
 hang[0] = 0; 
 //bắt ₫ầu tìm hàng cho con hậu ở cột thứ 2 (chỉ số là 1) 
 c = 1; 
 while (Tim1cach()) 
 { 
 // tìm ₫ược cách sắp 8 con hậu 
 InKetqua(); 
 //lùi lại cột trước ₫ể tiếp tục tìm cách sắp khác 
 c--; 
 } 
 // hết cách --> dừng chương trình 
 Console.WriteLine("Số nghiệm là " + cachso); 
 //chờ người dùng ấn Enter ₫ể ₫óng cửa sổ Console lại. 
 Console.Write("Ấn Enter ₫ể dừng chương trình : "); 
 Console.Read(); 
 return; 
 } 
 //cố gắng tìm 1 phương án sắp 8 con hậu 
 static bool Tim1cach() 
 { 
 int h; 
 while (c <= MAX) 
 { 
 // tìm chỉ số hàng cho con hậu ở cột c 
 h = timhang(c); 
 if (h >= 0) 
 { //nếu tìm ₫ược 
 //lưu hàng vào danh sách kết quả rồi tăng chỉ số cột ₫ể tiếp tục 
 hang[c++] = h; 
 continue; 
 } 
 //trường hợp không tìm ₫ược hàng cho con hậu ở cột c 
 if (c > 0) 
 { 
 //nếu cột c không phải là cột ₫ầu tiên thì : 
 //xét lại cột c từ hàng ₫ầu rồi lùi cột c 
Trang 3 
 hang[c--] = -1; 
 continue; 
 } 
 //hết cách 
 return false; 
 } 
 return true; 
 }//hết hàm Tim1cach 
 //hàm cố gắng tìm chỉ số hàng cho con hậu ở cột c 
 //trả về chỉ số hàng tìm ₫ược hay -1 ₫ể báo sai 
 static int timhang(int c) 
 { 
 int h, hmin = hang[c] + 1; 
 for (h = hmin; h <= MAX; h++) // thử hàng h 
 if (testvitri(h, c)) return h; 
 return -1; 
 } 
 //hàm kiểm tra xem có thể ₫ặt con hậu ở vị trí h,c ? 
 //trả về TRUE nếu ₫ược, FALSE nếu không 
 static bool testvitri(int h, int c) { 
 int c1,h1; 
 //cột c ₫ang kiểm tra nên chưa có con hậu nào 
 // xem có con hậu nào nằm ở hàng h ? 
 for (c1 = 0; c1 < c; c1++) 
 if (hang[c1] == h) return false; 
 // xem có con hậu nào nằm trên ₫ường chéo trên trái - dưới phải 
 c1 = c-1; h1 = h-1; 
 while (c1>= 0 && h1 >=0) { 
 if (hang[c1] == h1) return false; 
 h1--; c1--; 
 } 
 // xem có con hậu nào nằm trên ₫ường chéo trên phải - dưới trái 
 c1 = c-1; h1 = h+1; 
 while (c1>= 0 && h1 <=MAX) { 
 if (hang[c1] == h1) return false; 
 h1++; c1--; 
 } 
 return true; 
 } 
 //hàm in kết quả 1 cách sắp 8 con hậu theo yêu cầu 
 static void InKetqua() { 
 int h,c; 
 Console.WriteLine("Cách sắp thứ : " + (++cachso)); 
 for (h= 0; h <=MAX; h++) { 
 // Hiển thị hàng lưới ngang của bàn cờ 
 for (c = 0; c <= MAX; c++) Console.Write("+---"); 
 Console.WriteLine("+"); 
Trang 4 
 // Hiển thị nội dung hàng thứ h của bàn cờ 
 for (c= 0; c<=MAX;c++) 
 if (hang[c] == h) Console.Write("| x "); 
 else Console.Write("| "); 
 Console.WriteLine("|"); 
 } 
 // Hiển thị hàng lưới ngang cuối cùng của bàn cờ 
 for (c = 0; c <= MAX; c++) Console.Write("+---"); 
 Console.WriteLine("+"); 
 } 
 }//hết class Program 
}//hết namespace 
4. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Hãy kiểm tra kết quả hiển 
thị của chương trình. 
Trang 1 
MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG 
Bài thực hành số 1.1 : Viết chương trình tạo từ 
I. Mục tiêu : 
 Giúp SV ôn lại qui trình viết 1 ứng dụng VC# ₫ơn giản, tập trung vào việc sử dụng các 
kiểu dữ liệu cơ bản ₫ịnh sẵn như struct và array. 
II. Nội dung : 
 Xây dựng chương trình nhỏ chạy ở chế ₫ộ textmode (console), thực hiện các yêu cầu 
sau : 
1. chờ user nhập vào chuỗi có n ký tự khác nhau. 
2. tìm tất cả phương án ₫ể tạo từ dài n ký tự, mỗi ký tự là ký tự do user nhập, mỗi ký 
tự ₫ược dùng 1 lần trong từ. 
3. in các từ tạo ₫ược ₫ể người dùng xem dễ dàng. 
III. Chuẩn ₫ầu ra : 
 Sinh viên nắm vững và viết thành thạo các ứng dụng nhỏ chạy ở chế ₫ộ textmode và 
biết cách dùng các kiễu dữ liệu cơ bản ₫ịnh sẵn, nhất là kiểu struct và array, khi cần. 
IV. Phân tích : 
1. Ta dùng thuật giải backtracking ₫ể tìm các phương án tạo từ như sau : 
 + Lặp tìm chỉ số gốc của ký tự ₫ược dùng cho từng vị trí (cột) trong từ, từ trái sang phải : 
- Nếu sắp ₫ược cho cột c thì tăng c 1 ₫ơn vị ₫ể tiếp tục cột kế tiếp, nếu cột c ₫ã vượt 
qua MAX thì ₫ã tìm ₫ược 1 từ mới. 
- Nếu không sắp ₫ược cho cột c thì giảm c 1 ₫ơn vị ₫ể thử tiếp các khả năng còn lại 
của cột cũ này. Nếu c <0 thì hết cách. 
2. Để lưu vết xử lý trên từng cột, ta dùng biến array chiso[MAX], mỗi phần tử chiso[c] chứa 
chỉ số ký tự gốc ₫ã xử lý lần cuối trước ₫ây (-1 : chưa, MAX : hết). 
Từ thuật giải ₫ược viết bằng ngôn ngữ tự nhiên ở trên, ta dịch nó thành chương trình ₫ược viết 
bằng VC# như trong mã nguồn dưới ₫ây. 
V. Qui trình : 
1. Chạy VS .Net, chọn menu File.New.Project ₫ể hiển thị cửa sổ New Project. 
2. Mở rộng mục Visual C# trong TreeView "Project Types", chọn mục Windows, chọn icon 
"Console Application" trong listbox "Templates" bên phải, thiết lập thư mục chứa Project 
trong listbox "Location", nhập tên Project vào textbox "Name:" (td. TaoTu), click button 
OK ₫ể tạo Project theo các thông số ₫ã khai báo. 
3. Ngay sau khi Project vừa ₫ược tạo ra, cửa sổ soạn code cho chương trình ₫ược hiển thị. 
Hiệu chỉnh code của file Program.cs ₫ể có nội dung như sau : 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
namespace TaoTu 
{ 
 class Program 
 { 
Trang 2 
 //₫ịnh nghĩa các thuộc tính dữ liệu 
 const int MAXLEN = 20; //số ký tự max cần dùng ₫ể tạo từ 
 static String srcstr; //chuỗi các ký tự khác nhau ₫ể tạo từ 
 static int sotu; //số từ ₫ã tìm ₫ược 
 static int[] chiso = new int[MAXLEN + 1]; //danh sách chỉ số ký tự ₫ã thử trong từng cột 
 static int sokytu; //số ký tự gốc ₫ược dùng ₫ể tạo từ 
 static int c; //vị trị cột ₫ang sắp 
 //Điểm nhập của chương trình 
 static void Main(string[] args) 
 { 
 //nhập chuỗi ký tự dùng ₫ể tạo từ 
 do 
 { 
 Console.Write("Hãy nhập chuỗi các ký tự cần dùng : "); 
 srcstr = Console.ReadLine(); 
 //xác ₫ịnh số ký tự ₫ược dùng 
 sokytu = srcstr.Length; 
 } while (sokytu >= MAXLEN); 
 // khởi ₫ộng trạng thái xuất phát 
 for (c = 0; c < sokytu; c++) chiso[c] = -1; 
 //bắt ₫ầu ₫ặt ký tự chỉ số 0 vào cột ₫ầu (cột 0) của từ cần xây dựng 
 chiso[0] = 0; 
 //bắt ₫ầu tìm ký tự cho cột thứ 2 (chỉ số là 1) của từ cần xây dựng 
 c = 1; 
 while (Tim1cach()) 
 { 
 // tìm ₫ược 1 từ mới 
 InKetqua(); 
 //lùi lại cột trước ₫ể tiếp tục tìm cách sắp khác 
 c--; 
 } 
 // hết cách --> dừng chương trình 
 Console.WriteLine("Số từ xây dựng ₫ược là " + sotu); 
 //chờ người dùng ấn Enter ₫ể ₫óng cửa sổ Console lại. 
 Console.Write("Ấn Enter ₫ể dừng chương trình : "); 
 Console.Read(); 
 return; 
 } 
 //cố gắng tìm 1 phương án sắp các ký tự thành 1 tự mới theo yêu cầu 
 static bool Tim1cach() { 
 int h; 
 while (c < sokytu) 
 { 
 // tìm chỉ số ký tự cho ký tự cột c 
 h = timkytu(c); 
 if (h >= 0) 
 { //tìm ₫ược ==>lưu chỉ số vào danh sách kết quả rồi tăng chỉ số cột ₫ể tiếp tục 
Trang 3 
 chiso[c++] = h; 
 continue; 
 } 
 //trường hợp không tìm ₫ược ký tự ở cột c 
 if (c > 0) 
 { 
 //cột c chưa phải là cột ₫ầu tiên =>xét lại cột c từ ký tự ₫ầu rồi lùi cột c 
 chiso[c--] = -1; 
 continue; 
 } 
 //hết cách 
 return false; 
 } 
 return true; 
 }//hết hàm Tim1cach 
 //hàm tìm chỉ số hàng cho con hậu ở cột c 
 static int timkytu(int c) 
 { 
 int h, hmin = chiso[c] + 1; 
 for (h = hmin; h < sokytu; h++) // thử ký tự chỉ số h 
 if (duocphep(h, c)) return h; 
 return -1; 
 } 
 // Kiểm tra xem có thể xếp ký tự thứ h vào vị trí thứ c trong từ cần xây dựng 
 static bool duocphep(int h, int c) 
 { 
 int k; 
 for (k = 0; k < c; k++) 
 if (chiso[k] == h) return false; 
 return true; 
 } 
 //Kiểm tra từ, nếu có nghĩa thì trả về TRUE, nếu không trả về FALSE 
 static bool conghia(String str) 
 { 
 // Bạn viết lại hàm này theo yêu cầu riêng 
 //ở ₫ây ta coi mọi từ ₫ều có nghĩa 
 return true; 
 } 
 //hàm in từ mới tìm theo yêu cầu 
 static void InKetqua() 
 { 
 String desstr; 
 int k; 
 //Xây dựng từ mới tìm ₫ược 
 desstr = ""; 
 for (k = 0; k < sokytu; k++) 
Trang 4 
 desstr += srcstr[chiso[k]]; 
 if (conghia(desstr)) //kiểm tra từ có nghĩa trước khi in 
 { 
 Console.WriteLine("Từ thứ " + (++sotu) + " : " + desstr); 
 } 
 } 
 }//hết class Program 
}//hết namespace 
4. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng, nhập 1 chuỗi ký tự gốc rồi 
xem và kiểm tra kết quả hiển thị của chương trình. 
5. Lặp lại bước 4 cho nhiều chuỗi ký tự có ₫ộ dài khác nhau. 
Trang 1 
MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG 
Bài thực hành số 1.3 : Viết chương trình "Mã ₫i tuần tra" 
I. Mục tiêu : 
 Giúp SV ôn lại qui trình viết 1 ứng dụng VC# ₫ơn giản, tập trung vào việc sử dụng các 
kiểu dữ liệu cơ bản ₫ịnh sẵn như struct và array. 
II. Nội dung : 
 Xây dựng chương trình nhỏ chạy ở chế ₫ộ textmode (console), thực hiện các yêu cầu 
sau : 
1. chờ người dùng nhập kích thước bàn cờ, tọa ₫ộ hàng cột của con mã xuất 
phát. 
2. tìm tất cả phương án ₫ể giúp con mã ₫i tuần qua tất cả các ô cờ, mỗi ô chỉ 
₫ược phép ₫i qua 1 lần. 
3. in các phương án dạng ma trận 2 chiều ₫ể người dùng xem dễ dàng. 
III. Chuẩn ₫ầu ra : 
 Sinh viên nắm vững và viết thành thạo các ứng dụng nhỏ chạy ở chế ₫ộ textmode và 
biết cách dùng các kiễu dữ liệu cơ bản ₫ịnh sẵn, nhất là kiểu struct và array, khi cần. 
IV. Phân tích : 
1. Ta dùng thuật giải backtracking ₫ể tìm các phương án giúp con mã ₫i tuần qua tất cả 
các ô cờ : 
 + Ở mỗi vị trí, con mã có tối ₫a 8 khả năng ₫i tiếp. 
 + Xuất phát từ vị trí ₫ầu, lặp tìm vị trí con mã kế tiếp (từ khả năng 1 tới 8) : 
- Nếu tìm ₫ược thì tăng chỉ số nước ₫i 1 ₫ơn vị rồi tiếp tục cho ₫ến khi con mã ₫i hết 
các ô, lúc này ₫ã tìm ₫ược 1 cách mới. 
- Nếu không tìm ₫ược thì giảm chỉ số nước ₫i 1 ₫ơn vị, thử tiếp các khả năng còn lại 
của vị trí cũ này. Nếu chỉ số nước ₫i <0 thì hết cách. 
2. Để lưu vết ₫i con mã, ta dùng biến array Nuocdi[MAX], mỗi phần tử Nuocdi[i] chứa tọa ₫ộ 
con mã tương ứng và chỉ số cách ₫ã xử lý lần cuối trước ₫ây (-1 : chưa, 8 : hết). 
Từ thuật giải ₫ược viết bằng ngôn ngữ tự nhiên ở trên, ta dịch nó thành chương trình ₫ược viết 
bằng VC# như trong mã nguồn dưới ₫ây. 
V. Qui trình : 
1. Chạy VS .Net, chọn menu File.New.Project ₫ể hiển thị cửa sổ New Project. 
2. Mở rộng mục Visual C# trong TreeView "Project Types", chọn mục Windows, chọn icon 
"Console Application" trong listbox "Templates" bên phải, thiết lập thư mục chứa Project 
trong listbox "Location", nhập tên Project vào textbox "Name:" (td. Madituan), click button 
OK ₫ể tạo Project theo các thông số ₫ã khai báo. 
3. Ngay sau khi Project vừa ₫ược tạo ra, cửa sổ soạn code cho chương trình ₫ược hiển thị. 
Hiệu chỉnh code của file Program.cs ₫ể có nội dung như sau : 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
Trang 2 
namespace Madituan 
{ 
 class Program 
 { 
 // Kiểu chứa thông tin về 1 bước ₫i 
 private struct ItemRec { 
 public int x, y; 
 public int huong; 
 }; 
 // Các biến dữ liệu chính 
 static int Size; 
 static int[,] Banco; 
 static ItemRec[] Nuocdi; 
 static int SoNuocdi; 
 static int SoNghiem; 
 // Chương trình chính 
 static void Main(string[] args) 
 { 
 Khoidong(); 
 while (DiBuocNua()) 
 if (SoNuocdi == Size * Size-1) 
 { 
 //tìm ₫ược 1 cách mới, in cách ₫i mới tìm ₫ược 
 InKetqua(); 
 Banco[Nuocdi[SoNuocdi].x, Nuocdi[SoNuocdi].y] = -1; 
 //lùi con mã 1 bước 
 SoNuocdi = SoNuocdi - 1; 
 //tiếp tục tìm cách ₫i khác 
 Nuocdi[SoNuocdi].huong = Nuocdi[SoNuocdi].huong + 1; 
 } 
 //chờ người dùng ấn Enter ₫ể ₫óng cửa sổ Console lại. 
 Console.Write("Ấn Enter ₫ể dừng chương trình : "); 
 Console.Read(); 
 } 
 //hàm khởi ₫ộng các giá tr5i ₫ầu của chương trình 
 static void Khoidong() { 
 int i,j; 
 int row, col; 
 String buf; 
 do //chờ nhập kích thước bàn cờ 
 { 
 Console.Write("Nhập số hàng (cột) của bàn cờ: "); 
 buf = Console.ReadLine(); Size = Int32.Parse(buf); 
 } while (Size 9); 
 do //chờ nhập chỉ số hàng xuất phát 
 { 
 Console.Write("Nhập chỉ số hàng xuất phát của con mã : "); 
 buf = Console.ReadLine(); row = Int32.Parse(buf); 
Trang 3 
 } while (row < 0 || Size <= row); 
 do //chờ nhập chỉ số cột xuất phát 
 { 
 Console.Write("Nhập chỉ số cột xuất phát của con mã : "); 
 buf = Console.ReadLine(); col = Int32.Parse(buf); 
 } while (col < 0 || Size <= col); 
 //phân phối vùng nhớ chứa array Banco và danh sach Nuocdi 
 Banco = new int[Size, Size]; 
 Nuocdi = new ItemRec[Size * Size]; 
 for (i = 0; i < Size * Size; i++) 
 Nuocdi[i] = new ItemRec(); 
 //khởi ₫ộng trạng thái ₫ầu cho các vị trí 
 for (i = 0; i < Size; i++) 
 for (j = 0; j < Size; j++) 
 Banco[i, j] = -1; // con mã chưa ₫i qua ô [i,j] 
 SoNghiem = 0; 
 // Thiết lập nước ₫i ₫ầu tiên của con mã 
 Nuocdi[0].x = col; 
 Nuocdi[0].y = row; 
 Nuocdi[0].huong = 0; 
 SoNuocdi =0; 
 //chọn khả năng ₫i tiếp của vị trí ₫ầu tiên của con mã 
 Banco[Nuocdi[SoNuocdi].x, Nuocdi[SoNuocdi].y] = 0; 
 } 
 //hàm tìm vị trí kế tiếp của con mã 
 // trả về TRUE nếu tìm ₫ược, FALSE nếu không tìm ₫ược 
 static bool DiBuocNua() { 
 int x=0, y=0; 
 bool RetVal; 
 RetVal = false; 
 do { // lặp tìm vị trí kế 
 while (RetVal==false && Nuocdi[SoNuocdi].huong < 8) { 
 switch (Nuocdi[SoNuocdi].huong) { //thử hướng ₫i hiện tại 
 case 0 : 
 x = Nuocdi[SoNuocdi].x + 2; 
 y = Nuocdi[SoNuocdi].y - 1; 
 break; 
 case 1 : 
 x = Nuocdi[SoNuocdi].x + 1; 
 y = Nuocdi[SoNuocdi].y - 2; 
 break; 
 case 2 : 
 x = Nuocdi[SoNuocdi].x - 1; 
 y = Nuocdi[SoNuocdi].y - 2; 
 break; 
 case 3 : 
 x = Nuocdi[SoNuocdi].x - 2; 
 y = Nuocdi[SoNuocdi].y - 1; 
Trang 4 
 break; 
 case 4 : 
 x = Nuocdi[SoNuocdi].x - 2; 
 y = Nuocdi[SoNuocdi].y + 1; 
 break; 
 case 5 : 
 x = Nuocdi[SoNuocdi].x - 1; 
 y = Nuocdi[SoNuocdi].y + 2; 
 break; 
 case 6 : 
 x = Nuocdi[SoNuocdi].x + 1; 
 y = Nuocdi[SoNuocdi].y + 2; 
 break; 
 case 7 : 
 x = Nuocdi[SoNuocdi].x + 2; 
 y = Nuocdi[SoNuocdi].y + 1; 
 break; 
 } 
 if (0<=x && x<Size && 0<=y && y<Size && Banco[x,y]==-1) { 
 // nếu ₫ược thì ghi nhận 
 SoNuocdi = SoNuocdi + 1; 
 Banco[x,y] = SoNuocdi; 
 Nuocdi[SoNuocdi].x = x; 
 Nuocdi[SoNuocdi].y = y; 
 Nuocdi[SoNuocdi].huong = 0; 
 RetVal =true; 
 } else // nếu không tìm ₫ược vị trí kế tiếp 
 Nuocdi[SoNuocdi].huong = Nuocdi[SoNuocdi].huong + 1; 
 } 
 if (RetVal==false && SoNuocdi != 0) { 
 // nếu không tìm ₫ược vị trí kế thì lùi con mã 1 bước 
 Banco[Nuocdi[SoNuocdi].x,Nuocdi[SoNuocdi].y] = -1; 
 SoNuocdi = SoNuocdi - 1; 
 Nuocdi[SoNuocdi].huong = Nuocdi[SoNuocdi].huong + 1; 
 } 
 } while (!RetVal && (SoNuocdi!= 0)); 
 return RetVal; 
 } 
 // In kết quả con mã ₫i trên bàn cờ 
 static void InKetqua() 
 { 
 int h, c; 
 SoNghiem = SoNghiem + 1; 
 Console.WriteLine("Cách ₫i thứ : " + SoNghiem); 
 for (h = 0; h < Size; h++) 
 { 
 // Hiển thị hàng lưới ngang bàn cờ 
 for (c = 0; c < Size; c++) Console.Write("+----"); 
 Console.WriteLine("+"); 
Trang 5 
 // Hiển thị nội dung hàng thứ h bàn cờ 
 for (c = 0; c < Size; c++) 
 Console.Write("| {0:D2} ", Banco[h, c]); 
 Console.WriteLine("|"); 
 } 
 // Hiển thị hàng lưới ngang cuối cùng của bàn cờ 
 for (c = 0; c < Size; c++) Console.Write("+----"); 
 Console.WriteLine("+"); 
 } 
 }//hết class Program 
}//hết namespace 
4. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Hãy nhập kích thước bàn 
cờ và tọa ₫ộ miêu tả vị trí xuất phát của con mã rồi xem và kiểm tra kết quả hiển thị của 
chương trình. 
5. Lặp lại bước 4 nhiều lần với nhiều kích thước khác nhau và tọa ₫ộ xuất phát khác nhau 
₫ể quan sát kết quả. Lưu ý do thuật giải rất nhiều bước, còn máy thì tốc ₫ộ hạn chế nên 
nếu chọn kích thước từ 8 trở lên thì sẽ tốn rất nhiều ngày mới có thể có kết quả. 
Trang 1 
MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG 
Bài thực hành số 2.1 : Xây dựng ứng dụng OOP ₫ơn giản 
& tìm hiểu sự tương tác giữa các ₫ối tượng 
I. Mục tiêu : 
 Giúp SV làm quen với qui trình thiết kế trực quan 1 ứng dụng Dialog Based. 
 Giúp SV làm quen với việc dùng lại linh kiện phần mềm. 
 Giúp SV thấy cụ thể cấu trúc ứng dụng cấu thành từ các ₫ối tượng. 
 Giúp SV thấy sự tương tác giữa các ₫ối tượng. 
II. Nội dung : 
 Xây dựng ứng dụng Dialog Based cho phép người dùng chơi các file multimedia. 
 Dịch và chạy chương trình. 
 Debug chương trình ₫ể tìm lỗi nếu có. 
 Tìm hiểu cấu trúc ứng dụng & sự tương tác cụ thể giữa các ₫ối tượng. 
III. Chuẩn ₫ầu ra : 
 Thành thạo việc xây dựng 1 ứng dụng theo qui trình thiết kế trực quan. 
 Thành thạo việc dùng lại linh kiện phần mềm có sẵn, thấy rõ cấu trúc phầm mềm 
và sự tương tác giữa các ₫ối tượng trong phần mềm. 
 Thành thạo việc viết code thay ₫ổi kích thước và vị trí các ₫ối tượng giao diện khi 
cửa sổ chứa chúng bị thay ₫ổi. 
IV. Phân tích : 
 Sau khi phân tích chức năng của chương trình, ta thấy chương trình là 1 form 
giao diện trực quan, nó chứa 1 button Play ₫ể người dùng ra lệnh chơi file, nó 
cũng cần 1 ₫ối tượng cho phép người dùng duyệt trực quan cây thư mục ₫ể chọn 
file (giả sử ta biết ₫ó là ₫ối tượng FileOpenDialog). Cuối cùng chương trình cần 1 
₫ối tượng có khả năng play file multimedia (giả sử ta biết ₫ó là ₫ối tượng 
Windows Media Player). 
 Theo kết quả phân tích trên, cấu trúc chương trình cần viết khá ₫ơn giản, nó chỉ 
chứa các ₫ối tượng ₫ã có sẵn, ta không cần phải bận tâm ₫ặc tả chi tiết các ₫ối 
tượng cần dùng mà chỉ cần dùng lại chúng, lắp ghép chúng lại ₫ể tạo thành 
chương trình. Đây là trường hợp may mắn nhất, nhưng trong thực tế lập trình 
hướng ₫ối tượng, ta sẽ có ₫ược may mắn này thường xuyên. 
V. Qui trình : 
1. Chạy VS .Net, chọn menu File.New.Project ₫ể hiển thị cửa sổ New Project. 
2. Mở rộng mục Visual C# trong TreeView "Project Types", chọn mục Window, chọn 
icon "Windows Application" trong listbox "Templates" bên phải, thiết lập thư mục 
chứa Project trong listbox "Location", nhập tên Project vào textbox "Name:" (thí dụ 
MicroWMP), click button OK ₫ể tạo Project theo các thông số ₫ã khai báo. 
Trang 2 
3. Form ₫ầu tiên của ứng dụng ₫ã hiển thị trong cửa sổ thiết kế, việc thiết kế form là 
quá trình lặp 4 thao tác tạo mới/xóa/hiệu chỉnh thuộc tính/tạo hàm xử lý sự kiện cho 
từng ₫ối tượng cần dùng trong form. 
4. Nếu cửa sổ ToolBox chưa hiển thị chi tiết, chọn menu View.Toolbox ₫ể hiển thị nó 
(thường nằm ở bên trái màn hình). Click chuột vào button (Auto Hide) nằm ở góc 
trên phải cửa sổ ToolBox ₫ể chuyển nó về chế ₫ộ hiển thị thường trực. 
5. Duyệt tìm phần tử Button (trong nhóm Common Controls), chọn nó, dời chuột về góc 
trên trái của form và vẽ nó với kích thước mong muốn. Xem cửa sổ thuộc tính của 
Button vừa vẽ (thường ở góc dưới phải màn hình), duyệt tìm và hiệu chỉnh thuộc tính 
Text = "Play", duyệt tìm và thay ₫ổi thuộc tính (Name) = btnPlay. 
6. Dời chuột vào trong cửa sổ Toolbox, duyệt tìm nhóm Components, ấn phải chuột vào 
mục Components (hay vào bất kỳ phần tử nào trong nhóm này) ₫ể hiển thị menu 
lệnh, chọn option "Choose Items". Khi cửa sổ "Choose Toolbox Items" hiển thị, click 
chuột vào button COM Components ₫ể hiển thị danh sách các linh kiện phần mềm 
theo chuẩn COM ₫ang ₫ược Windows quản lý, hãy duyệt tìm và ₫ánh dấu chọn vào 
phần tử “Windows Media Player”, rồi click button OK ₫ể "add" các control này vào 
nhóm Components của cửa sổ Toolbox của Project ứng dụng. Bây giờ việc dùng 
control “Windows Media Player” giống y như các ₫iều khiển có sẵn khác. 
7. Duyệt tìm phần tử “Windows Media Player” (trong nhóm Components), chọn nó, dời 
chuột ngay dưới Button vừa vẽ, vẽ nó chiếm hết phần còn lại của form. Xem cửa sổ 
thuộc tính của control vừa vẽ (thường ở góc dưới phải màn hình), duyệt tìm và hiệu 
chỉnh thuộc tính thuộc tính (Name) = wmpPlay. 
 Sau khi thiết kế xong, Form có dạng sau : 
8. Dời chuột về button btnPlay, ấn kép chuột vào nó ₫ể tạo hàm xử lý sự kiện Click 
chuột cho button, cửa sổ mã nguồn sẽ hiển thị ₫ể ta bắt ₫ầu viết code cho hàm. 
Cách tổng quát ₫ể tạo hàm xử lý sự kiện là chọn ₫ối tượng btnPlay, cửa sổ thuộc tính 
của nó sẽ hiển thị, click icon ₫ể hiển thị danh sách các sự kiện của ₫ối tượng, 
duyệt tìm sự kiện quan tâm (Click), ấn kép chuột vào comboBox bên phải sự kiện 
Trang 3 
Click ₫ể máy tạo tự ₫ộng hàm xử lý cho sự kiện này. Cửa sổ mã nguồn sẽ hiển thị 
khung sườn của hàm vừa ₫ược tạo với thân rỗng, viết thân cho hàm này như sau : 
 private void btnPlay_Click(object sender, EventArgs e) { 
 //tạo form duyệt chọn file cần chơi 
 OpenFileDialog dlg = new OpenFileDialog(); 
 //hiển thị form duyệt chọn file cần chơi 
 DialogResult ret = dlg.ShowDialog(); 
 //kiểm tra quyết ₫ịnh của người dùng, nếu người dùng chọn OK thì chơi 
 if (ret == DialogResult.OK) 
 wmpPLay.URL = dlg.FileName; 
 } 
9. Chọn menu Debug.Start Debugging ₫ể dịch và chạy thử ứng dụng. Khi Form chương 
trình hiển thị, hãy click chuột vào button Play, cửa sổ duyệt chọn file sẽ hiển thị, hãy 
duyệt và chọn 1 file multimedia nào ₫ó (ảnh tĩnh, film, âm thanh, file playlist,), click 
button Open ₫ể chơi file này. Hãy thử chọn nhiều file khác nhau xem chương trình 
chạy ổn ₫ịnh không. 
10. Dừng chương trình, dời chuột về cửa sổ “Solution Explorer”, duyệt tìm phần tử 
Form1, ấn phải chuột trên nó ₫ể hiển thị menu lệnh, chọn lệnh “View Code” ₫ể hiển 
thị lại mã nguồn của Form chương trình, khảo sát thân của hàm btnPlay và tìm hiểu 
sự tương tác giữa ₫ối tượng Form1 với các ₫ối tượng OpenFileDialog và wmpPlay. 
11. Chạy lại ứng dụng, quan sát góc trên phải của Form chương trình, ta thấy 3 button 
chức năng thông thường là 1. thu nhỏ form về dạng icon, 2. phóng to/thu nhỏ kích 
thước form, 3. ₫óng form : 
12. Thử click chuột vào button phóng to/thu nhỏ, form sẽ ₫ược phóng to ₫ể chiếm hết 
màn hình nhưng các ₫ối tượng giao diện ₫ược thiết kế bên trong nó (button, WMP) 
không hề thay ₫ổi kích thước theo. Làm sao thay ₫ổi kích thước các ₫ối tượng trong 
form theo kích thước của form ? 
13. Nếu muốn phóng to/thu nhỏ các ₫ối tượng bên trong theo kích thước cửa sổ, ta cần 
viết code thực hiện việc này 1 cách tường minh, ₫oạn code thay ₫ổi kích thước và vị 
trí các ₫ối tượng bên trong ₫ược ₫ể trong hàm xử lý sự kiện SizeChanged của ₫ối 
tượng Form. 
14. Dừng chương trình, dời chuột về cửa sổ “Solution Explorer”, duyệt tìm phần tử 
Form1, ấn kép chuột trên nó ₫ể hiển thị cửa sổ thiết kế Form, chọn Form ₫ể hiển thị 
cửa sổ thuộc tính của nó, click icon ₫ể hiển thị danh sách các sự kiện của Form, 
duyệt tìm sự kiện quan tâm (SizeChanged), ấn kép chuột vào comboBox bên phải sự 
kiện SizeChanged ₫ể máy tạo tự ₫ộng hàm xử lý cho sự kiện này. Cửa sổ mã nguồn 
Trang 4 
sẽ hiển thị khung sườn của hàm vừa ₫ược tạo với thân rỗng, viết thân cho hàm này 
như sau : 
 private void Form1_SizeChanged(object sender, EventArgs e) { 
 //xác ₫ịnh kích thước hiện hành của Form 
 int cx = this.Size.Width; 
 int cy = this.Size.Height; 
 //thay ₫ổi vị trí của ₫ối tượng WMP về vị trí mong muốn 
 wmpPlay.Location = new Point (10, 40); 
 //thay ₫ổi kích thước của ₫ối tượng WMP theo kích thước Form 
 wmpPlay.Size = new Size (cx - 30, cy - 80); 
 } 
15. Chạy lại ứng dụng, thử phóng to/thu nhỏ, thay ₫ổi kích thước của cửa sổ, ta thấy ₫ối 
tượng WMP sẽ thay ₫ổi kích thước theo. Riêng button thì không thay ₫ổi vì ta không 
có nhu cầu và không viết code làm việc này. 
Trang 1 
MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG 
Bài thực hành số 2.2 : Xây dựng ứng dụng giải ô số Sudoku 
I. Mục tiêu : 
 Giúp SV làm quen với qui trình thiết kế trực quan 1 ứng dụng Dialog Based. 
 Giúp SV làm quen với việc dùng lại linh kiện phần mềm. 
 Giúp SV thấy cụ thể cấu trúc ứng dụng cấu thành từ các ₫ối tượng. 
 Giúp SV thấy sự tương tác giữa các ₫ối tượng. 
II. Nội dung : 
 Xây dựng chương trình nhỏ chạy ở chế ₫ộ ₫ồ họa cho phép user nhập các giá trị 
vào 1 số ô Sudoku rồi giải. Cửa sổ ứng dụng có dạng sau : 
III. Chuẩn ₫ầu ra : 
 Thành thạo việc xây dựng 1 ứng dụng theo qui trình thiết kế trực quan. 
 Thành thạo việc dùng lại linh kiện phần mềm có sẵn, thấy rõ cấu trúc phầm mềm 
và sự tương tác giữa các ₫ối tượng trong phần mềm. 
 Thành thạo việc viết code thay ₫ổi kích thước và vị trí các ₫ối tượng giao diện khi 
cửa sổ chứa chúng bị thay ₫ổi. 
IV. Phân tích : 
Trang 2 
Chương trình chứa 1 ₫ối tượng Form, Form chứa các ₫ối tượng bên trong : 
 - 3 ₫ối tượng Button 
 - 1 ₫ối tượng Label 
 - 1 ₫ối tượng ma trận Sudoku 
Ta có thể thiết kế trực quan Form với các ₫ối tượng co sẵn như Button, Label cho dễ. 
Riêng ma trận Sudoku sẽ ₫ược lập trình ₫ộng theo trạng thái từng thời ₫iểm của nó. 
V. Qui trình : 
1. Chạy VS .Net, chọn menu File.New.Project ₫ể hiển thị cửa sổ New Project. 
2. Mở rộng mục Visual C# trong TreeView "Project Types", chọn mục Window, chọn 
icon "Windows Application" trong listbox "Templates" bên phải, thiết lập thư mục 
chứa Project trong listbox "Location", nhập tên Project vào textbox "Name:" (thí dụ 
Form_Sudoku), click button OK ₫ể tạo Project theo các thông số ₫ã khai báo. 
3. Form ₫ầu tiên của ứng dụng ₫ã hiển thị trong cửa sổ thiết kế, việc thiết kế form là 
quá trình lặp 4 thao tác tạo mới/xóa/hiệu chỉnh thuộc tính/tạo hàm xử lý sự kiện cho 
từng ₫ối tượng cần dùng trong form. 
4. Nếu cửa sổ ToolBox chưa hiển thị chi tiết, chọn menu View.Toolbox ₫ể hiển thị nó 
(thường nằm ở bên trái màn hình). Click chuột vào button (Auto Hide) nằm ở góc 
trên phải cửa sổ ToolBox ₫ể chuyển nó về chế ₫ộ hiển thị thường trực. 
5. Duyệt tìm phần tử Button (trong nhóm Common Controls), chọn nó, dời chuột về góc 
trên trái của form và vẽ nó với kích thước mong muốn. Xem cửa sổ thuộc tính của 
Button vừa vẽ (thường ở góc dưới phải màn hình), duyệt tìm và hiệu chỉnh thuộc tính 
Text = "Giải", duyệt tìm và thay ₫ổi thuộc tính (Name) = btnGiai. 
6. Lặp lại bước 5 hai lần nữa ₫ể vẽ 2 button ("Giải tiếp", btnGiaitiep) và ("Xóa", btnXoa). 
7. Duyệt tìm phần tử Label (trong nhóm Common Controls), chọn nó, dời chuột về vị trí 
ngay dưới các button và vẽ nó với kích thước mong muốn. Hiệu chỉnh thuộc tính 
(Name) = lblMesg. 
8. Dời chuột về button btnGiai, ấn kép chuột vào nó ₫ể tạo hàm xử lý sự kiện Click 
chuột cho button, cửa sổ mã nguồn sẽ hiển thị ₫ể ta bắt ₫ầu viết code cho hàm. 
Cách tổng quát ₫ể tạo hàm xử lý sự kiện là chọn ₫ối tượng btnGiai, cửa sổ thuộc tính 
của nó sẽ hiển thị, click icon ₫ể hiển thị danh sách các sự kiện của ₫ối tượng, 
duyệt tìm sự kiện quan tâm (Click), ấn kép chuột vào comboBox bên phải sự kiện 
Click ₫ể máy tạo tự ₫ộng hàm xử lý cho sự kiện này. Cửa sổ mã nguồn sẽ hiển thị 
khung sườn của hàm vừa ₫ược tạo với thân rỗng, ta viết thân cho hàm này sau. 
9. Dời chuột về cửa sổ “Solution Explorer” (thường nằm ở phía trên phải màn hình), 
duyệt tìm phần tử Form1.cs, ấn phải chuột trên nó ₫ể hiển thị menu lệnh, chọn lệnh 
“View Designer” ₫ể hiển thị lại cửa số thiết kế của Form. Thực hiện lại bước 7 trên 
button btnGiaitiep ₫ể tạo hàm xử lý sự kiện Click chuột cho button này. 
10. Tiếp tục tạo hàm xử lý sự kiện Click chuột cho button btnXoa. 
Trang 3 
11. Dời chuột về cửa sổ “Solution Explorer”, duyệt tìm phần tử Form1.cs, ấn phải chuột 
trên nó ₫ể hiển thị menu lệnh, chọn lệnh “View Designer” ₫ể hiển thị lại cửa số thiết 
kế của Form. Chọn Form này rồi lần lượt tạo hàm xử lý sự kiện KeyDown, 
MouseDown, Paint cho Form. 
12. Dời chuột về ₫ầu class Form1 rồi viết tiếp ₫oạn code sau phục vụ việc giải ô số 
Sudoku : 
 //============================================================== 
 // phần code ₫ộc lập với giao diện 
 //============================================================== 
 //₫ịnh nghĩa kiểu miêu tả thông tin về 1 ô số 
 struct Cell 
 { 
 public bool fix; //fix = true : giá trị ô cố ₫ịnh 
 public sbyte value; 
 }; 
 //₫ịnh nghĩa các thuộc tính dữ liệu 
 const int LEN = 9; 
 Cell[,] matran = new Cell[LEN, LEN]; 
 int h, c; //tọa ₫ộ ô ₫ang xử lý 
 int cachso; 
 //hàm kiểm tra ô (h,c) có thể chứa giá trị val không ? 
 bool Testvitri(int h, int c, sbyte val) 
 { 
 int h1, c1; 
 int i, j; 
 matran[h, c].value = 0; 
 if (val > 9) return false; 
 // xem có trùng với cell nào ở hàng h ? 
 for (c1 = 0; c1 < LEN; c1++) 
 if (matran[h, c1].value == val) return false; 
 // xem có trùng với cell nào ở cot c ? 
 for (h1 = 0; h1 < LEN; h1++) 
 if (matran[h1, c].value == val) return false; 
 // xem có trùng với cell trong vùng 3x3 ? 
 h1 = h / 3 * 3; 
 c1 = c / 3 * 3; 
 for (i = h1; i < h1 + 3; i++) 
 for (j = c1; j < c1 + 3; j++) 
 if (matran[i, j].value == val) return false; 
 //chứa kết quả vào cell tương ứng 
 matran[h, c].value = val; 
 return true; 
 } 
Trang 4 
 //hàm tìm trị phù hợp cho ô h,c ? 
 //trả về TRUE nếu ₫ược, FALSE nếu không 
 bool timtri(int h, int c) 
 { 
 sbyte val; 
 sbyte d; 
 if (matran[h,c].fix) return true; 
 val = matran[h, c].value; val++; 
 matran[h,c].value = 0; 
 for (d = val; d <= 9; d++) if (Testvitri(h, c, d)) return true; 
 return false; 
 } 
 //hàm lùi về ô ngay trước ô h,c cần xừ lý tiếp 
 //trả về TRUE nếu lùi ₫ược, FALSE nếu không lùi ₫ược 
 bool Back(ref int h, ref int c) 
 { 
 while (true) 
 { 
 if (c > 0) c--; 
 else 
 { 
 c = LEN - 1; h--; 
 } 
 if (h < 0) return false; //hết cách 
 if (matran[h, c].fix == false) return true; 
 } 
 } 
 //============================================================= 
 // phần code phục vụ giao diện với người dùng 
 //============================================================= 
 //Định nghĩa các hằng cần dùng 
 int yStart = 70; //top của bảng Sukodu 
 int xStart = 10; //left của bảng Sukodu 
 int wSeparator = 4; //khoảng hở giữa các vùng 
 const int WCELL = 40; //₫ộ rộng từng ô 
 const int HCELL = 40; //₫ộ cao tửng ô 
 //tạo pen với màu Blue, nét vẽ 2 pixel 
 Pen pen = new Pen(Color.FromArgb(255, 0, 255), 1); 
 //tạo brush với màu ₫ỏ, tô ₫ặc 
 Brush brush = new SolidBrush(Color.FromArgb(255, 0, 255)); 
 Graphics g; 
Trang 5 
 int xcur, ycur; //ô nhập liệu 
 //hàm hiển thị nội dung ô row,col 
 private void OutXY(int row, int col) 
 { 
 //tạo ₫ối tượng font chữ cần dùng 
 Font myFont = new Font("Helvetica", 11); 
 //tạo biến miêu tả chế ₫ộ canh giữa khi xuất chuỗi 
 StringFormat format1 = new StringFormat(StringFormatFlags.NoClip); 
 format1.Alignment = StringAlignment.Center; 
 //tính tọa ₫ộ x,y trên form của ô row,col 
 int x, y; 
 x = xStart + col * WCELL + (col / 3 + 1) * wSeparator; 
 y = yStart + row * HCELL + (row / 3 + 1) * wSeparator; 
 //thiết lập màu nền và màu chữ cho ô 
 Color bColor, fColor; 
 if (matran[row,col].fix) 
 { 
 bColor = Color.FromArgb(0, 0, 255); 
 fColor = Color.FromArgb(255, 255, 255); 
 } 
 else 
 { 
 bColor = Color.FromArgb(230, 230, 230); 
 fColor = Color.FromArgb(0, 0, 0); 
 } 
 pen.Color = fColor; 
 brush = new SolidBrush(bColor); 
 //tô nền cho ô 
 g.FillRectangle(brush, x + 2, y + 2, WCELL - 4, HCELL - 4); 
 if (matran[row,col].value > 0) // hiển thị ô hợp lệ 
 g.DrawString(matran[row,col].value.ToString(), myFont, new 
SolidBrush(fColor), x + WCELL / 2, y + 8, format1); 
 if (matran[row,col].value == -1) //hiển thị ô không hợp lệ 
 { 
 g.DrawString("?", myFont, System.Drawing.Brushes.Red,x + WCELL / 2, y + 
8, format1); 
 } 
 if (row == ycur && col == xcur) 
 { 
 //vẽ cursor nhập liệu ở ô hiện hành 
 pen.Color = Color.DarkBlue; 
 g.DrawRectangle(pen,x + 3, y + 3, WCELL - 6, HCELL - 6); 
 } 
Trang 6 
 } 
 private void Giai() { 
 //bắt ₫ầu tìm trị cho ô trên trái 
 cachso = 0; 
 h = 0; c = 0; 
 //cố gắng tìm 1 cách sắp xếp các ô số 
 Tim1cach(); 
 btnGiai.Enabled = false; 
 btnGiaitiep.Enabled = true; 
 } 
 //hàm cố gắng tìm 1 cách sắp xếp các ô số 
 void Tim1cach() 
 { 
 while (h<LEN) { //cần tìm trị cho ô h,c 
 //tìm trị cho ô h,c 
 if (timtri(h,c)) { //nếu tìm ₫ược 
 //tiếp tục ô kế tiếp 
 if (++c == LEN) { c = 0; ++h; } 
 continue; 
 } 
 //nếu tìm không ₫ược trị cho ô h,c 
 matran[h, c].value = 0; 
 if (Back(ref h, ref c)) continue; 
 //hết cách --> dừng chương trình 
 lblMesg.Text = "Hết cách rồi"; 
 return; 
 } 
 // tìm ₫ược cách sắp toàn bộ các ô số 
 cachso++; 
 lblMesg.Text = "Cách thứ " + cachso + ":"; 
 this.Invalidate(); 
 return; 
 } 
 //hàm tìm cách giải kế tiếp 
 private void Giaitiep() 
 { 
 if (!Back(ref h, ref c)) 
 //hết cách 
 lblMesg.Text = "Không còn cách nào khác nữa."; 
 else 
 { 
Trang 7 
 Tim1cach(); 
 } 
 } 
 //hàm reset ma trận Sudoku về trạng thái ban ₫ầu 
 private void XoaSudoku() 
 { 
 int h, c; 
 //lặp reset từng cell 
 for (h = 0; h < LEN; h++) 
 for (c = 0; c < LEN; c++) { 
 matran[h, c].fix = false; 
 matran[h, c].value = 0; 
 } 
 lblMesg.Text = "Hãy nhập số vào các ô :"; 
 btnGiaitiep.Enabled = false; 
 btnGiai.Enabled = true; 
 Invalidate(); 
 } 
13. Viết code cho các hàm xử lý sự kiện vừa tạo ra trong các bước trước như sau (lưu ý 
chỉ copy thân hàm và dán vào khung sườn của hàm ₫ã ₫ược máy tạo sẵn) : 
 //hàm khởi tạo Form 
 public Form1() 
 { 
 InitializeComponent(); 
 int h, c; 
 //phân phối vùng nhớ cho ma trận Sukodu 
 for (h = 0; h < LEN; h++) 
 for (c = 0; c < LEN; c++) 
 matran[h, c] = new Cell(); 
 //hiệu chỉnh lại kích thước Form ₫ể chứa vừa ma trận TextBox 
 this.Size = new Size(9 * WCELL + xStart * 2 + 14 + 4 * wSeparator, 9 * HCELL + 
yStart + 10 + 40 + 4 * wSeparator); 
 //thiết lập ô chứa cursor nhập liệu 
 xcur = ycur = LEN / 2; 
 //cho phép Form xử lý sự kiện phím 
 this.KeyPreview = true; 
 XoaSudoku(); 
 } 
 //hàm xử lý Click chuột trên button Giai 
 private void btnGiai_Click(object sender, EventArgs e) 
 { 
 Giai(); 
Trang 8 
 } 
 //hàm xử lý Click trên button Giaitiep 
 private void btnGiaitiep_Click(object sender, EventArgs e) 
 { 
 Giaitiep(); 
 } 
 //hàm xử lý Click trên button Xoa 
 private void btnXoa_Click(object sender, EventArgs e) 
 { 
 XoaSudoku(); 
 } 
 //hàm xử lý Click chuột trên Form 
 private void Form1_MouseDown(object sender, MouseEventArgs e) 
 { 
 //xác ₫ịnh tọa ₫ộ chuột 
 int x = e.X, y =e.Y; 
 //kiểm tra chuột có nằm trên ma trận Sudoku ? 
 if (xStart > x || x >xStart + LEN * WCELL + 4*wSeparator || 
 yStart > y || y > yStart+ LEN * HCELL + 4*wSeparator) { 
 //nếu nằm ngoài ma trận thì không làm gì 
 return; 
 } 
 //xác ₫ịnh ô ₫ược focus 
 xcur = (x - xStart) /WCELL; 
 if (xcur == LEN) xcur--; 
 ycur = (y - yStart) /HCELL; 
 if (ycur == LEN) ycur--; 
 //vẽ lại Form 
 this.Invalidate(); 
 return; 
 } 
 //hàm xử lý ấn phím trên Form 
 private void Form1_KeyDown(object sender, KeyEventArgs e) 
 { 
 if (Keys.D0<= e.KeyCode && e.KeyCode <=Keys.D9) { //các phím số 0-9 
 sbyte d = (sbyte)(e.KeyCode -Keys.D0); 
 if (d == 0) { //phím xóa ô 
 matran[ycur, xcur].fix = false; 
 matran[ycur, xcur].value = d; 
Trang 9 
 } 
 else if (Testvitri(ycur, xcur, d)) {//hợp lệ 
 matran[ycur,xcur].fix = true; 
 matran[ycur,xcur].value = d; 
 } else { //không hợp lệ 
 matran[ycur,xcur].value = -1; 
 matran[ycur,xcur].fix = false; 
 lblMesg.Text = "Hãy sửa giá trị ô màu ₫ỏ vì bị lỗi."; 
 } 
 } 
 //kiểm tra các phím ₫iều khiển 
 switch (e.KeyCode) { 
 case Keys.Up: 
 if (ycur==0) return; 
 ycur--; break; 
 case Keys.Down: 
 if (ycur==LEN) return; 
 ycur++; break; 
 case Keys.Left: 
 if (xcur==0) return; 
 xcur--; break; 
 case Keys.Right: 
 if (xcur==LEN) return; 
 xcur++; break; 
 case Keys.Enter: 
 Giai(); break; 
 case Keys.Delete: 
 XoaSudoku(); break; 
 case Keys.Space: 
 Giaitiep(); break; 
 case Keys.Escape: 
 this.Close(); break; 
 default: 
 break; 
 } 
 Invalidate(); 
 } 
 //hàm vẽ lại Form 
 private void Form1_Paint(object sender, PaintEventArgs e) 
 { 
 int x1,y1,x2,y2; 
 int row, col; 
 g = e.Graphics; 
Trang 10 
 //thiết lập màu vẽ 
 for (row = 0; row < LEN; row++) 
 for (col = 0; col < LEN; col++) OutXY(row, col); 
 //thiết lập màu Magenta cho pen 
 pen.Color = Color.FromArgb(255, 0, 255); 
 //tạo brush với màu Magenta, tô ₫ặc 
 brush = new SolidBrush(Color.FromArgb(255, 0, 255)); 
 //vẽ các ₫ường lưới dọc phân ô và phân vùng ma trận Sudoku 
 y1 = yStart; 
 y2= yStart+ LEN * HCELL + 4*wSeparator; 
 for (col=0;col<=LEN;col++) { 
 //xác ₫ịnh tọa ₫ộ x của ₫ường lưới 
 x1 = x2 = xStart + col*WCELL+ (col/3+1)*wSeparator; 
 if ((col-col/3*3)==0) //lưới phân vùng 
 g.FillRectangle(brush, x1 - wSeparator, y1, wSeparator, y2 - yStart); 
 else { //lưới phân ô 
 pen.Color = Color.FromArgb(0, 0, 255); 
 g.DrawLine(pen, x1, y1, x2, y2); 
 } 
 } 
 //vẽ các ₫ường lưới ngang phân ô và phân vùng ma trận Sudoku 
 x1 = xStart; 
 x2 = xStart + LEN * WCELL + 3 * wSeparator; 
 for (row=0;row<=LEN;row++) { 
 //xác ₫ịnh tọa ₫ộ y của ₫ường lưới 
 y1 = y2 = yStart + row * HCELL + (row / 3 + 1) * wSeparator; 
 if ((row - row / 3 * 3) == 0) //lưới phân vùng 
 g.FillRectangle(brush, x1, y1 - wSeparator, x2 - xStart, wSeparator); 
 else { //lưới phân ô 
 pen.Color = Color.FromArgb(0, 0, 255); 
 g.DrawLine(pen, x1, y1, x2, y2); 
 } 
 } 
 } 
14. Chọn menu Debug.Start Debugging ₫ể dịch và chạy thử ứng dụng. 
15. Khi Form chương trình hiển thị, hãy click chuột vào từng ô cần nhập số rồi gỏ phím 
số cần nhập. Sau khi ₫ã nhập xong các ô số của bài toán, bạn click button Giai và 
xem ₫áp án có ₫úng với yêu cầu. Nếu muốnn xem ₫áp án khác, bạn ấn button "Giải 
tiếp", máy sẽ cố gắng tìm phương án khác, nếu có nó hiển thị lên, nếu không nó báo 
hết cách. 
Trang 11 
16. Muốn giải ô số Sudoku khác, bạn click button "Xóa" ₫ể máy khởi ₫ộng lại từ ₫ầu. 
Hãy thực hiện lại bước 15. 
Trang 1 
MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG 
Bài thực hành số 3.1 : Viết chương trình khảo sát việc ₫ịnh nghĩa & sử dụng ₫ối 
tượng 
I. Mục tiêu : 
 Giúp SV làm quen với việc ₫ặc tả interface & class của ₫ối tượng. 
 Giúp SV hiểu rõ chi tiết về các mức ₫ộ bao ₫óng thành phần trong ₫ối tượng. 
 Giúp SV hiểu rõ cách thức sử dụng ₫ối tượng. 
II. Nội dung : 
 Đặc tả 1 interface và 1 class hiện thực interface này. 
 Xây dựng chương trình nhỏ demo các tình huống dùng ₫ối tượng khác nhau. 
III. Chuẩn ₫ầu ra : 
 Sinh viên nắm vững và viết thành thạo các lệnh interface và class ₫ể ₫ịnh nghĩa 2 
góc nhìn khác nhau của từng ₫ối tượng ₫ược dùng trong phần mềm. 
 Sinh viên nắm vững các mức ₫ộ bao ₫óng thành phần trong ₫ối tượng, từ ₫ó chủ 
₫ộng kiểm soát việc dùng ₫ối tượng trong các tình huống sử dụng khác nhau. 
IV. Qui trình : 
1. Chạy VS .Net, chọn menu File.New.Project ₫ể hiển thị cửa sổ New Project. 
2. Mở rộng mục Visual C# trong TreeView "Project Types", chọn mục Windows, chọn icon 
"Console Application" trong listbox "Templates" bên phải, thiết lập thư mục chứa Project 
trong listbox "Location", nhập tên Project vào textbox "Name:" (td. DefAndUseObject), 
click button OK ₫ể tạo Project theo các thông số ₫ã khai báo. 
3. Ngay sau khi Project vừa ₫ược tạo ra, cửa sổ soạn code cho chương trình ₫ược hiển thị. 
Hiệu chỉnh code của file Program.cs ₫ể có nội dung như sau : 
namespace DefAndUseObject { 
 class Program { 
 //₫ịnh nghĩa 1 hàm dịch vụ 
 static void button2_Click(object sender, System.EventArgs e) { 
 Console.WriteLine("Ham xu lý Click cua class Program chay"); 
 } 
 //₫iểm nhập của chương trình 
 static void Main(string[] args) { 
 //1. tạo ₫ối tượng thuộc class MyClass 
 MyClass obj = new MyClass(); 
 //2. thử truy xuất các thành phần private và protected 
 //quan sát phản ứng của chương trình dịch 
 obj.m_x = 5; 
 obj.arr[1] = 10; 
 //3. truy xuất thuộc tính giao tiếp 
 obj.x = 5; 
 //4. gởi thông ₫iệp chạy tác vụ chức năng 
 obj.func2(); 
 //5. tạo sự kiện Click ₫ể xem hàm nào chạy 
 Object sender =new Object(); 
 EventArgs e = new EventArgs(); 
 obj.OnClick(sender,e); 
Trang 2 
 //6. thiết lập lại hàm xử lý sự kiện Click 
 obj.Click -= new MyClass.EventHandler(obj.button1_Click); 
 obj.Click += new MyClass.EventHandler(button2_Click); 
 //7. tạo sự kiện Click ₫ể xem hàm nào chạy 
 obj.OnClick(sender, e); 
 //8. dùng ₫ối tượng như danh sách các số nguyên 
 int i; 
 //chứa 10 số nguyên từ 0-9 vào danh sách 
 for (i = 0; i < 10; i++) obj[i] = i; 
 //₫ọc lại các số nguyên trong danh sách và hiển thị 
 for (i= 0; i < 10; i++) 
 Console.WriteLine("phan tu " + i + " = " + obj[i]); 
 //9.chờ người dùng ấn phím ₫ể ₫óng cửa sổ 
 Console.Write("Hay an phim Enter de dung chuong trinh : "); 
 Console.Read(); 
 } 
 } //kết thúc class 
} //kết thúc namespace 
4. Dời chuột về phần tử gốc của cây Project trong cửa sổ “Solution Explorer”, ấn phải chuột 
vào nó ₫ể hiển thị menu lệnh, chọn chức năng Add.New Item ₫ể hiển thị cửa sổ “Add 
New Item”, chọn mục “Interface”, hiệu chỉnh tên interface là IMyInterface.cs, chọn button 
Add ₫ể máy tạo 1 interface mới. 
5. Cửa sổ soạn code cho interface IMyInterface ₫ược hiển thị, ta ₫ịnh nghĩa interface ₫ơn 
giản như sau : 
namespace DefAndUseObject { 
 interface IMyInterface { 
 void func2(); //chỉ có 1 tác vụ chức năng 
 } 
} 
6. Dời chuột về phần tử gốc của cây Project trong cửa sổ “Solution Explorer”, ấn phải chuột 
vào nó ₫ể hiển thị menu lệnh, chọn chức năng Add.Class ₫ể hiển thị cửa sổ “Add New 
Item”, chọn mục “Class”, hiệu chỉnh tên class là MyClass.cs, chọn button Add ₫ể máy tạo 
1 class mới. 
7. Khi cửa sổ soạn code cho class MyClass hiển thị, hiệu chỉnh nội dung của class như sau 
: 
namespace DefAndUseObject { 
 class MyClass : IMyInterface { 
 //1. ₫ịnh nghĩa các thuộc tính vật lý 
 private int m_x; 
 protected int[] arr = new int[100]; 
 //2. ₫ịnh nghĩa các tác vụ quản lý ₫ối tượng 
 public MyClass() { 
 this.Click += new EventHandler(button1_Click); 
 } 
 ~MyClass() {} //hàm destructor 
 //3. ₫ịnh nghĩa ₫ối tượng ₫ại diện hàm chức năng 
 public delegate void EventHandler(Object sender, EventArgs e); 
 //4. ₫ịnh nghĩa sự kiện Click ₫ược xử lý bởi delegate EventHandler. 
Trang 3 
 public event EventHandler Click; 
 //5. ₫ịnh nghĩa các tác vụ & toán tử chức năng 
 public void button1_Click(object sender, System.EventArgs e) { 
 Console.WriteLine("Ham xu lý Click cua class MyClass chay"); 
 } 
 public void func2() { 
 Console.WriteLine("Ham MyClass.func2() ₫ang chạy"); 
 } 
 //6. ₫ịnh nghĩa tác vụ kích hoạt sự kiện Click 
 public void OnClick(Object sender, EventArgs e) { 
 if (Click != null) Click(sender, e); 
 } 
 //7. ₫ịnh nghĩa thuộc tính luận lý x 
 public int x { 
 get { return m_x; } 
 set { m_x = value; } 
 } 
 //8. ₫ịnh nghĩa indexer 
 public int this[int index] { 
 get { 
 //kiểm tra giới hạn ₫ể quyết ₫ịnh 
 if (index = 100) { return 0; } 
 else { return arr[index]; } 
 } 
 set { 
 if (0 <= index && index < 100) { arr[index] = value; } 
 } 
 } 
 } //kết thúc class 
} //kết thúc namespace 
8. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Ta thấy máy báo lỗi ở 2 
lệnh truy xuất thành phần bị che dấu bởi ₫ối tượng (có tầm vực private, protected). 
9. Hãy chú thích 2 dòng lệnh bị lỗi rồi dịch và chạy lại ứng dụng, cửa sổ Console hiển thị 
các thông báo xuất của chương trình. Hãy kiểm tra từng lệnh xem ₫iều gì xảy ra và cố 
gắng lý giải kết quả. 
10. Hãy hiệu chỉnh lệnh ₫ịnh nghĩa biến MyClass obj= ở ₫ầu hàm Main thành : 
IMyInterfce obj = new MyClass(); 
rồi dịch và chạy lại ứng dụng. Máy sẽ báo lỗi ở các hàng lệnh truy xuất ₫ối tượng obj, mày 
chỉ cho phép dùng ₫úng lệnh gởi thông ₫iệp obj.func2(); Lý giải : vì biến obj có kiểu là 
interface IMyInterface nên ta chỉ có thể truy xuất ₫úng 1 hàm func2 trong interface mà 
thôi, mọi chi tiết của ₫ối tượng ₫ược tham khảo ₫ều bị che dấu. 
Trang 1 
MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG 
Bài thực hành số 4.1 : Viết chương trình khảo sát việc quản lý ₫ời sống ₫ối 
tượng và sử dụng ₫ối tượng 
I. Mục tiêu : 
 Giúp SV làm quen với việc ₫ặc tả interface & class của ₫ối tượng. 
 Giúp SV hiểu rõ chi tiết về thừa kế, bao ₫óng. 
 Giúp SV hiểu rõ chi tiết về ₫ời sống của ₫ối tượng, hành vi của lệnh new & các tác vụ 
constructors, cách thức tất toán ₫ối tượng trước khi xóa ₫ối tượng. 
 Giúp SV hiểu rõ cách thức sử dụng ₫ối tượng, thấy lợi ích của ₫a xạ. 
II. Nội dung : 
 Đặc tả 1 interface chung và 3 class ClassA, ClassB, ClassC hiện thực interface này 
và dựa trên cơ chế thừa kế. 
 Xây dựng chương trình nhỏ chạy ở chế ₫ộ textmode (console) tạo từng ₫ối tượng 
thuộc từng class rồi sử dụng nó. 
III. Chuẩn ₫ầu ra : 
 Sinh viên nắm vững và viết thành thạo các lệnh interface và class ₫ể ₫ịnh nghĩa 2 
góc nhìn khác nhau của từng ₫ối tượng ₫ược dùng trong phần mềm. 
 Sinh viên nắm vững và chủ ₫ộng kiểm soát ₫ược ₫ời sống của từng ₫ối tượng ₫ược 
dùng trong phần mềm. 
 Sinh viên viết thành thạo các lệnh gởi thông ₫iệp và nắm vững cơ chế ₫a xạ. 
IV. Qui trình : 
1. Chạy VS .Net, chọn menu File.New.Project ₫ể hiển thị cửa sổ New Project. 
2. Mở rộng mục Visual C# trong TreeView "Project Types", chọn mục Windows, chọn icon 
"Console Application" trong listbox "Templates" bên phải, thiết lập thư mục chứa Project 
trong listbox "Location", nhập tên Project vào textbox "Name:" (td. UseObject), click 
button OK ₫ể tạo Project theo các thông số ₫ã khai báo. 
3. Ngay sau khi Project vừa ₫ược tạo ra, cửa sổ soạn code cho chương trình ₫ược hiển thị. 
Hiệu chỉnh code của file Program.cs ₫ể có nội dung như sau : 
namespace UseObject { 
 class Program { 
 static void Main(string[] args) { 
 Console.WriteLine("Lenh ClassA ca = new ClassA(); chay. Hay quan sat trinh tu 
cac constructor."); 
 ClassA ca = new ClassA(); 
 Console.WriteLine(); 
 Console.WriteLine("Lenh ca.func1(); chay. Hay quan sat ham cu the nao chay"); 
 ca.func1(); 
 Console.WriteLine(); 
 Console.WriteLine("Lenh ca.func2(); chay. Hay quan sat ham cu the nao chay"); 
 ca.func2(); 
 Console.WriteLine(); 
 Console.WriteLine("Lenh ca = new ClassB (); chay. Hay quan sat trinh tu cac 
constructor."); 
 ca = new ClassB (); 
 Console.WriteLine(); 
 Console.WriteLine("Lenh ca.func1(); chay. Hay quan sat ham cu the nao chay"); 
Trang 2 
 ca.func1(); 
 Console.WriteLine(); 
 Console.WriteLine("Lenh ca.func2(); chay. Hay quan sat ham cu the nao chay"); 
 ca.func2(); 
 Console.WriteLine(); 
 Console.WriteLine("Lenh ca = new ClassC (1,2); chay. Hay quan sat trinh tu cac 
constructor."); 
 ca = new ClassC (1,2); 
 Console.WriteLine(); 
 Console.WriteLine("Lenh ca.func1(); chay. Hay quan sat ham cu the nao chay"); 
 ca.func1(); 
 Console.WriteLine(); 
 Console.WriteLine("Lenh ca.func2(); chay. Hay quan sat ham cu the nao chay"); 
 ca.func2(); 
 Console.WriteLine(); 
 Console.WriteLine("Lenh cc.func3(); chay. Hay quan sat ham cu the nao chay"); 
 cc.func3(); //bi loi vi func3 la ham private 
 Console.WriteLine(); 
 Console.WriteLine("Lenh cc.func4(); chay. Hay quan sat ham cu the nao chay"); 
 ca.func4(); 
 Console.WriteLine(); 
 Console.Write("Ấn Enter ₫ể dừng chương trình : "); 
 Console.Read(); 
 } 
 } //kết thúc class 
} //kết thúc namespace 
4. Dời chuột về phần tử gốc của cây Project trong cửa sổ “Solution Explorer”, ấn phải chuột 
vào nó ₫ể hiển thị menu lệnh, chọn chức năng Add.New Item ₫ể hiển thị cửa sổ “Add 
New Item”, chọn mục “Interface”, hiệu chỉnh tên interface là IA.cs, chọn button Add ₫ể 
máy tạo 1 interface mới. 
5. Cửa sổ soạn code cho interface IA ₫ược hiển thị, ta ₫ịnh nghĩa interface ₫ơn giản như 
sau : 
namespace UseObject { 
 interface IA { 
 void func2(); //hàm dịch vụ duy nhất trong interface 
 } 
} 
6. Dời chuột về phần tử gốc của cây Project trong cửa sổ “Solution Explorer”, ấn phải chuột 
vào nó ₫ể hiển thị menu lệnh, chọn chức năng Add.Class ₫ể hiển thị cửa sổ “Add New 
Item”, chọn mục “Class”, hiệu chỉnh tên class là ClassA.cs, chọn button Add ₫ể máy tạo 
1 class mới. 
7. Khi cửa sổ soạn code cho class ClassA hiển thị, hiệu chỉnh nội dung của class như sau : 
namespace UseObject { 
 class ClassA : IA { 
 private int i; 
 protected double d; 
 //contructor 0 tham số 
 public ClassA() : base() { 
Trang 3 
 i = 1; d = 1.1416; 
 Console.WriteLine("Constructor for ClassA() is running..."); 
 } 
 //contructor 2 tham số 
 public ClassA(int i, double d) : base() { 
 this.i = i; this.d = d; 
 Console.WriteLine("Constructor for ClassA(i,d) is running..."); 
 } 
 //destructor 
 ~ClassA() { 
 Console.WriteLine("Destructor for ClassA is running..."); 
 } 
 //hàm func1 không thể bị override 
 public int func1() { 
 Console.WriteLine("Ham ClassA::func1 chay."); 
 return 1; 
 } 
 //hàm func2 có thể bị override 
 virtual public void func2() { 
 Console.WriteLine("Ham ClassA::func2 chay."); 
 } 
 //hàm func3 không thể bị override 
 private void func3() { 
 Console.WriteLine("Ham ClassA::func3 chay."); 
 } 
 //hàm func4 không thể bị override 
 public void func4() { 
 Console.WriteLine("Ham ClassA::func4 chay."); 
 func1(); //lien ket tinh --> khong da xa 
 func2(); //lien ket dong --> da xa 
 } 
 } 
} 
8. Dời chuột về phần tử gốc của cây Project trong cửa sổ “Solution Explorer”, ấn phải chuột 
vào nó ₫ể hiển thị menu lệnh, chọn chức năng Add.Class ₫ể hiển thị cửa sổ “Add New 
Item”, chọn mục “Class”, hiệu chỉnh tên class là ClassB.cs, chọn button Add ₫ể máy tạo 
1 class mới. 
9. Khi cửa sổ soạn code cho class ClassB hiển thị, hiệu chỉnh nội dung của class như sau : 
namespace UseObject { 
 class ClassB : ClassA { 
 //contructor 0 tham số 
 public ClassB() : base() { 
 Console.WriteLine("Constructor for ClassB() is running..."); 
Trang 4 
 } 
 //contructor 2 tham số 
 public ClassB(int i, double d) : base(i,d) { 
 Console.WriteLine("Constructor for ClassB(i,d) is running..."); 
 } 
 //destructor 
 ~ClassB() { 
 Console.WriteLine("Destructor for ClassB is running..."); 
 } 
 /* không cho phép override hàm func1 
 public override int func1() { 
 Console.WriteLine("Ham ClassB::func1 chay."); 
 return 1; 
 } */ 
 //override hàm func2 
 public override void func2() { 
 Console.WriteLine("Ham ClassB::func2 chay."); 
 } 
 } 
} 
10. Dời chuột về phần tử gốc của cây Project trong cửa sổ “Solution Explorer”, ấn phải chuột 
vào nó ₫ể hiển thị menu lệnh, chọn chức năng Add.Class ₫ể hiển thị cửa sổ “Add New 
Item”, chọn mục “Class”, hiệu chỉnh tên class là ClassB.cs, chọn button Add ₫ể máy tạo 
1 class mới. 
11. Khi cửa sổ soạn code cho class ClassB hiển thị, hiệu chỉnh nội dung của class như sau : 
namespace UseObject { 
 class ClassC : ClassB { 
 //contructor 0 tham số 
 public ClassC() : base() { 
 Console.WriteLine("Constructor for ClassC() is running..."); 
 } 
 //contructor 2 tham số 
 public ClassC(int i, double d) : base (i,d) { 
 Console.WriteLine("Constructor for ClassC(i,d) is running..."); 
 } 
 //destructor 
 ~ClassC() { 
 Console.WriteLine("Destructor for ClassC is running..."); 
 Console.Write("Ấn Enter ₫ể chạy tiếp : "); 
 Console.Read(); 
 } 
 /* không cho phép override hàm func1 
Trang 5 
 public override int func1() { 
 Console.WriteLine("Ham ClassC::func1 chay."); 
 return 1; 
 }*/ 
 //override hàm func2 
 public override void func2() { 
 Console.WriteLine("Ham ClassC::func2 chay."); 
 } 
 } 
} 
12. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Ta thấy máy báo lỗi ở 
lệnh cc.func3(); vì func3() có tầm vực private nên không thể truy xuất từ ngoài. 
13. Hãy chú thích dòng lệnh bị lỗi rồi dịch và chạy lại ứng dụng, cửa sổ Console hiển thị các 
thông báo xuất của chương trình. Hãy kiểm tra từng lệnh xem ₫iều gì xảy ra và cố gắng lý 
giải kết quả. 
14. Hãy hiệu chỉnh lệnh ₫ịnh nghĩa biến ClassA ca ở ₫ầu hàm Main thành : 
IA ca = new ClassA(); 
rồi dịch và chạy lại ứng dụng. Máy sẽ báo lỗi ở các hàng lệnh ca.func1(); Lý giải : vì biến 
ca có kiểu là interface IA nên ta chỉ có thể truy xuất ₫úng 1 hàm func2 trong interface mà 
thôi, mọi chi tiết của ₫ối tượng ₫ược tham khảo ₫ều bị che dấu. 
Trang 1 
MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG 
Bài thực hành số 5.1 : Xây dựng chương trình giải phương trình bậc 2 dùng 
giao diện ₫ồ họa trực quan 
I. Mục tiêu : 
 Giúp SV làm quen với qui trình ₫iển hình ₫ể xây dựng một ứng dụng dùng giao diện 
₫ồ họa trực quan bằng môi trường Visual Studio .Net. 
II. Nội dung : 
 Thiết kế trực quan form giao diện của chương trình giải phương trình bậc 2, khai báo 
hàm xử lý sự kiện, viết code cho hàm xử lý sự kiện ₫ể giải phương trình bậc 2. 
III. Chuẩn ₫ầu ra : 
 Sinh viên nắm vững và dùng thành thạo qui trình kỹ thuật ₫ể thiết kế trực quan form 
giao diện của chương trình, thiết lập giá trị các thuộc tính cho từng phần tử giao diện, 
khai báo hàm xử lý sự kiện cho sự kiện quan tâm của ₫ối tượng giao diện, viết code 
cho hàm xử lý sự kiện ₫ể thực hiện giải thuật có ₫ộ phức tạp trung bình. 
IV. Qui trình : 
1. Chạy VS .Net, chọn menu File.New.Project ₫ể hiển thị cửa sổ New Project. 
2. Mở rộng mục Visual C# trong TreeView "Project Types", chọn mục Window, chọn icon 
"Windows Application" trong listbox "Templates" bên phải, thiết lập thư mục chứa Project 
trong listbox "Location", nhập tên Project vào textbox "Name:" (td. Form_GPTB2), click 
button OK ₫ể tạo Project theo các thông số ₫ã khai báo. 
3. Form ₫ầu tiên của ứng dụng ₫ã hiển thị trong cửa sổ thiết kế, việc thiết kế form là quá 
trình lặp 4 thao tác tạo mới/xóa/hiệu chỉnh thuộc tính/tạo hàm xử lý sự kiện cho từng ₫ối 
tượng cần dùng trong form. 
4. Nếu cửa sổ ToolBox chưa hiển thị chi tiết, chọn menu View.Toolbox ₫ể hiển thị nó 
(thường nằm ở bên trái màn hình). Click chuột vào button (Auto Hide) nằm ở góc trên 
phải cửa sổ ToolBox ₫ể chuyển nó về chế ₫ộ hiển thị thường trực. Duyệt tìm phần tử 
Label (trong nhóm Common Controls), chọn nó, dời chuột về vị trí thích hợp trong form và 
vẽ nó với kích thước mong muốn. Hiệu chỉnh thuộc tính Text = "Nhap a :". Nếu cần, hãy 
thay ₫ổi vị trí và kích thước của Label và của Form. 
5. Duyệt tìm phần tử TextBox (trong nhóm Common Controls), chọn nó, dời chuột về vị trí 
bên phải Label vừa vẽ và vẽ nó với kích thước mong muốn. Hiệu chỉnh thuộc tính (Name) 
= txtA. Nếu cần, hãy thay ₫ổi vị trí và kích thước của TextBox. 
6. Lặp lại các bước 4, 5 ₫ể vẽ 2 Label "Nhập b :", "Nhập c :", 2 TextBox có (Name) = txtB, 
txtC, 1 button "Bắt ₫ầu giải" có (Name) = btnStart, 3 Label có (Name) lần lượt là 
lblKetqua, lblX1, lblX2. 
Đối với các ₫ối tượng giống nhau, ta có thể dùng kỹ thuật Copy-Paste ₫ể nhân bản vô 
tính chúng cho dễ dàng. 
Sau khi thiết kế xong, Form có dạng sau : 
Trang 2 
7. Dời chuột về button "Bắt ₫ầu giải", ấn kép chuột vào nó ₫ể tạo hàm xử lý sự kiện Click 
chuột cho button, cửa sổ mã nguồn sẽ hiển thị ₫ể ta bắt ₫ầu viết code cho hàm. Lưu ý 
rằng ₫ể tạo hàm xử lý sự kiện bất kỳ cho ₫ối tượng 1 cách chính quy, ta phải hiển thị cửa 
sổ thuộc tính của ₫ối tượng, rồi hiển thị danh sách các sự kiện rồi mới ₫ịnh nghĩa hàm xử 
lý sự kiện mong muốn. 
8. Viết code cho hàm btnStart_Click() như sau : 
 private void btnStart_Click(object sender, EventArgs e) 
 { 
 NhapABC(); //nhập a,b,c 
 GiaiPT(); //giải phương trình 
 XuatKetqua(); //xuất kết quả 
 } 
9. Hiệu chỉnh hàm khởi tạo form như sau : 
 public Form1() { 
 InitializeComponent(); 
 //xóa nội dung ban ₫ầu của các Label kết quả 
 lblKetqua.Text = lblX1.Text = lblX2.Text = ""; 
 } 
10. Dời chuột về ₫ầu class Form1, viết thêm ₫oạn code ₫ịnh nghĩa các thuộc tính và hàm 
chức năng cần dùng sau ₫ây : 
 //₫ịnh nghĩa các biến cần dùng ₫ể thực hiện giải phương trình bậc 2 
 double a, b, c; 
 double delta; 
 double x1, x2; 
 //₫ịnh nghĩa hàm nhập 3 thông số a,b,c của phương trình bậc 2 
 void NhapABC() 
Trang 3 
 { 
 a = Double.Parse(txtA.Text); 
 b = Double.Parse(txtB.Text); 
 c = Double.Parse(txtC.Text); 
 } 
 //₫ịnh nghĩa hàm tính nghiệm của phương trình bậc 2 
 void GiaiPT() 
 { 
 //tính biệt số delta của phương trình 
 delta = b * b - 4 * a * c; 
 if (delta >= 0) 
 { //nếu có nghiệm thực 
 x1 = (-b + Math.Sqrt(delta)) / 2 / a; 
 x2 = (-b - Math.Sqrt(delta)) / 2 / a; 
 } 
 } 
 //₫ịnh nghĩa hàm xuất kết quả 
 void XuatKetqua() 
 { 
 if (delta < 0) 
 { 
 //báo vô nghiệm 
 lblKetqua.Text = "Phương trình vô nghiệm"; 
 lblX1.Text = ""; 
 lblX2.Text = ""; 
 } 
 else 
 { //báo có 2 nghiệm 
 lblKetqua.Text = "Phương trình có 2 nghiệm thực : "; 
 lblX1.Text = "X1 = " + x1.ToString(); 
 lblX2.Text = "X2 = " + x2.ToString(); 
 } 
 } 
11. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Hãy thử nhập từng bộ ba 
(a,b,c) của phương trình bậc 2 rồi ấn button "Bắt ₫ầu giải" ₫ể giải và xem kết quả. 
Trang 1 
MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG 
Bài thực hành số 5.2 : Xây dựng chương trình giải phương trình bậc 2 dùng 
giao diện ₫ồ họa trực quan 
I. Mục tiêu : 
 Giúp SV làm quen với qui trình ₫iển hình ₫ể xây dựng một ứng dụng dùng giao diện 
₫ồ họa trực quan bằng môi trường Visual Studio .Net. 
II. Nội dung : 
 Lập trình tạo form giao diện của chương trình giải phương trình bậc 2, khai báo thủ 
tục xử lý sự kiện, viết code cho thủ tục xử lý sự kiện ₫ể giải phương trình bậc 2. 
III. Chuẩn ₫ầu ra : 
 Sinh viên nắm vững và dùng thành thạo các ₫oạn code ₫ể tạo form giao diện của 
chương trình, thiết lập giá trị các thuộc tính cho từng phần tử giao diện, khai báo thủ 
tục xử lý sự kiện cho sự kiện quan tâm của ₫ối tượng giao diện, viết code cho thủ tục 
xử lý sự kiện ₫ể thực hiện giải thuật có ₫ộ phức tạp trung bình. 
IV. Phân tích : 
Chương trình chứa 1 ₫ối tượng Form, Form chứa các ₫ối tượng bên trong : 
 - 3 cặp ₫ối tượng (Label+TextBox) ₫ể người dùng nhập 3 tham số a,b,c 
 - 1 ₫ối tượng Button ₫ể kích hoạt chức năng giải phương trình 
 - 3 ₫ối tượng Label ₫ể hiển thị kết quả 
Thay vì thiết kế trực quan các ₫ối tượng trong Form như bài 5.1, bài thực hành này sẽ miêu tả 
qui trình viết code VC# ₫ể tạo các ₫ối tượng giao diện ₫ược chứa trong Form. 
V. Qui trình : 
1. Chạy VS .Net, chọn menu File.New.Project ₫ể hiển thị cửa sổ New Project. 
2. Mở rộng mục Visual C# trong TreeView "Project Types", chọn mục Windows, chọn icon 
"Windows Forms Application" trong listbox "Templates" bên phải, thiết lập thư mục chứa 
Project trong listbox "Location", nhập tên Project vào textbox "Name:" (thí dụ 
Form_GPTB2_P), click button OK ₫ể tạo Project theo các thông số ₫ã khai báo. 
3. Form ₫ầu tiên của ứng dụng ₫ã hiển thị trong cửa sổ thiết kế với kích thước mặc ₫ịnh 
(thường chưa phù hợp với yêu cầu của ứng dụng). Form lúc ₫ầu còn trống, chưa có phần 
tử giao diện nào bên trong. 
4. Chọn Form ₫ể hiển thị cửa sổ thuộc tính của Form, click icon trong cửa sổ thuộc tính 
của Form ₫ể hiển thị danh sách các sự kiện của Form, duyệt tìm sự kiện Load, ấn kép 
chuột vào comboBox bên phải sự kiện Load ₫ể máy tạo tự ₫ộng hàm xử lý cho sự kiện 
này. 
5. Khi cửa sổ soạn code cho hàm Form_Load() hiển thị, ta thấy hàm này vẫn còn trống. Hãy 
viết code cho hàm Form_Load() như sau : 
 private void Form1_Load(object sender, EventArgs e) 
 { 
 //Tạo Label Label1 
 Label1 = new Label(); 
 Label1.Name = "Label1"; 
 Label1.AutoSize = true; 
 Label1.Location = new Point(13, 11); 
Trang 2 
 Label1.Size = new Size(62, 17); 
 Label1.TabIndex = 0; 
 Label1.Text = "Nhập a :"; 
 Controls.Add(Label1); //add Label vào Form 
 //Tạo TextBox txtA 
 txtA = new TextBox(); 
 txtA.Name = "txtA"; 
 txtA.Location = new Point(96, 11); 
 txtA.Size = new Size(239, 22); 
 txtA.TabIndex = 1; 
 Controls.Add(txtA) ; //add TextBox vào Form 
 //Tạo Label Label2 
 Label2 = new Label(); 
 Label2.Name = "Label2"; 
 Label2.AutoSize = true; 
 Label2.Location = new Point(13, 51); 
 Label2.Size = new Size(62, 17); 
 Label2.TabIndex = 2; 
 Label2.Text = "Nhập b :"; 
 Controls.Add(Label2); //add Label vào Form 
 //Tạo TextBox txtB 
 txtB = new TextBox(); 
 txtB.Name = "txtB"; 
 txtB.Location = new Point(96, 51); 
 txtB.Size = new Size(239, 22); 
 txtB.TabIndex = 3; 
 Controls.Add(txtB); //add TextBox vào Form 
 //Tạo Label Label3 
 Label3 = new Label(); 
 Label3.Name = "Label3"; 
 Label3.AutoSize = true; 
 Label3.Location = new Point(13, 90); 
 Label3.Size = new Size(61, 17); 
 Label3.TabIndex = 4; 
 Label3.Text = "Nhập c :"; 
 Controls.Add(Label3); //add Label vào Form 
 //Tạo TextBox txtC 
 txtC = new TextBox(); 
 txtC.Name = "txtC"; 
 txtC.Location = new Point(96, 90); 
 txtC.Size = new Size(239, 22); 
 txtC.TabIndex = 5; 
 Controls.Add(txtC); //add TextBox vào Form 
 //Tạo button Start 
 btnStart = new Button(); 
 btnStart.Name = "txtStart"; 
 btnStart.Location = new Point(81, 126); 
Trang 3 
 btnStart.Size = new Size(164, 25); 
 btnStart.TabIndex = 6; 
 btnStart.Text = "Bắt ₫ầu giải"; 
 btnStart.UseVisualStyleBackColor = true; 
 Controls.Add(btnStart); //add Button vào Form 
 //kết hợp hàm xử lý Click chuột 
 btnStart.Click += new EventHandler(btnStart_Click); 
 //Tạo Label lblKetqua 
 lblKetqua = new Label(); 
 lblKetqua.Name = "lblKetqua"; 
 lblKetqua.AutoSize = true; 
 lblKetqua.Location = new Point(15, 165); 
 lblKetqua.Size = new Size(51, 17); 
 lblKetqua.TabIndex = 7; 
 lblKetqua.Text = ""; 
 Controls.Add(lblKetqua); //add Label vào Form 
 //Tạo Label lblX1 
 lblX1 = new Label(); 
 lblX1.Name = "lblX1"; 
 lblX1.AutoSize = true; 
 lblX1.Location = new Point(15, 193); 
 lblX1.Size = new Size(51, 17); 
 lblX1.TabIndex = 8; 
 lblX1.Text = ""; 
 Controls.Add(lblX1); //add Label vào Form 
 //Tạo Label lblX2 
 lblX2 = new Label(); 
 lblX2.Name = "lblX2"; 
 lblX2.AutoSize = true; 
 lblX2.Location = new Point(15, 223); 
 lblX2.Size = new Size(51, 17); 
 lblX2.TabIndex = 9; 
 lblX2.Text = ""; 
 Controls.Add(lblX2); //add Label vào Form 
 //Thiết lập 1 số thuộc tính cho Form1 
 ClientSize = new Size(348, 255); 
 Name = "Form1"; 
 Text = "Giải phương trình bậc 2 "; 
 } 
 } 
6. Dời chuột lên ₫ầu class Form1 rồi viết tiếp ₫oạn code ₫ịnh nghĩa các thuộc tính và tác vụ 
cần dùng sau ₫ây : 
 //₫ịnh nghĩa cặp Label + TextBox phục vụ nhập a 
 private Label Label1; 
 private TextBox txtA; 
 //₫ịnh nghĩa cặp Label + TextBox phục vụ nhập b 
Trang 4 
 private Label Label2; 
 private TextBox txtB; 
 //₫ịnh nghĩa cặp Label + TextBox phục vụ nhập c 
 private Label Label3; 
 private TextBox txtC; 
 //₫ịnh nghĩa Button thực hiện giải phương trình 
 private Button btnStart; 
 //₫ịnh nghĩa 3 Label hiển thị kết quả giải phương trình 
 private Label lblKetqua; 
 private Label lblX1; 
 private Label lblX2; 
 //₫ịnh nghĩa các biến cần dùng 
 double a, b, c; 
 double delta; 
 double x1, x2; 
 //₫ịnh nghĩa hàm nhập 3 thông số a,b,c của phương trình bậc 2 
 void NhapABC() { 
 a = Double.Parse(txtA.Text); 
 b = Double.Parse(txtB.Text); 
 c = Double.Parse(txtC.Text); 
 } 
 //₫ịnh nghĩa hàm tính nghiệm của phương trình bậc 2 
 void GiaiPT() { 
 //tính biệt số delta của phương trình 
 delta = b * b - 4 * a * c; 
 if (delta >= 0) { //nếu có nghiệm thực 
 x1 = (-b + Math.Sqrt(delta)) / 2 / a; 
 x2 = (-b - Math.Sqrt(delta)) / 2 / a; 
 } 
 } 
 //₫ịnh nghĩa hàm xuất kết quả 
 void XuatKetqua() { 
 if (delta < 0) { 
 //báo vô nghiệm 
 lblKetqua.Text = "Phương trình vô nghiệm"; 
 lblX1.Text = ""; 
 lblX2.Text = ""; 
 } else { //báo có 2 nghiệm 
 lblKetqua.Text = "Phương trình có 2 nghiệm thực : "; 
 lblX1.Text = "X1 = " + x1.ToString(); 
 lblX2.Text = "X2 = " + x2.ToString(); 
 } 
 } 
 //₫ịnh nghĩa hàm xử lý Click trên button "Bắt ₫ầu giải" 
 private void btnStart_Click(object sender, EventArgs e) 
Trang 5 
 { 
 NhapABC(); //nhập a,b,c 
 GiaiPT(); //giải phương trình 
 XuatKetqua(); //xuất kết quả 
 } 
7. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Hãy thử nhập từng bộ ba 
(a,b,c) của phương trình bậc 2 rồi ấn button "Bắt ₫ầu giải" ₫ể giải và xem kết quả. 
Trang 1 
MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG 
Bài thực hành số 5.3 : Xây dựng form giao diện có hình dạng tùy ý 
I. Mục tiêu : 
 Giúp SV làm quen với qui trình ₫iển hình ₫ể xây dựng một ứng dụng dùng Form giao 
diện với hình dạng tùy ý bằng môi trường Visual Studio .Net. 
II. Nội dung : 
 Lập trình tạo form giao diện của chương trình giải phương trình bậc 2 với hình dạng 
tùy ý, khai báo thủ tục xử lý sự kiện, viết code cho thủ tục xử lý sự kiện ₫ể giải phương 
trình bậc 2. 
III. Chuẩn ₫ầu ra : 
 Sinh viên nắm vững và thực hiện thành thạo qui trình ₫iển hình ₫ể xây dựng một ứng 
dụng dùng Form giao diện với hình dạng tùy ý bằng môi trường Visual Studio .Net, 
thiết lập giá trị các thuộc tính cho từng phần tử giao diện, khai báo thủ tục xử lý sự 
kiện cho sự kiện quan tâm của ₫ối tượng giao diện, viết code cho thủ tục xử lý sự kiện 
₫ể thực hiện giải thuật có ₫ộ phức tạp trung bình. 
IV. Phân tích : 
Chương trình chứa 1 ₫ối tượng Form, hình dạng của Form sẽ do 1 hình bitmap qui ₫ịnh (chứ 
không phải là hình chữ nhật như bình thường), Form chứa các ₫ối tượng bên trong : 
 - 3 cặp ₫ối tượng (Label+TextBox) ₫ể người dùng nhập 3 tham số a,b,c 
 - 1 ₫ối tượng Button ₫ể kích hoạt chức năng giải phương trình 
 - 3 ₫ối tượng Label ₫ể hiển thị kết quả. 
 - 1 ₫ối tượng Button ₫ể ₫óng Form và dừng chương trình. 
V. Qui trình : 
1. Copy thư mục Form_GPTB2 quản lý Project chương trình của bài 5.1 thành thư mục mới 
có tên là Form_NonRec_GPTB2. 
 2. Dùng chương trình xử lý ảnh ưa thích (Paint, PhotoShop, Corel Draw,...) soạn ảnh bitmap 
miêu tả hình dạng và kích thước của Form, thí dụ như hình sau : 
Trang 2 
 Lưu ảnh lên file (thí dụ d:\bgform.bmp). Lưu ý ảnh qui ₫ịnh hình dạng của Form nên có 
các tính chất thiết yếu sau ₫ây : 
- kích thước phải phù hợp với nhu cầu của Form ứng dụng. 
- màu vùng bao phủ Form phải ₫ồng nhất và dễ xác ₫ịnh bằng phần mềm, thí dụ màu 
trắng (255,255,255) hay ₫en (0,0,0). 
- tất cả các phần tử bên trong qui ₫ịnh vùng của Form phải khác màu với màu nền bao 
phủ Form. 
3. Chạy VS .Net, chọn menu File.Open.Project và mở lại Project ₫ược chứa trong thư mục 
Form_NonRec_GPTB2. 
4. Dời chuột về cửa sổ "Solution Explorer", ấn phải chuột vào mục Form1.cs ₫ể hiển thị 
menu lệnh kèm theo nó, chọn option "View Designer" ₫ể hiển thị lại cửa sổ thiết kế 
Form1. 
5. Chọn Form ₫ể hiển thị cửa sổ thuộc tính của Form, duyệt tìm thuộc tính 
BackgroundImage, ấn chuột vào button ... bên phải thuộc tính này rồi khai báo file ảnh 
d:\bgform.bmp làm ảnh nên cho Form1. 
6. Chỉnh lại kích thước của Form sao cho chứa trọn vẹn ảnh nền bên trong Form. Sắp xếp 
lại các ₫ối tượng bên trong Form sao cho chúng nằm gọn trong vùng ảnh nền. Thiết lập 
thuộc tính qui ₫ịnh màu nền (BackColor) cho các ₫ối tượng giao diện sao cho khác biệt 
với màu vùng bao phủ Form. 
7. Tiếp tục duyệt tìm thuộc tính FormBorderStyle của Form và hiệu chỉnh thành None. 
8. Tiếp tục duyệt tìm thuộc tính TransparencyKey của Form và hiệu chỉnh thành màu trắng 
(White). Đây là màu của vùng bao phủ vùng ảnh miêu tả hình dạng của Form. 
9. Vẽ thêm 1 button ở vị trí thích hợp trong Form có (Name) = btnClose, Text = "Close" ₫ể 
phục vụ ₫óng Form và dừng chương trình. Tạo hàm xử lý sự kiện Click chuột trên button 
này và viết code cho hàm như sau : 
 private void btnClose_Click(object sender, EventArgs e) 
 { 
 Close(); //₫óng Form và dừng chương trình 
 } 
10. Dời chuột về cửa sổ "Solution Explorer", ấn phải chuột vào mục Form1.cs ₫ể hiển thị 
menu lệnh kèm theo nó, chọn option "View Designer" ₫ể hiển thị lại cửa sổ thiết kế 
Form1. Chọn Form ₫ể hiển thị cửa sổ thuộc tính của Form, click icon trong cửa sổ 
thuộc tính của Form ₫ể hiển thị danh sách các sự kiện của Form, tạo lần lượt các hàm xử 
lý sự kiện MouseDown, MouseMove, MouveUp cho Form. 
11. Hãy viết code cho 3 hàm xử lý chuột vừa tạo ra ở bước 8 như sau (phục vụ dời vị trí Form 
ứng dụng khi nó ₫ang chạy) : 
 private void Form1_MouseDown(object sender, MouseEventArgs e) 
 { 
 int xOffset, yOffset; 
 if (e.Button == MouseButtons.Left) { 
 xOffset = -e.X - SystemInformation.FrameBorderSize.Width; 
 yOffset = -e.Y - SystemInformation.CaptionHeight - 
SystemInformation.FrameBorderSize.Height; 
 mouseOffset = new Point(xOffset, yOffset); 
 isMouseDown = true; 
Trang 3 
 } 
 } 
 private void Form1_MouseUp(object sender, MouseEventArgs e) 
 { 
 if (e.Button == MouseButtons.Left) isMouseDown = false; 
 } 
 private void Form1_MouseMove(object sender, MouseEventArgs e) 
 { 
 if (isMouseDown) { 
 Point mousePos = Control.MousePosition; 
 mousePos.Offset(mouseOffset.X, mouseOffset.Y); 
 Location = mousePos; 
 } 
 } 
12. Dời chuột lên ₫ầu class Form1 rồi viết tiếp ₫oạn code ₫ịnh nghĩa các thuộc tính sau ₫ây : 
 //₫ịnh nghĩa các biến cần dùng ₫ể quản lý Form 
 private Point mouseOffset; 
 private Boolean isMouseDown = false; 
13. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Hãy thử nhập từng bộ ba 
(a,b,c) của phương trình bậc 2 rồi ấn button "Bắt ₫ầu giải" ₫ể giải và xem kết quả. 
14. Hãy thử drag mouse ₫ể dời Form từ vị trí này sang vị trí khác. 
15. Hãy click vào button Close ₫ể dừng chương trình. 
Trang 1 
MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG 
Bài thực hành số 5.4 : Xây dựng form giao diện có hình dạng tùy ý 
I. Mục tiêu : 
 Giúp SV làm quen với qui trình ₫iển hình ₫ể xây dựng một ứng dụng dùng Form giao 
diện với hình dạng tùy ý bằng môi trường Visual Studio .Net. 
II. Nội dung : 
 Lập trình tạo form giao diện của chương trình giải phương trình bậc 2 với hình dạng 
tùy ý, khai báo thủ tục xử lý sự kiện, viết code cho thủ tục xử lý sự kiện ₫ể giải phương 
trình bậc 2. 
III. Chuẩn ₫ầu ra : 
 Sinh viên nắm vững và thực hiện thành thạo qui trình ₫iển hình ₫ể xây dựng một ứng 
dụng dùng Form giao diện với hình dạng tùy ý bằng môi trường Visual Studio .Net, 
thiết lập giá trị các thuộc tính cho từng phần tử giao diện, khai báo thủ tục xử lý sự 
kiện cho sự kiện quan tâm của ₫ối tượng giao diện, viết code cho thủ tục xử lý sự kiện 
₫ể thực hiện giải thuật có ₫ộ phức tạp trung bình. 
IV. Phân tích : 
Chương trình chứa 1 ₫ối tượng Form, hình dạng của Form có thể là hình chữ nhật mặc ₫ịnh 
hay sẽ do 1 hình bitmap qui ₫ịnh. Việc chuyển ₫ổi hình dạng của Form sẽ ₫ược thực hiện bởi 
yêu cầu người dùng thông qua 1 button. Form chứa các ₫ối tượng bên trong : 
 - 3 cặp ₫ối tượng (Label+TextBox) ₫ể người dùng nhập 3 tham số a,b,c 
 - 1 ₫ối tượng Button ₫ể kích hoạt chức năng giải phương trình 
 - 3 ₫ối tượng Label ₫ể hiển thị kết quả. 
 - 1 ₫ối tượng Button ₫ể ₫óng Form và dừng chương trình. 
 - 1 ₫ối tượng Button ₫ể switch hình dạng Form. 
V. Qui trình : 
1. Copy thư mục Form_GPTB2 quản lý Project chương trình của bài 5.1 thành thư mục mới 
có tên là Form_NonRec_GPTB2_P. 
 2. Dùng chương trình xử lý ảnh ưa thích (Paint, PhotoShop, Corel Draw,...) soạn ảnh bitmap 
miêu tả hình dạng và kích thước của Form, thí dụ như hình sau : 
Trang 2 
 Lưu ảnh lên file (thí dụ d:\bgform.bmp). Lưu ý ảnh qui ₫ịnh hình dạng của Form nên có 
các tính chất thiết yếu sau ₫ây : 
- kích thước phải phù hợp với nhu cầu của Form ứng dụng. 
- màu vùng bao phủ Form phải ₫ồng nhất và dễ xác ₫ịnh bằng phần mềm, thí dụ màu 
trắng (255,255,255) hay ₫en (0,0,0). 
- tất cả các phần tử bên trong qui ₫ịnh vùng làm việc của Form phải khác màu với màu 
nền bao phủ Form. 
3. Chạy VS .Net, chọn menu File.Open.Project và mở lại Project ₫ược chứa trong thư mục 
Form_NonRec_GPTB2_P. 
4. Dời chuột về cửa sổ "Solution Explorer", ấn phải chuột vào mục Form1.cs ₫ể hiển thị 
menu lệnh kèm theo nó, chọn option "View Designer" ₫ể hiển thị lại cửa sổ thiết kế 
Form1. 
5. Chọn Form ₫ể hiển thị cửa sổ thuộc tính của Form, duyệt tìm thuộc tính 
BackgroundImage, ấn chuột vào button ... bên phải thuộc tính này rồi khai báo file ảnh 
d:\bgform.bmp làm ảnh nên cho Form1. 
6. Chỉnh lại kích thước của Form sao cho chứa trọn vẹn ảnh nền bên trong Form. Sắp xếp 
lại các ₫ối tượng bên trong Form sao cho chúng nằm gọn trong vùng ảnh nền. Thiết lập 
thuộc tính qui ₫ịnh màu nền (BackColor) cho các ₫ối tượng giao diện sao cho khác biệt 
với màu vùng bao phủ Form. 
7. Vẽ thêm 1 button ở vị trí thích hợp trong Form có (Name) = btnClose, Text = "Close" ₫ể 
phục vụ ₫óng Form và dừng chương trình. Tạo hàm xử lý sự kiện Click chuột trên button 
này và viết code cho hàm như sau : 
 private void btnClose_Click(object sender, EventArgs e) 
 { 
 Close(); //₫óng Form và dừng chương trình 
 } 
8. Dời chuột về cửa sổ "Solution Explorer", ấn phải chuột vào mục Form1.cs ₫ể hiển thị 
menu lệnh kèm theo nó, chọn option "View Designer" ₫ể hiển thị lại cửa sổ thiết kế 
Trang 3 
Form1. Vẽ thêm 1 label "Chọn hình dạng của form" và 1 ComboBox có (Name)=cbTrans 
có 4 options "Hình chữ nhật bình thường", "Hình do ảnh nền qui ₫ịnh", "Hình ₫a giác", 
"Hình chữ nhật bo ₫ầu". Tạo hàm xử lý sự kiện SelectedIndexChanged cho cbTrans và 
viết code cho hàm như sau : 
 private void cbTrans_SelectedIndexChanged(object sender, EventArgs e) 
 { 
 int i = cbTrans.SelectedIndex; 
 int h, w; 
 GraphicsPath path; 
 Bitmap bm; 
 switch (i) 
 { 
 case 0: //hình chữ nhật 
 this.BackgroundImage = null; 
 this.FormBorderStyle = FormBorderStyle.Sizable; 
 this.Region = null; 
 fNonRec = false; 
 break; 
 case 1: //hình do ảnh nền 
 bm = (Bitmap)Bitmap.FromFile("d:\\bgform.bmp"); 
 Color col = bm.GetPixel(1, 1); 
 this.ClientSize = new Size(bm.Width, bm.Height); 
 this.Region = ConvertB2R(bm, col); 
 this.BackgroundImage = bm; 
 this.FormBorderStyle = FormBorderStyle.None; 
 break; 
 case 2: //hình ₫a giác 
 path = new GraphicsPath(); 
 h = this.ClientSize.Height; 
 w = this.ClientSize.Width; 
 path.AddLine(new Point(0, h / 4), new Point(w / 4, 0)); 
 path.AddLine(new Point(w / 4, 0), new Point((3 * w) / 4, 0)); 
 path.AddLine(new Point((3 * w) / 4, 0), new Point(w, h / 4)); 
 path.AddLine(new Point(w, h / 4), new Point(w, (3 * h) / 4)); 
 path.AddLine(new Point(w, (3 * h) / 4), new Point((3 * w) / 4, h)); 
 path.AddLine(new Point((3 * w) / 4, h), new Point(w / 4, h)); 
 path.AddLine(new Point(w / 4, h), new Point(0, (3 * h) / 4)); 
 path.AddLine(new Point(0, (3 * h) / 4), new Point(0, h / 4)); 
 //tạo vùng giới hạn bởi các path vẽ ở trên 
 this.Region = new Region(path); 
 bm = (Bitmap)Bitmap.FromFile("d:\\bgform1.bmp"); 
 this.BackgroundImage = bm; 
 this.FormBorderStyle = FormBorderStyle.None; 
 break; 
 case 3: //hình chữ nhật bo tròn 
 path = new GraphicsPath(); 
 h = this.ClientSize.Height; 
 w = this.ClientSize.Width; 
 path.AddArc(0, 0, w / 2, h / 2, 180, 90); 
 path.AddLine(new Point(w / 4, 0), new Point((3 * w) / 4, 0)); 
Trang 4 
 path.AddArc(w/2, 0, w / 2, h / 2,270,90); 
 path.AddLine(new Point(w, h / 4), new Point(w, (3 * h) / 4)); 
 path.AddArc(w/2, h/2, w / 2, h / 2,0,90); 
 path.AddLine(new Point((3 * w) / 4, h), new Point(w / 4, h)); 
 path.AddArc(0, h/2, w / 2, h / 2,90,90); 
 path.AddLine(new Point(0, (3 * h) / 4), new Point(0, h / 4)); 
 //tạo vùng giới hạn bởi các path vẽ ở trên 
 this.Region = new Region(path); 
 bm = (Bitmap)Bitmap.FromFile("d:\\bgform2.bmp"); 
 this.BackgroundImage = bm; 
 this.FormBorderStyle = FormBorderStyle.None; 
 break; 
 } 
 } 
9. Dời chuột về cửa sổ "Solution Explorer", ấn phải chuột vào mục Form1.cs ₫ể hiển thị 
menu lệnh kèm theo nó, chọn option "View Designer" ₫ể hiển thị lại cửa sổ thiết kế 
Form1. Chọn Form ₫ể hiển thị cửa sổ thuộc tính của Form, click icon trong cửa sổ 
thuộc tính của Form ₫ể hiển thị danh sách các sự kiện của Form, tạo lần lượt các hàm xử 
lý sự kiện MouseDown, MouseMove, MouveUp cho Form. 
10. Hãy viết code cho 3 hàm xử lý chuột vừa tạo ra ở bước 9 như sau (phục vụ dời vị trí Form 
ứng dụng khi nó ₫ang chạy) : 
 private void Form1_MouseDown(object sender, MouseEventArgs e) 
 { 
 int xOffset, yOffset; 
 if (e.Button == MouseButtons.Left) { 
 xOffset = -e.X - SystemInformation.FrameBorderSize.Width; 
 yOffset = -e.Y - SystemInformation.CaptionHeight - 
SystemInformation.FrameBorderSize.Height; 
 mouseOffset = new Point(xOffset, yOffset); 
 isMouseDown = true; 
 } 
 } 
 private void Form1_MouseUp(object sender, MouseEventArgs e) 
 { 
 if (e.Button == MouseButtons.Left) isMouseDown = false; 
 } 
 private void Form1_MouseMove(object sender, MouseEventArgs e) 
 { 
 if (isMouseDown) { 
 Point mousePos = Control.MousePosition; 
 mousePos.Offset(mouseOffset.X, mouseOffset.Y); 
 Location = mousePos; 
 } 
 } 
11. Dời chuột lên ₫ầu file (trước phát biểu class Form1) rồi thêm các lệnh using sau ₫ây : 
using System.Drawing.Imaging; 
using System.Drawing.Drawing2D; 
Trang 5 
12. Dời chuột về ₫ầu class Form1 rồi viết tiếp ₫oạn code ₫ịnh nghĩa các thuộc tính và các 
hàm dịch vụ sau ₫ây : 
 //₫ịnh nghĩa các biến cần dùng ₫ể quản lý Form 
 private Point mouseOffset; 
 private Boolean isMouseDown = false; 
 //hàm kiểm tra 1 pixel ảnh có trùng màu qui ₫ịnh không 
 bool Equal(Byte[] pbase, int idx, Color key) 
 { 
 if (pbase[idx] != key.B) return false; 
 if (pbase[idx] != key.G) return false; 
 if (pbase[idx] != key.R) return false; 
 if (pbase[idx] != key.A) return false; 
 return true; 
 } 
 //hàm chuyển ảnh bitmap thành Region qui ₫ịnh ₫ường viền của ảnh 
 Region ConvertB2R(Bitmap bitmap, Color Key) 
 { 
 // Dim modeFlag As Boolean = (mode = TransparencyMode.ColorKeyOpaque) 
 GraphicsUnit unit = GraphicsUnit.Pixel; 
 RectangleF boundsF = bitmap.GetBounds(ref unit); 
 Rectangle bounds = new Rectangle((int)boundsF.Left, (int)boundsF.Top, 
(int)boundsF.Width, (int)boundsF.Height); 
 //get access to the raw bits of the image 
 BitmapData bitmapData = bitmap.LockBits(bounds, ImageLockMode.ReadOnly, 
PixelFormat.Format32bppArgb); 
 //Get the address of the first line. 
 IntPtr ptr = bitmapData.Scan0; 
 //Declare an array to hold the bytes of the bitmap. 
 //This code is specific to a bitmap with 24 bits per pixels. 
 int bytes = Math.Abs(bitmapData.Stride) * bitmap.Height; 
 byte[] pbase = new byte[bytes]; 
 //Copy the RGB values into the array. 
 System.Runtime.InteropServices.Marshal.Copy(ptr, pbase, 0, bytes); 
 //avoid property accessors in the for 
 int yMax = (int)boundsF.Height; 
 int xMax = (int)boundsF.Width; 
 //to store all the little rectangles in 
 GraphicsPath path = new GraphicsPath(); 
 int isrow = 0; 
 int idx = 0; 
 int x, y; 
 for (y = 0; y <= yMax - 1; y++) 
 { 
 idx = isrow; 
 for (x = 0; x <= xMax - 1; x++) 
 { 
 //is this transparent? if ((yes, just go on with the loop 
 if (Equal(pbase, idx, Key)) 
Trang 6 
 { 
 idx = idx + 4; 
 continue; 
 } 
 //store where the scan starts 
 int x0 = x; 
 //not transparent - scan until we find the next transparent byte 
 while (x < xMax && (!Equal(pbase, idx, Key))) 
 { 
 x = x + 1; 
 idx = idx + 4; 
 } 
 //add the rectangle we have found to the path 
 path.AddRectangle(new Rectangle(x0, y, x - x0, 1)); 
 } 
 //jump to the next line 
 isrow = isrow + bitmapData.Stride; 
 } 
 //now create the region from all the rectangles 
 Region region = new Region(path); 
 //clean up 
 path.Dispose(); 
 bitmap.UnlockBits(bitmapData); 
 return region; 
 } 
13. Tìm và hiệu chỉnh lại hàm khởi tạo Form1 như sau : 
 public Form1() 
 { 
 InitializeComponent(); 
 lblKetqua.Text = lblX1.Text = lblX2.Text = ""; 
 this.BackgroundImage = null; 
 } 
14. Soạn thảo thêm 2 ảnh bitmap d:\bgform1.bmp và d:\bgform2.bmp ₫ể dùng làm ảnh nền 
cho các dạng form khác nhau. 
15. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Hãy thử nhập từng bộ ba 
(a,b,c) của phương trình bậc 2 rồi ấn button "Bắt ₫ầu giải" ₫ể giải và xem kết quả. 
16. Hãy thử chọn từng mục khác nhau trong danh sách ComboBox ₫ể chuyển Form từ hình 
chữ nhật mặc ₫ịnh ↔ hình dạng khác. 
17. Hãy thử drag mouse ₫ể dời Form từ vị trí này sang vị trí khác. 
18. Hãy click vào button Close ₫ể dừng chương trình. 
Trang 1 
MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG 
Bài thực hành số 6.1 : Xây dựng chương trình ₫ồng hồ quả lắc 
I. Mục tiêu : 
 Giúp SV làm quen với cách thức viết code ₫ể hiển thị 3 loại dữ liệu cơ bản cấu thành 
bất kỳ thông tin cần xuất : chuỗi văn bản, hình bitmap, hình ₫ồ họa toán học. 
II. Nội dung : 
 Viết code ₫ể hiển thị 3 loại dữ liệu cơ bản : chuỗi văn bản, hình bitmap, hình ₫ồ họa 
toán học và quan sát kết quả củ từng ₫oạn code. 
III. Chuẩn ₫ầu ra : 
 Sinh viên nắm vững và lập trình thành thạo các ₫oạn code ₫ể hiển thị 3 loại dữ liệu cơ 
bản : chuỗi văn bản, hình bitmap, hình ₫ồ họa toán học. 
IV. Qui trình : 
0. Dùng chương trình soạn thảo ₫ồ họa như Paint, CorelDraw, Photoshop vẽ ảnh bitmap 
của khung ₫ồng hồ, mặt ₫ồng hồ như hình dưới ₫ây rồi cất lên file c:\bgclock.bmp. 
1. Chạy VS .Net, chọn menu File.New.Project ₫ể hiển thị cửa sổ New Project. 
2. Mở rộng mục Visual C# trong TreeView "Project Types", chọn mục Windows, chọn icon 
"Windows Application" trong listbox "Templates" bên phải, thiết lập thư mục chứa Project 
trong listbox "Location", nhập tên Project vào textbox "Name:" (td. VCDongho), click 
button OK ₫ể tạo Project theo các thông số ₫ã khai báo. 
3. Form ₫ầu tiên của ứng dụng ₫ã hiển thị trong cửa sổ thiết kế, lúc này form hoàn toàn 
trống, chưa chứa ₫ối tượng giao diện nào. 
4. Nếu cửa sổ ToolBox chưa hiển thị chi tiết, chọn menu View.Toolbox ₫ể hiển thị nó 
(thường nằm ở bên trái màn hình). Click chuột vào button (Auto Hide) nằm ở góc trên 
phải cửa sổ ToolBox ₫ể chuyển nó về chế ₫ộ hiển thị thường trực. Duyệt tìm phần tử 
Timer (trong nhóm Comopents hay nhóm All Window Forms), chọn nó, dời chuột vào 
trong form (ở vị trí nào cũng ₫ược vì ₫ối tượng này không ₫ược hiển thị) và vẽ nó với kích 
thước tùy ý. Hiệu chỉnh thuộc tính (Name) = myTimer. 
5. Chọn ₫ối tượng myTimer, cửa sổ thuộc tính của nó sẽ hiển thị, click icon ₫ể hiển thị 
danh sách các sự kiện của ₫ối tượng, ấn kép chuột vào comboBox bên phải sự kiện Tick 
₫ể máy tạo tự ₫ộng hàm xử lý cho sự kiện này. 
Trang 2 
6. Viết code cụ thể cho hàm như sau : 
 //hàm phục vụ Timer 
 private void myTimer_Tick(object sender, EventArgs e) { 
 myTimer.Stop(); //dừng ₫ếm timer 
 this.Refresh(); //vẽ lại form theo giờ hiện hành 
 } 
7. Ấn phải chuột vào mục Form1.cs trong cửa sổ Solution Explorer rồi chọn option View 
Designer ₫ể hiển thị lại cửa sổ thiết kế Form. Chọn Form, cửa sổ thuộc tính của nó sẽ 
hiển thị, click icon ₫ể hiển thị danh sách các sự kiện của Form, duyệt tìm sự kiện 
Paint, ấn kép chuột vào comboBox bên phải sự kiện Paint ₫ể máy tạo tự ₫ộng hàm xử lý 
cho sự kiện này. V
            Các file đính kèm theo tài liệu này:
 tailieu.pdf tailieu.pdf