150
Trang 1 MÔN : LP TRÌNH HƯỚNG ĐỐI TƯỢNG Bài thc hành s0.1 : Viết chương trình gii phương trình bc 2 I. Mc tiêu : Giúp SV ôn li qui trình viết 1 ng dng VC# ₫ơn gin, hthng li các vn ₫ề chính ca phn mm này, ₫ể các chương còn li gii quyết chúng. II. Ni dung : Xây dng chương trình nhgii phương trình bc 2 có dng ax^2 + bx + c = 0 chy chế ₫ộ textmode (console). III. Chun ₫ầu ra : Sinh viên nm vng và viết thành tho các ng dng nhchy chế ₫ộ textmode. IV. Qui trình : 1. Chy VS .Net, chn menu File.New.Project ₫ể hin thca sNew Project. 2. Mrng mc Visual C# trong TreeView "Project Types", chn mc Windows, chn icon "Console Application" trong listbox "Templates" bên phi, thiết lp thư mc cha Project trong listbox "Location", nhp tên Project vào textbox "Name:" (td. GPTB2), click button OK ₫ể to Project theo các thông sã khai báo. 3. Ngay sau khi Project va ₫ược to ra, ca sson code cho chương trình ₫ược hin th. Hiu chnh code ca file Program.cs ₫ể có ni dung như sau : using System; namespace GPTB2 { class Program { //₫ịnh nghĩa các biến cn dùng static double a, b, c; static double delta; static double x1, x2; //₫ịnh nghĩa hàm nhp 3 thông sa,b,c ca phương trình bc 2 static void NhapABC() { String buf; Console.Write("Nhp a : "); buf= Console.ReadLine(); a = Double.Parse(buf); Console.Write("Nhp b : "); buf = Console.ReadLine(); b = Double.Parse(buf); Console.Write("Nhp c : "); buf = Console.ReadLine(); c = Double.Parse(buf); } //₫ịnh nghĩa hàm tính nghim ca phương trình bc 2 static void GiaiPT() { //tính bit sdelta ca phương trình delta = b * b - 4 * a * c; if (delta >= 0) //nếu có nghim thc { x1 = (-b + Math.Sqrt(delta)) / 2 / a; x2 = (-b - Math.Sqrt(delta)) / 2 / a; } }

Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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; } }

Page 2: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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.

Page 3: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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 + ∑∞

=1nne

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 {

Page 4: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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

Page 5: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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.

Page 6: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộ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ả.

Page 7: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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];

Page 8: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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;

Page 9: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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.

Page 10: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộ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 {

Page 11: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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

Page 12: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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("+");

Page 13: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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.

Page 14: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộ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 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 {

Page 15: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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

Page 16: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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++)

Page 17: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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.

Page 18: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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;

Page 19: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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 <= 3 || 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);

Page 20: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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;

Page 21: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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("+");

Page 22: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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ả.

Page 23: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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.

Page 24: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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

Page 25: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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

Page 26: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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.

Page 27: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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 :

Page 28: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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.

Page 29: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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; }

Page 30: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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;

Page 31: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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); }

Page 32: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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 {

Page 33: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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();

Page 34: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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;

Page 35: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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;

Page 36: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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.

Page 37: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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.

Page 38: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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);

Page 39: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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.

Page 40: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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 < 0 || 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.

Page 41: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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");

Page 42: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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() {

Page 43: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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...");

Page 44: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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

Page 45: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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.

Page 46: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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 :

Page 47: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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()

Page 48: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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ả.

Page 49: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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);

Page 50: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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);

Page 51: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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

Page 52: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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)

Page 53: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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ả.

Page 54: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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 :

Page 55: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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;

Page 56: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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.

Page 57: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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 :

Page 58: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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ế

Page 59: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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));

Page 60: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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;

Page 61: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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))

Page 62: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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.

Page 63: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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.

Page 64: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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. Viết code cụ thể cho hàm như sau :

private void Form1_Paint(object sender, PaintEventArgs e) { //tạo ₫ối tượng image gốc Image bgimg = Image.FromFile("c:\\bgclock.bmp"); //xác ₫ịnh ₫ối tượng mục tiêu Control control = (Control)sender; //thay ₫ổi kích thước form theo ảnh khung ₫ồng hồ control.Size = new Size(bgimg.Width + 10 + 8, bgimg.Height + 10 + 35); //xác ₫ịnh ₫ối tượng graphics (₫ối tượng vẽ) của ₫ối tượng Graphics g = e.Graphics; //vẽ bitmap miêu tả khung ₫ồng hồ g.DrawImage(bgimg, 5,5); //₫ịnh nghĩa các biến cần dùng Rectangle rec = control.DisplayRectangle; Pen hPen; Brush hBrush; int xo,yo,rql,rh,rm, rs; int x, y; //thiết lập tâm ₫ồng hồ xo = 76; yo = 74; //thiết lập bán kính cần lắc, kim giờ/phút/giây rql = 140; rh = 50; rm = 55; rs = 60; //tạo pen ₫ể vẽ cần lắc hPen = new Pen (Color.FromArgb(0,0, 255),2); //tạo brush ₫ể tô nền quả lắc hBrush = new SolidBrush(Color.FromArgb(255, 0, 0)); //xác ₫ịnh giờ/phút/giây hiện hành DateTime now = DateTime.Now; //tính góc của cần lắc (góc quay max. là 40 ₫ộ) double goc = 80*now.Millisecond/1000; if (goc < 40) goc = goc +70; else goc = 150-goc; //₫ổi góc cần lắc từ ₫ộ ra radian goc = goc*3.1416/180; //xác ₫ịnh tâm quả lắc (₫iểm còn lại của cần lắc) x = xo+(int)(rql*Math.Cos(goc)); y = yo+(int)(rql*Math.Sin(goc)); //vẽ cần lắc g.DrawLine(hPen, xo, yo, x, y);

Page 65: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 3

//vẽ quả lắc g.FillEllipse(hBrush, x-3, y-3, 5, 5); g.DrawEllipse(hPen,x-4,y-4,7,7); //tạo pen ₫ể vẽ kim giờ hPen = new Pen(Color.FromArgb(0,0,0),3); //tính góc của kim giờ goc = 90+360*(now.Hour+(double)now.Minute/60)/12; //₫ổi góc từ ₫ộ ra radian goc = goc*3.1416/180; //xác ₫ịnh tọa ₫ộ ₫ỉnh thứ 2 của kim giờ x = xo - (int)(rh * Math.Cos(goc)); y = yo - (int)(rh * Math.Sin(goc)); //vẽ kim giờ g.DrawLine(hPen, xo, yo, x, y); //tạo pen ₫ể vẽ kim phút hPen = new Pen(Color.FromArgb(65,110,55),2); //tính góc của kim phút goc = 90+360*now.Minute/60; //₫ổi góc từ ₫ộ ra radian goc = goc*3.1416/180; //xác ₫ịnh tọa ₫ộ ₫ỉnh thứ 2 của kim phút x = xo - (int)(rm * Math.Cos(goc)); y = yo - (int)(rm * Math.Sin(goc)); //vẽ kim phút g.DrawLine(hPen, xo, yo, x, y); //tạo pen ₫ể vẽ kim giây hPen = new Pen(Color.FromArgb(237,5,220),1); //tính góc của kim giây goc = 90+360*now.Second/60; //₫ổi góc từ ₫ộ ra radian goc = goc*3.1416/180; //xác ₫ịnh tọa ₫ộ ₫ỉnh thứ 2 của kim giây x = xo - (int)(rs * Math.Cos(goc)); y = yo - (int)(rs * Math.Sin(goc)); //vẽ kim giây g.DrawLine(hPen, xo, yo, x, y); //tạo chuỗi miêu tả giờ/phút/giây hiện hành String buf = "" + now.Hour + ":" + now.Minute + ":" + now.Second; //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; //xuất chuỗi miêu tả giờ/phút/giây g.DrawString(buf, myFont, System.Drawing.Brushes.Blue, xo, rec.Height - 35, format1); //cho phép timer chạy tiếp myTimer.Start(); }

Page 66: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 4

8. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Xem kết quả và ₫ánh giá kết quả.

Page 67: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 1

MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG Bài thực hành số 7.1 : Xây dựng chương trình tính tổng 2 ma trận

I. Mục tiêu :

Giúp SV làm quen với cách thức viết code ₫ể ₫ọc dữ liệu ở dạng chuỗi văn bản từ file, mã hóa chuỗi thành dạng thích hợp ₫ể xử lý/tính toán bên trong máy, cách thức ₫ể giải mã thông tin trong máy thành dạng chuỗi ₫ể ghi ra file văn bản hầu giúp người dùng có thể kiểm tra dễ dàng kết quả.

II. Nội dung : Viết code ₫ể ₫ọc dữ liệu của 2 ma trận từ 2 file văn bản, tính ma trận tổng, xuất kết

quả ma trận tổng ra file văn bản ₫ể người dùng dễ dàng kiểm tra kết quả.

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 ₫ể ₫ọc/ghi dữ liệu văn bản

từ file văn bản vào các biến bên trong chương trì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 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. TongMT), click button OK ₫ể tạo Project theo các thông số ₫ã khai báo.

3. Ngay sau Project vừa ₫ược tạo ra, cửa sổ soạn code cho chương trình ₫ược hiển thị. Thêm lệnh using sau ₫ây vào ₫ầu file :

using System.IO; 4. Viết code cho thân class Program như sau : class Program { static double[,] A; //ma trận A static double[,] B; //ma trận B static double[,] S; //ma trận S static int hang, cot; //hàm ₫ọc ma trận vào biến bộ nhớ static void ReadMT(string path, ref double[,] A, ref int hang, ref int cot) { //1. tạo ₫ối tượng quản lý file FileStream stream = new FileStream(path, FileMode.Open); //2. tạo ₫ối tượng phục vụ ₫ọc file StreamReader reader = new StreamReader(stream, Encoding.ASCII); //3. ₫ịnh nghĩa các biến dữ liệu theo yêu cầu chương trình int i, j; string buf = ""; //4. ₫ọc dữ liệu từ file vào các biến ReadItem(reader, ref buf); hang = Int32.Parse(buf); //₫ọc số hàng ReadItem(reader, ref buf); cot = Int32.Parse(buf); //₫ọc số cột //phân phối vùng nhớ cho ma trận A = new double[hang, cot]; //₫ọc từng phần tử ma trận for (i = 0; i < hang; i++) for (j = 0; j < cot; j++) { ReadItem(reader, ref buf);

Page 68: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 2

A[i, j] = Double.Parse(buf); //₫ọc số thực } //5. ₫óng các ₫ối tượng ₫ược dùng lại reader.Close(); stream.Close(); } //hàm ghi ma trận ra file text static void WriteMT(string path, double[,] A, int hang, int cot) { //1. tạo ₫ối tượng quản lý file FileStream stream = new FileStream(path, FileMode.Create); //2. tạo ₫ối tượng phục vụ ghi file StreamWriter writer = new StreamWriter(stream, Encoding.ASCII); //3. ₫ịnh nghĩa các biến dữ liệu theo yêu cầu chương trình int i, j; //4. ghi dữ liệu từ các biến ra file writer.Write(hang); writer.Write(", "); //ghi số hàng và dấu ngăn writer.Write(cot); writer.WriteLine(); //ghi số cột và dấu ngăn //ghi ma trận for (i = 0; i < hang; i++) { //ghi từng hàng ma trận for (j = 0; j < cot; j++) { writer.Write(A[i, j]); writer.Write(","); //ghi phần tử i,j } writer.WriteLine(); //ghi dấu xuống hàng } //5. ₫óng các ₫ối tượng ₫ược dùng lại writer.Close(); stream.Close(); } //hàm ₫ọc chuỗi miêu tả 1 dữ liệu nào ₫ó static void ReadItem(StreamReader reader, ref String buf) { char ch = '\0'; //thiết lập chuỗi nhập ₫ược lúc ₫ầu là rỗng buf = ""; while (reader.EndOfStream != true) {//lặp ₫ọc bỏ các dấu ngăn ch = (char)reader.Read(); //₫ọc 1 ký tự if (ch != ',' && ch != '\r' && ch != '\n') break; //nếu là ký tự bình thường thì dừng } buf += ch.ToString(); //lặp ₫ọc các ký tự của chuỗi dữ liệu while (reader.EndOfStream != true) { ch = (char)reader.Read(); //₫ọc 1 ký tự if (ch == ',' || ch == '\r' || ch == '\n') return; //nếu là dấu ngăn thì dừng buf += ch.ToString(); //chứa ký tự vào bộ ₫ệm } } //₫iểm nhập chương trình static void Main(string[] args) {

Page 69: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 3

int i, j, h = 0, c = 0; //₫ọc ma trận A từ file c:\A.txt ReadMT("c:\\a.txt", ref A, ref hang, ref cot); //₫ọc ma trận B từ file c:\B.txt ReadMT("c:\\b.txt", ref B, ref h, ref c); if (h != hang || c != cot) { Console.WriteLine("Hai ma trận A, B không cùng kích thước"); return; } //phân phối ma trận tổng S S = new double[hang, cot]; //tính ma trận tổng S for (i = 0; i < hang; i++) for (j = 0; j < cot; j++) S[i, j] = A[i, j] + B[i, j]; //xuất ma trận kết quả ra file c:\S.txt WriteMT("c:\\S.txt", S, hang, cot); } //hết hàm Main } //hết class program

5. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Lưu ý là trước khi chạy ứng dụng, hãy dùng chương trình soạn thảo văn bản (NotePad, WordPad,...) soạn thảo 2 file c:\A.txt, c:\B.txt chứa dữ liệu của 2 ma trận A và B.

Thí dụ nội dung c:\A.txt như sau : 5, 7 1, 2, 3, 4, 5, 6, 7 8, 9, 10, 11, 12, 13, 14 15, 16, 17, 18, 19, 20, 21 22, 23, 24, 25, 26, 27, 28 29, 30, 31, 32, 33, 34, 35

Và nội dung c:\B.txt như sau : 5, 7 2, 3, 4, 5, 6, 7, 8 9, 10, 11, 12, 13, 14, 15 16, 17, 18, 19, 20, 21, 22 23, 24, 25, 26, 27, 28, 29 30, 31, 32, 33, 34, 35, 36

Page 70: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 1

MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG Bài thực hành số 7.2 : Xây dựng chương trình tính tổng 2 ma trận

I. Mục tiêu :

Giúp SV làm quen với cách thức viết code ₫ể ₫ọc dữ liệu ở dạng nhị phân từ file ₫ể xử lý/tính toán ngay bên trong máy mà không cần tốn chi phí mã hóa chúng, cách thức ₫ể ghi dữ liệu nhị phân bên trong chương trình ra file nhị phân cho hiệu quả cả về dung lượng chứa lẫn thời gian ghi tin (vì không cần tốn chi phí giải mã).

II. Nội dung : Viết code ₫ể ₫ọc dữ liệu của 2 ma trận từ 2 file nhị phân, tính ma trận tổng, xuất kết

quả ma trận tổng ra file nhị phân ₫ể ₫ạt hiệu quả cao nhất.

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 ₫ể ₫ọc/ghi dữ liệu nhị

phân từ file nhị phân vào các biến bên trong chương trình.

IV. Qui trình :

1. Vẫn giữ lại 2 file c:\A.txt và c:\B.txt chứa nội dung 2 ma trận A và B như sau :

Nội dung c:\A.txt như sau : 5, 7 1, 2, 3, 4, 5, 6, 7 8, 9, 10, 11, 12, 13, 14 15, 16, 17, 18, 19, 20, 21 22, 23, 24, 25, 26, 27, 28 29, 30, 31, 32, 33, 34, 35

Và nội dung c:\B.txt như sau : 5, 7 2, 3, 4, 5, 6, 7, 8 9, 10, 11, 12, 13, 14, 15 16, 17, 18, 19, 20, 21, 22 23, 24, 25, 26, 27, 28, 29 30, 31, 32, 33, 34, 35, 36

2. Nhân bản thư mục chứa Project của bài thực hành 7.1 (thư mục TongMTTxt) thành thư mục mới và ₫ặt tên cho thư mục này là TongMTBin.

3. Chạy VS .Net, mở lại Porject trong thư mục TongMTBin.

4. Hiệu chỉnh lại hàm WriteMT như sau : //hàm ghi ma trận ra file binary static void WriteMT(string path, double[,] A, int hang, int cot) { //1. tạo ₫ối tượng quản lý file FileStream stream = new FileStream(path, FileMode.Create); //2. tạo ₫ối tượng phục vụ ghi file BinaryWriter writer = new BinaryWriter(stream); //3. ₫ịnh nghĩa các biến dữ liệu theo yêu cầu chương trình int i, j; //4. ghi dữ liệu từ các biến ra file writer.Write(hang); //ghi số hàng writer.Write(cot); //ghi số cột //ghi ma trận

Page 71: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 2

for (i = 0; i < hang; i++) { //ghi từng hàng ma trận for (j = 0; j < cot; j++) { writer.Write(A[i, j]); //ghi phần tử i,j } } //5. ₫óng các ₫ối tượng ₫ược dùng lại writer.Close(); stream.Close(); }

5. Duyệt tìm hàm Main(), tìm và sửa lệnh gọi hàm WriteMT() thành : //xuất ma trận kết quả ra file c:\S.bin WriteMT("c:\\S.bin", S, hang, cot);

6. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Nếu không có lỗi thì chương trình sẽ chạy tốt và ghi nội dung ma trận tổng ra file S.bin. So sánh kích thước của file S.bin với file S.txt, lý giải tại sao kích thước của file S.bin chỉ có 288 byte.

7. Copy file c:\S.bin thành 2 file c:\A.bin và c:\B.bin ₫ể tạo 2 file miêu tả 2 ma trận A và B ở dạng nhị phân.

8. Hiệu chỉnh lại hàm ReadMT như sau : //hàm ₫ọc ma trận từ file binary static void ReadMT(string path, ref double[,] A, ref int hang, ref int cot) { //1. tạo ₫ối tượng quản lý file FileStream stream = new FileStream(path, FileMode.Open); //2. tạo ₫ối tượng phục vụ ₫ọc file BinaryReader reader = new BinaryReader(stream); //3. ₫ịnh nghĩa các biến dữ liệu theo yêu cầu chương trình int i, j; //4. ₫ọc dữ liệu từ file vào các biến //₫ọc số hàng hang = reader.ReadInt32(); //₫ọc số nguyên 32 bit //₫ọc số cột cot = reader.ReadInt32(); //₫ọc số nguyên 32 bit //phân phối vùng nhớ cho ma trận A = new double[hang, cot]; //₫ọc từng phần tử ma trận for (i = 0; i < hang; i++) for (j = 0; j < cot; j++) { A[i, j] = reader.ReadDouble(); //₫ọc số thực } //5. ₫óng các ₫ối tượng ₫ược dùng lại reader.Close(); stream.Close(); }

9. Duyệt tìm hàm Main(), tìm và sửa lệnh 2 lệnh gọi hàm ReadMT() thành : //₫ọc ma trận A từ file c:\A.bin ReadMT("c:\\a.bin", ref A, ref hang, ref cot); //₫ọc ma trận B từ file c:\B.bin ReadMT("c:\\b.bin", ref B, ref h, ref c);

10. Duyệt tìm và xóa hàm ReadItem vì không cần thiết.

Page 72: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 3

11. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Nếu không có lỗi thì chương trình sẽ chạy tốt, nó sẽ ₫ọc lần lượt từng ma trận trong file nhị phân tương ứng vào chương trình, tình tổng ma trận và ghi nội dung ma trận tổng ra file S.bin.

Page 73: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 1

MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG Bài thực hành số 7.3 : Xây dựng ứng dụng hiển thị nội dung file ở

dạng Binary (Hexadecimal) 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. Giúp SV làm quen với cách thức viết code ₫ể ₫ọc dữ liệu ở dạng nhị phân từ file

₫ể xử lý/tính toán ngay bên trong máy mà không cần tốn chi phí mã hóa chúng.

II. Nội dung : Xây dựng ứng dụng Dialog Based hiển thị nội dung file ở dạng Binary

(Hexadecimal). Dịch và chạy chương trình. Debug chương trình ₫ể tìm lỗi nếu có.

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. Sinh viên nắm vững và lập trình thành thạo các ₫oạn code ₫ể ₫ọc dữ liệu nhị

phân từ file nhị phân vào các biến bên trong chương trình.

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 "Open File..." ₫ể người dùng kích hoạt chức năng hiển thị 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 hiển thị nội dung file dạng Binary (₫ối tượng ListBox).

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

Page 74: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 2

chứa Project trong listbox "Location", nhập tên Project vào textbox "Name:" (thí dụ BinaryView), 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 = "Open File…", duyệt tìm và thay ₫ổi thuộc tính (Name) = btnOpen.

6. Duyệt tìm phần tử ListBox (trong nhóm Common Controls), chọn nó, dời chuột về ngay dưới Button và vẽ nó với kích thước mong muốn. Xem cửa sổ thuộc tính của ListBox 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 (Name) = lbOutput.

Sau khi thiết kế xong, Form có dạng sau :

7. Dời chuột về button btnOpen, ấ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 btnOpen, 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, viết thân cho hàm này như sau :

private void btnOpen_Click(object sender, EventArgs e) { //₫ịnh nghĩa các biến cần dùng int i, j;

Page 75: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 3

int byt; String slLine, srLine; String sline; 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) return; //1. tạo ₫ối tượng quản lý file FileStream stream = new FileStream(dlg.FileName, FileMode.Open); //2. xác ₫ịnh kích thước file long flen = stream.Length; //3. xuất từng nhóm 16 byte của file ra thành 1 dòng j = 0; slLine = srLine = ""; lbOutput.Items.Clear(); for (i = 0; i < flen; i++) { byt = stream.ReadByte(); sline = String.Format("{0:X2} ", byt); slLine = slLine + sline; if (byt < 32) sline = "."; else sline = Char.ToString((char)byt); srLine = srLine + sline; if (++j == 16) { //du dong lbOutput.Items.Add(slLine + " " + srLine); j = 0; slLine = srLine = ""; } } if (j == 0) return; //4. xử lý dòng cuối cùng while (j++ < 16) slLine = slLine + " "; lbOutput.Items.Add(slLine + " " + srLine); //5. ₫óng file lại stream.Close(); }

8. Dời chuột về cửa sổ "Solution Explorer", duyệt tìm mục Form1.cs, ấn kép chuột vào mục này ₫ể hiển thị lại cửa sổ thiết kế form. Chọn Form ₫ể hiển thị cửa sổ thuộc tính

của Form, click icon ₫ể hiển thị danh sách các sự kiện của Form, duyệt tìm sự kiện 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 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 :

//thay ₫ổi kích thước ListBox theo kích thước mới của Form

Page 76: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 4

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; //tính lại kích thước của ListBox cx = cx - 8 - lbOutput.Location.X * 2; cy = cy - 8 - 25 - lbOutput.Location.Y; //thay ₫ổi kích thước của ListBox theo kích thước Form lbOutput.Size = new Size(cx, cy); }

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 "Open File...", cửa sổ duyệt chọn file sẽ hiển thị, hãy duyệt và chọn 1 file nào ₫ó cần xem, click button Open ₫ể hiển thị nội dung file này.

10. Ta thấy nội dung trên từng hàng bị che mất bên phải vì ₫ộ rộng Form nhỏ quá. 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 :

11. Hãy 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 và ListBox cũng ₫ược phóng to theo, lúc này ta thấy ₫ầy ₫ủ thông tin trên từng hàng.

12. Dừng chương trình lại, hiển thị cửa sổ mã nguồn, cố gắng ₫ọc hiểu ₫oạn code trong thân của 2 hàm xử lý sự kiện btnOpen_Click() và Form1_SizeChanged().

Page 77: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 1

MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG Bài thực hành số 7.4 : Xây dựng chương trình ghi/₫ọc hệ thống ₫ối tượng

I. Mục tiêu :

Giúp SV làm quen với cách thức viết code ₫ể ghi/₫ọc hệ thống ₫ối tượng gồm nhiều ₫ối tượng có mối quan hệ tham khảo lẫn nhau sao cho dễ dàng, trong sáng, an toàn và tin cậy nhất.

II. Nội dung : Viết code ₫ể ghi/₫ọc ₫ối tượng b có trạng thái cụ thể như hình vẽ dưới ₫ây.

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 ₫ể ₫ọc/ghi ₫ối tượng cần

thiết trong chương trình của mình.

IV. Qui trình :

Giả sử ta có hệ thống các ₫ối tượng với trạng thái và mối quan hệ giữa chúng cụ thể như sau. Lưu ý chúng có mối quan hệ bao gộp dạng vòng :

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. WRObject), click button OK ₫ể tạo Project theo các thông số ₫ã khai báo.

3. Ngay sau Project vừa ₫ược tạo ra, cửa sổ soạn code cho chương trình ₫ược hiển thị. Thêm lệnh các using sau ₫ây vào ₫ầu file :

using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary;

4. Viết code cho hàm Main và các hàm dịch vụ khác nhau sau : class Program { static String fbuf; static void Main(string[] args) { //₫iểm nhập của chương trình

Page 78: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 2

//xây dựng hệ thống ₫ối tượng và ghi lên file Create_SaveObject(); //₫ọc lại hệ thống ₫ối tượng //ReadObject(); } //hàm xây dựng hệ thống ₫ối tượng và ghi lên file public static void Create_SaveObject() { //khở tạo ₫ối tượng b theo hình ở silde 24 B b = new B(); b.init(2,2.345); b.Setba(1,1.234,b); b.Setpba(3,3.1416,b); b.Setpba1(4,4.567,b); //ghi ₫ối tượng b dùng kỹ thuật Serialization try { //1. ₫ịnh nghĩa ₫ối tượng FileStream miêu tả file chứa kết quả FileStream fs = new FileStream("c:\\data.obj", FileMode.Create); //2. tạo ₫ối tượng BinaryFormatter phục vụ ghi ₫ối tượng BinaryFormatter formatter = new BinaryFormatter(); //3. gọi tác vụ Serialize của formatter ₫ể ghi ₫ối tượng formatter.Serialize(fs,b); //4. ₫óng file lại fs.Flush(); fs.Close(); } catch (Exception e) { Console.WriteLine(e.ToString()); } } //hàm ₫ọc ₫ối tượng b dùng kỹ thuật Serialization public static void ReadObject() { try { //1. ₫ịnh nghĩa ₫ối tượng FileStream miêu tả file chứa dữ liệu ₫ã có FileStream fs = new FileStream("c:\\data.obj", FileMode.Open); //2. tạo ₫ối tượng BinaryFormatter phục vụ ₫ọc ₫ối tượng BinaryFormatter formatter = new BinaryFormatter(); //3. gọi tác vụ Deserialize ₫ể ₫ọc ₫ối tượng từ file vào B b = (B) formatter.Deserialize(fs); //4. ₫óng file lại fs.Close(); } catch (Exception e) { Console.WriteLine(e.ToString()); } } //hết hàm Main } //hết class program 5. Ấn phải chuột vào phần tử gốc của cây Project trong cửa sổ Solution Explorer, chọn

option Add.Class, ₫ặt tên là A.cs ₫ể tạo ra file ₫ặc tả class A. Khi cửa sổ hiển thị mã nguồn của class A hiển thị, ₫ặc tả class A như ₫oạn code dưới ₫ây :

//thêm lệnh using sau ở ₫ầu file using System.Runtime.Serialization; namespace WRObject { [Serializable] public class A { //₫ịnh nghĩa các thuộc tính dữ liệu private int intA1; private double dblA2;

Page 79: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 3

private B pab; //₫ịnh nghĩa các tác vụ public A() {} public void init(int a1, double a2, B p) { this.intA1 = a1; this.dblA2 = a2; this.pab = p; } } } 6. Ấn phải chuột vào phần tử gốc của cây Project trong cửa sổ Solution Explorer, chọn

option Add.Class, ₫ặt tên là B.cs ₫ể tạo ra file ₫ặc tả class B. Khi cửa sổ hiển thị mã nguồn của class B hiển thị, ₫ặc tả class B như ₫oạn code dưới ₫ây :

//thêm lệnh using sau ở ₫ầu file using System.Runtime.Serialization; namespace WRObject { [Serializable] public class B { //₫ịnh nghĩa các thuộc tính dữ liệu private int intB1; private double dblB2; private A ba; private A pba; private A pba1; //₫ịnh nghĩa các tác vụ public B() { } public void init(int b1, double b2) { this.intB1 = b1; this.dblB2 = b2; ba = new A(); pba = new A(); pba1 = new A(); } public void Setba (int a1, double a2, B b) { this.ba.init (a1,a2,b); } public void Setpba (int a1, double a2, B b) { this.pba.init (a1,a2,b); } public void Setpba1 (int a1, double a2, B b) { this.pba1.init (a1,a2,b); } } //hết class B } //hết namespace WRObject 7. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Hệ thống ₫ối tượng sẽ

₫ược tạo ra và lưu lên file c:\data.obj. 8. Hiển thị cửa sổ soạn mã nguồn file Program.cs, chú thích lệnh gọi Create_SaveObject();

và bỏ chú thích lệnh gọi ReadObject();. Dời chuột về lệnh "B b = (B) formatter.Deserialize(fs);" trong hàm ReadObject(), click chuột vào lệnh trái của lệnh này ₫ể thiết lập ₫iểm dừng. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Ứng dụng sẽ dừng ở lệnh dừng. Dời chuột về biến b, ta thấy cửa sổ hiển thị giá trị của biến này lúc này là null.

Page 80: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 4

9. Ấn F10 ₫ể thực hiện ₫úng lệnh này rồi dừng lại, dời chuột về biến b, rồi mở rộng cây phân cấp miêu tả nội dung biến b và thấy nó chứa ₫úng thông tin như slide 14, nghĩa là chương trình ₫ã ₫ọc ₫ược toàn bộ hệ thống ₫ối tượng ₫ã lưu giữ trước ₫ây.

Page 81: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 1

MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG Bài thực hành số 8.1 : Xây dựng và debug class cụ thể ₫ể chuẩn bị chuyển

thành class tổng quát hóa I. Mục tiêu :

Giúp SV làm quen với việc chuẩn bị xây dựng class tổng quát hóa.

II. Nội dung : Viết code miêu tả class “Stack các số nguyên” cung cấp 2 tác vụ push() và pop() ₫ể

cất/lấy lại từng số nguyên trên ₫ỉnh stack. Viết chương trình nhỏ thử dùng ₫ối tượng “Stack các số nguyên”, thử cất 10 số

nguyên vào stack rồi lấy lại xem Stack có hoạt ₫ộng tốt không. Debug phần mềm và class Stack ₫ể ₫ảm bảo chúng chạy ₫úng chức năng.

III. Chuẩn ₫ầu ra : Sinh viên nắm vững việc ₫ặc tả class cụ thể, nhận thức ₫ây là bước ₫ầu tiên nên làm

₫ể xây dựng class tổng quát hóa dễ dàng, ít rủi ro.

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. AnyStackpp), click button OK ₫ể tạo Project theo các thông số ₫ã khai báo.

3. Ngay sau Project vừa ₫ược tạo ra, cửa sổ soạn code cho chương trình ₫ược hiển thị. Viết code cho hàm Main như sau : namespace AnyStackApp { class Program { static void Main(string[] args) { int i; //tạo ₫ối tượng IntStack ₫ể dùng IntStack si = new IntStack(); //push lần lượt 11 giá trị từ -5 tới 5 for (i = -5; i <= 5; i++) { if (!si.push(i)) { Console.WriteLine("Khong push duoc nua!!!"); return; } } //pop các giá trị trong Stack ra và hiển thị ₫ể kiểm tra try { while (true) { int ci = si.pop(); Console.WriteLine("Tri vua pop ra la : " + ci); } } catch (Exception e) { Console.Write("Hết stack. Ấn Enter ₫ể ₫óng cửa sổ"); Console.Read(); } } //hết hàm Main

Page 82: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 2

} //hết class Program } //hết namespace

4. Ấn phải chuột vào phần tử gốc của cây Project trong cửa sổ Solution Explorer, chọn option Add.Class, ₫ặt tên là IntStack.cs ₫ể tạo ra file ₫ặc tả class IntStack. Khi cửa sổ hiển thị mã nguồn của class IntStack hiển thị, ₫ặc tả class IntStack như ₫oạn code dưới ₫ây : namespace AnyStackApp { public class IntStack { private int[] data; //danh sách các phần tử trong stack private int top; // chỉ số phần tử ₫ỉnh stack private int max; // số lượng max hiện hành stack // khai báo hằng miêu tả số lượng phần tử cần thêm mỗi lần thiếu stack private int GROWBY = 4; //hàm constrcutor public IntStack() { top = 0; max =GROWBY; data = (int[])new int[max]; } //hàm push phần tử vào ₫ỉnh public bool push(int newVal) { int[] newdata; if (top==max) { //nếu ₫ầy stack //xin cấp phát lại vùng nhớ lớn hơn GROWBY phần tử sơ với stack hiện hành try { newdata = (int[])new int[GROWBY+max]; } catch (Exception e){ //System.out.println("He thong het cho roi!!!"); return false; } //di chuyển stack hiện hành về stack mới for (int i = 0; i<max; i++) newdata[i] =data[i]; //cập nhật lại stack mới, ₫ể hệ thống xóa stack cũ tự ₫ộng data = newdata; max += GROWBY; } //chứa giá trị mới vào ₫ỉnh stack data[top++] =newVal; return true; } //hàm pop 1 phần tử từ ₫ỉnh stack public int pop() { if (top == 0) //nếu cạn stack thì tạo Exception throw new Exception ("Cạn stack"); else //trả về trị ở ₫ỉnh stack

Page 83: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 3

return data[--top]; } } //hết class IntStack } //hết namespace AnyStackApp

5. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Hãy xem kết quả hiển thị và ₫ánh giá chức năng của ₫ối tượng IntStack.

Page 84: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 1

MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG Bài thực hành số 8.2 : Xây dựng class tổng quát hóa “Stack các giá trị”

I. Mục tiêu :

Giúp SV làm quen với việc xây dựng class tổng quát hóa có dùng giá trị thuộc kiểu bất kỳ.

II. Nội dung : Viết code miêu tả class tổng quát hóa “Stack các giá trị bất kỳ” cung cấp 2 tác vụ

push() và pop() ₫ể cất/lấy lại từng giá trị trên ₫ỉnh stack. Viết chương trình nhỏ thử dùng class tổng quát hóa “Stack các giá trị bất kỳ” ₫ể tạo tự

₫ộng 2 class Stack các số nguyên và Stack các số thực, thử sử dụng 2 class cụ thể này.

III. Chuẩn ₫ầu ra : Sinh viên nắm vững việc ₫ặc tả class tổng quát hóa có dùng giá trị thuộc kiểu bất kỳ.

IV. Qui trình :

1. Chạy VS .Net, chọn menu File.Open.Project ₫ể hiển thị cửa sổ duyệt file. Duyệt và tìm file *.sln quản lý Project "AnyStackApp" có sẵn từ bài thực hành 8.1 ₫ể mở lại Project này.

2. Ấn phải chuột vào phần tử gốc của cây Project trong cửa sổ Solution Explorer, chọn option Add.Class, ₫ặt tên là ValueStack.cs ₫ể tạo ra file ₫ặc tả class tổng quát hóa ValueStack. Khi cửa sổ hiển thị mã nguồn của class ValueStack hiển thị, copy code ₫ã viết trong class IntStack, dán code này vào thân của ValueStack, rồi hiệu chỉnh lại như sau (phần màu ₫ỏ là phần thay ₫ổi so với class IntStack) :

//₫ịnh nghĩa class tổng quát hóa : Stack các giá trị thuộc kiểu T namespace AnyStackApp { public class ValueStack <T> { private T[] data; //danh sách các phần tử trong stack private int top; // chỉ số phần tử ₫ỉnh stack private int max; // số lượng max hiện hành stack // khai báo hằng miêu tả số lượng phần tử cần thêm mỗi lần thiếu stack private int GROWBY = 4; //hàm constrcutor public ValueStack () { top = 0; max =GROWBY; data = (T[])new T[max]; } //hàm push phần tử vào ₫ỉnh public bool push(T newVal) { T[] newdata; if (top==max) { //nếu ₫ầy stack //xin cấp phát lại vùng nhớ lớn hơn GROWBY phần tử sơ với stack hiện hành try { newdata = (T[])new T[GROWBY+max]; } catch (Exception e){ //System.out.println("He thong het cho roi!!!");

Page 85: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 2

return false; } //di chuyển stack hiện hành về stack mới for (int i = 0; i<max; i++) newdata[i] =data[i]; //cập nhật lại stack mới, ₫ể hệ thống xóa stack cũ tự ₫ộng data = newdata; max += GROWBY; } //chứa giá trị mới vào ₫ỉnh stack data[top++] =newVal; return true; } //hàm pop 1 phần tử từ ₫ỉnh stack public T pop() { if (top == 0) //nếu cạn stack thì tạo Exception throw new Exception ("Cạn stack"); else //trả về trị ở ₫ỉnh stack return data[--top]; } } //hết class ValueStack } //hết namespace AnyStackApp

3. Dời chuột về phần tử Program.cs trong cây Project trong cửa sổ Solution Explorer, ấn phải chuột trên nó ₫ể hiển thị menu lệnh, chọn lệnh “View Code” ₫ể hiển thị mã nguồn của chương trình (class Program), hiệu chỉnh hàm Main lại như sau (phần màu ₫ỏ là phần thay ₫ổi so với nội dung có sẵn): namespace AnyStackApp { class Program { static void Main(string[] args) { int i; //tạo class ValueStack<int> và ₫ối tượng của class này ₫ể dùng ValueStack<int> si = new ValueStack<int> (); //push lần lượt 11 giá trị từ -5 tới 5 for (i = -5; i <= 5; i++) { if (!si.push(i)) { Console.WriteLine("Khong push duoc nua!!!"); return; } } //pop các giá trị trong Stack ra và hiển thị ₫ể kiểm tra try { while (true) { int ci = si.pop(); Console.WriteLine("Tri vua pop ra la : " + ci); } } catch (Exception e) { Console.Write("Hết stack. Ấn Enter ₫ể ₫óng cửa sổ"); Console.Read(); }

Page 86: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 3

} //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 xem thứ tự hiển thị các số nguyên và ₫ánh giá chức năng của ₫ối tượng ValueStack<int>.

5. Dời chuột về phần tử Program.cs trong cây Project trong cửa sổ Solution Explorer, ấn phải chuột trên nó ₫ể hiển thị menu lệnh, chọn lệnh “View Code” ₫ể hiển thị mã nguồn của chương trình (class Program), hiệu chỉnh hàm Main lại như sau (phần màu ₫ỏ là phần thay ₫ổi so với nội dung có sẵn): namespace AnyStackApp { class Program { static void Main(string[] args) { int i; //tạo class ValueStack<double> và ₫ối tượng của class này ₫ể dùng ValueStack<double> si = new ValueStack<double> (); //push lần lượt 10 giá trị thực từ 3.1416 tới 10*3.1416 for (i = 1; i <= 10; i++) { if (!si.push(i*3.1416)) { Console.WriteLine("Khong push duoc nua!!!"); return; } } //pop các giá trị trong Stack ra và hiển thị ₫ể kiểm tra try { while (true) { double ci = si.pop(); Console.WriteLine("Tri vua pop ra la : " + ci); } } catch (Exception e) { Console.Write("Hết stack. Ấn Enter ₫ể ₫óng cửa sổ"); 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 xem thứ tự hiển thị các số thực và ₫ánh giá chức năng của ₫ối tượng ValueStack<double>.

Page 87: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 1

MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG Bài thực hành số 8.3 : Xây dựng class tổng quát hóa “Stack các tham khảo”

I. Mục tiêu :

Giúp SV làm quen với việc xây dựng class tổng quát hóa có dùng tham khảo thuộc kiểu bất kỳ.

II. Nội dung : Viết code miêu tả class tổng quát hóa “Stack các tham khảo bất kỳ” cung cấp 2 tác

vụ push() và pop() ₫ể cất/lấy lại từng tham khảo trên ₫ỉnh stack. Viết chương trình nhỏ thử dùng class tổng quát hóa “Stack các tham khảo bất kỳ” ₫ể

tạo tự ₫ộng 2 class Stack các ₫ối tượng nguyên và Stack các ₫ối tượng thực, thử sử dụng 2 class cụ thể này.

III. Chuẩn ₫ầu ra : Sinh viên nắm vững việc ₫ặc tả class tổng quát hóa có dùng tham khảo thuộc kiểu

bất kỳ.

IV. Qui trình :

1. Chạy VS .Net, chọn menu File.Open.Project ₫ể hiển thị cửa sổ duyệt file. Duyệt và tìm file *.sln quản lý Project "AnyStackApp" có sẵn từ bài thực hành 8.2 ₫ể mở lại Project này.

2. Ấn phải chuột vào phần tử gốc của cây Project trong cửa sổ Solution Explorer, chọn option Add.Class, ₫ặt tên là RefStack.cs ₫ể tạo ra file ₫ặc tả class tổng quát hóa RefStack. Khi cửa sổ hiển thị mã nguồn của class RefStack hiển thị, copy code ₫ã viết trong class IntStack, dán code này vào thân của RefStack, rồi hiệu chỉnh lại như sau (phần màu ₫ỏ là phần thay ₫ổi so với class IntStack) :

//₫ịnh nghĩa class tổng quát hóa : Stack các giá trị thuộc kiểu T namespace AnyStackApp { public class RefStack <T> where T : class { private T[] data; //danh sách các phần tử trong stack private int top; // chỉ số phần tử ₫ỉnh stack private int max; // số lượng max hiện hành stack // khai báo hằng miêu tả số lượng phần tử cần thêm mỗi lần thiếu stack private int GROWBY = 4; //hàm constrcutor public RefStack () { top = 0; max =GROWBY; data = (T[])new T[max]; } //hàm push phần tử vào ₫ỉnh public bool push(T newVal) { T[] newdata; if (top==max) { //nếu ₫ầy stack //xin cấp phát lại vùng nhớ lớn hơn GROWBY phần tử sơ với stack hiện hành try { newdata = (T[])new T[GROWBY+max]; } catch (Exception e){

Page 88: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 2

//System.out.println("He thong het cho roi!!!"); return false; } //di chuyển stack hiện hành về stack mới for (int i = 0; i<max; i++) newdata[i] =data[i]; //cập nhật lại stack mới, ₫ể hệ thống xóa stack cũ tự ₫ộng data = newdata; max += GROWBY; } //chứa giá trị mới vào ₫ỉnh stack data[top++] =newVal; return true; } //hàm pop 1 phần tử từ ₫ỉnh stack public T pop() { if (top == 0) //nếu cạn stack thì tạo Exception throw new Exception ("Cạn stack"); else //trả về trị ở ₫ỉnh stack return data[--top]; } } //hết class ValueStack } //hết namespace AnyStackApp

3. Ấn phải chuột vào phần tử gốc của cây Project trong cửa sổ Solution Explorer, chọn option Add.Class, ₫ặt tên là MyInt.cs ₫ể tạo ra file ₫ặc tả class ₫ối tượng mà mỗi ₫ối tượng chứa ₫ược 1 số nguyên. Khi cửa sổ hiển thị mã nguồn của class MyInt hiển thị, viết code cho class như sau : namespace AnyStackApp { class MyInt { private int m_value; //thuộc tính giao tiếp Value public int Value { get { return m_value; } set { m_value = value; } } //hàm contructor public MyInt(int val) { m_value = val; } } }

4. Dời chuột về phần tử Program.cs trong cây Project trong cửa sổ Solution Explorer, ấn phải chuột trên nó ₫ể hiển thị menu lệnh, chọn lệnh “View Code” ₫ể hiển thị mã nguồn của chương trình (class Program), hiệu chỉnh hàm Main lại như sau (phần màu ₫ỏ là phần thay ₫ổi so với nội dung có sẵn): namespace AnyStackApp { class Program { static void Main(string[] args) { int i; //tạo class RefStack<MyInt> và ₫ối tượng của class này ₫ể dùng RefStack<MyInt> si = new RefStack<MyInt> ();

Page 89: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 3

//push lần lượt 11 giá trị từ -5 tới 5 for (i = -5; i <= 5; i++) { if (!si.push(new MyInt(i))) { Console.WriteLine("Khong push duoc nua!!!"); return; } } //pop các giá trị trong Stack ra và hiển thị ₫ể kiểm tra try { while (true) { MyInt ci = si.pop(); Console.WriteLine("Tri vua pop ra la : " + ci.Value); } } catch (Exception e) { Console.Write("Hết stack. Ấn Enter ₫ể ₫óng cửa sổ"); Console.Read(); } } //hết hàm Main } //hết class Program } //hết namespace

5. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Hãy xem thứ tự hiển thị các số nguyên và ₫ánh giá chức năng của ₫ối tượng RefStack<MyInt>.

6. Ấn phải chuột vào phần tử gốc của cây Project trong cửa sổ Solution Explorer, chọn option Add.Class, ₫ặt tên là MyDouble.cs ₫ể tạo ra file ₫ặc tả class ₫ối tượng mà mỗi ₫ối tượng chứa ₫ược 1 số thực. Khi cửa sổ hiển thị mã nguồn của class MyDouble hiển thị, viết code cho class như sau : namespace AnyStackApp { class MyDouble { private double m_value; //thuộc tính giao tiếp Value public double Value { get { return m_value; } set { m_value = value; } } //hàm contructor public MyDouble(double val) { m_value = val; } } }

7. Dời chuột về phần tử Program.cs trong cây Project trong cửa sổ Solution Explorer, ấn phải chuột trên nó ₫ể hiển thị menu lệnh, chọn lệnh “View Code” ₫ể hiển thị mã nguồn của chương trình (class Program), hiệu chỉnh hàm Main lại như sau (phần màu ₫ỏ là phần thay ₫ổi so với nội dung có sẵn): namespace AnyStackApp { class Program { static void Main(string[] args) { int i; //tạo class RefStack<MyDouble> và ₫ối tượng của class này ₫ể dùng RefStack<MyDouble> si = new RefStack<MyDouble> (); //push lần lượt 10 giá trị thực từ 3.1416 tới 10*3.1416 for (i = 1; i <= 10; i++) {

Page 90: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 4

if (!si.push(new MyDouble(i*3.1416))) { Console.WriteLine("Khong push duoc nua!!!"); return; } } //pop các giá trị trong Stack ra và hiển thị ₫ể kiểm tra try { while (true) { MyDouble ci = si.pop(); Console.WriteLine("Tri vua pop ra la : " + ci); } } catch (Exception e) { Console.Write("Hết stack. Ấn Enter ₫ể ₫óng cửa sổ"); Console.Read(); } } //hết hàm Main } //hết class Program } //hết namespace

8. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Hãy xem thứ tự hiển thị các số thực và ₫ánh giá chức năng của ₫ối tượng RefStack<MyDouble>.

Page 91: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 1

MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG Bài thực hành số 9.1 : Xây dựng UserControl và ứng dụng dùng nó

I. Mục tiêu :

Giúp SV làm quen với cách thức xây dựng 1 UserControl giải quyết chức năng ₫ặc thù của mình bằng cách tích hợp nhiều ₫iều khiển ₫ã có sẵn.

Củng cố kiến thức về việc ₫ịnh nghĩa và dùng delegate và events.

II. Nội dung : Tích hợp các ₫iều khiển có sẵn như Label, TextBox, Button ₫ể xây dựng 1

UserControl LoginControl phục vụ việc login và tài khoản của chương trình.

III. Chuẩn ₫ầu ra : Sinh viên nắm vững và xây dựng thành thạo các UserControl có chức năng ₫ặc thù

cũng như xây dựng ứng dụng dùng lai các UserControl.

IV. Qui trình :

IV.1 Xây dựng User Control

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 Control Library" 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. MyUserControls), click button OK ₫ể tạo Project theo các thông số ₫ã khai báo.

3. Ngay sau Project vừa ₫ược tạo ra, nó có sẵn 1 User Control mới có tên mặc ₫ịnh là UserControl1, nó chỉ là 1 vùng hình chữ nhật trống, chứ chưa có gì. Dời chuột về cửa sổ Solution Explorer (thường ở trên phải màn hình), ấn kép chuột vào mục UserControl1.cs ₫ể hiển thị menu lệnh, chọn option Rename, nhập tên mới là LoginControl.cs và chọn button Yes khi ₫ược hỏi.

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 LoginControl và vẽ nó với kích thước mong muốn. Hiệu chỉnh thuộc tính Text = "Nhập tên user :". Nếu cần, hãy thay ₫ổi vị trí và kích thước của Label và của LoginControl.

5. Dời chuột về cửa sổ ToolBox, duyệt tìm phần tử TextBox (trong nhóm Common Controls), chọn nó, dời chuột về vị trí thích hợp trong LoginControl (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) = txtUser. 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 và 5 ₫ể vẽ Label "Nhập password :", TextBox có (Name) = txtPassword, 1 button "Đăng nhập" có (Name) = btnLogin.

7. Dời chuột về và chọn button "Đăng nhập", 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 Button, duyệt tìm sự kiện Click, ấn kép chuột vào comboBox bên phải của Click ₫ể máy tạo tự ₫ộng hàm xử lý rồi viết code cho hàm này như sau : private void btnLogin_Click(object sender, EventArgs e) { //kiểm tra ₫ã nhập user name chưa if (txtUser.Text.Length == 0) {

Page 92: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 2

MessageBox.Show("Hãy nhập tên user."); return; } //kiểm tra ₫ã nhập password chưa if (txtPassword.Text.Length == 0) { MessageBox.Show("Hãy nhập password."); return; } //tạo sự kiện Click ₫ể gọi hàm xử lý sự kiện Click //do người lập trình ứng dụng viết OnSubmitClicked(sender,e); }

8. Viết thêm ₫oạn code ₫ịnh nghĩa delegate, event và 2 thuộc tính UserName, Password như sau (nằm trước hay sau hàm sự lý Click chuột cho button) : //₫ịnh nghĩa delegate phục vụ cho event public delegate void SubmitClickedHandler(object sender, EventArgs e); //₫ịnh nghĩa event SubmitClicked public event SubmitClickedHandler SubmitClicked; //₫ịnh nghĩa hàm xử lý sự kiện SubmitClicked protected virtual void OnSubmitClicked(object sender, EventArgs e) { // kiểm tra xem có hàm xử lý sự kiện SubmitClicked ? //nếu có thì gọi nó if (SubmitClicked != null) { SubmitClicked(sender, e); // Notify Subscribers } } //₫ịnh nghĩa thuộc tính giao tiếp có tên là UserName public string UserName { get { return txtUser.Text; } set { txtUser.Text = value; } } //₫ịnh nghĩa thuộc tính giao tiếp có tên là Password public string Password { get { return txtPassword.Text; } set { txtPassword.Text = value; } }

9. Chọn menu Build.Build Solution ₫ể dịch và tạo file thư viện chứa các user control. Nếu có lỗi thì sữa và dịch lại.

10. Nếu dịch thành công, file thư viện có tên là MyUserControls.dll sẽ ₫ược tạo ra trong thư mục con Debug (hay Release tùy chế ₫ộ dịch) trong thư mục chứa Project. Ta nên copy file này vào thư mục chung chứa các file thư viện ₫ể sau này dùng tiện lợi hơn.

IV.2 Xây dựng ứng dụng dùng User Control

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. UseLoginControl), click button OK ₫ể tạo Project theo các thông số ₫ã khai báo.

Page 93: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 3

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ị, chọn menu View.Toolbox ₫ể hiển thị nó (thường nằm ở bên trái màn hình). Dời chuột vào trong cửa sổ Toolbox, ấn phải chuột ₫ể 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 Browse ₫ể hiển thị cửa sổ duyệt tìm file, hãy duyệt tìm ₫ến thư mục chứa file MyUserControls.dll vừa xây dựng ₫ược trong các slide trước, chọn file dll rồi click button OK ₫ể "add" các usercontrol trong thư viện này vào cửa sổ Toolbox của Project ứng dụng. Bây giờ việc dùng LoginControl giống y như các ₫iều khiển có sẵn khác.

5. Duyệt tìm phần tử LoginControl (trong nhóm General ở cuối cửa sổ Toolbox), 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.

6. Chọn ₫ối tượng LoginControl ₫ể hiển thị cửa sổ thuộc tính của nó, click chuột vào button Events ₫ể hiển thị các event của nó. duyệt tìm event SubmitClicked vào tạo hàm xử lý cho event này. Viết code cho hàm xử lý như sau : private void loginControl1_SubmitClicked(object sender, EventArgs e) { //viết code xử lý việc ₫ăng nhập tài khoản //ở ₫ây chỉ hiển thị thông báo ₫ể kiểm tra MessageBox.Show("Đã ₫ăng ký tài khoản : " + loginControl1.UserName); }

7. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Hãy thử sử dụng ₫ối tượng LoginControl và ₫ánh giá kết quả.

Page 94: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 1

MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG Bài thực hành số 9.1 : Xây dựng Inherited control và ứng dụng dùng nó

I. Mục tiêu :

Giúp SV làm quen với cách thức xây dựng 1 Inherited control giải quyết chức năng ₫ặc thù của mình bằng cách thừa kế ₫iều khiển ₫ã có sẵn có tính năng gần giống.

II. Nội dung : xây dựng 1 Inherited Control có tên là MyTextBox, nó là TextBox nhưng có thể hoạt

₫ộng ở 1 trong nhiều chế ₫ộ khác nhau :

1. Common (giống như textbox của .Net),

2. Text (chỉ cho nhập các ký tự alphabet),

3. NumInt (chỉ cho phép nhập các ký số),

4. NumReal (chỉ cho phép nhập các ký số và dấu chấm thập phân).

III. Chuẩn ₫ầu ra : Sinh viên nắm vững và xây dựng thành thạo các Inherited Control có chức năng ₫ặc

thù cũng như xây dựng ứng dụng dùng lai các Inherited Control.

IV. Qui trình :

IV.1 Xây dựng Inherited control

1. Chạy VS .Net, chọn menu File.Open.Project ₫ể hiển thị cửa sổ duyệt file. Duyệt và tìm file *.sln quản lý Project "Windows Control Library" có sẵn từ bài thực hành 9.1 ₫ể mở lại Project này.

2. Quan sát cây Project, chúng ta ₫ã thấy có mục LoginControl.cs quản lý user control ₫ã xây dựng từ bài thực hành 9.1. Ấn phải chuột vào gốc của cây Project trong cửa sổ "Solution Explorer", chọn option Add.User Control ₫ể tạo mới 1 User Control, nhập tên là MyTextBox.cs rồi click button Add ₫ể tạo mới nó.

3. Lúc này control mới chỉ là 1 vùng hình chữ nhật trống. Dời chuột về mục MyTextBox.cs trong cửa sổ Project, ấn phải chuột trên nó rồi chọn option "View Code" ₫ể hiển thị cửa sổ soạn mã nguồn cho MyTextBox control.

4. Thêm lệnh ₫ịnh nghĩa kiểu liệt kê các chế ₫ộ làm việc của MyTextBox : public enum ValidationType { Common = 0, //giống như TextBox bình thường NumInt, //chỉ nhận các ký số NumReal, //chỉ nhận các ký số và dấu chấm thập phân Text //chỉ nhận các ký tự chữ }

5. Hiệu chỉnh lại lệnh ₫ịnh nghĩa class MyTextBox ₫ể thừa kế class TextBox (thay vì UserControl như mặc ₫ịnh). Nội dung chi tiết của class MyTextBox ₫ược liệt kê ở các slide sau. public partial class MyTextBox : TextBox { bool fPoint; //hàm contructor public MyTextBox() : base() { InitializeComponent(); //₫ăng ký hàm xử lý sự kiện KeyPress this.KeyPress += new KeyPressEventHandler(OnKeyPress);

Page 95: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 2

} //₫ịnh nghĩa thuộc tính ValidateFor miêu tả chế ₫ộ làm việc private int intValidType = (int)ValidationType.Text; public ValidationType ValidateFor { get { return (ValidationType)intValidType; } set { intValidType = (int)value; } } //hàm xử lý sự kiện gỏ phím KeyPress protected void OnKeyPress(object sender, KeyPressEventArgs e) { //xác ₫ịnh mã ký tự ₫ược nhập char ch = e.KeyChar; //kiểm tra chế ₫ộ hoạt ₫ộng ₫ể phản ứng switch (intValidType) { case (int)ValidationType.Common: //nếu là kiểu tổng quát, thì không xử lý thêm gì cả return; case (int)ValidationType.NumInt: //nếu là kiểu số nguyên thì chỉ nhận ký số if (!Char.IsDigit(ch)) e.KeyChar = (char)0; return; case (int)ValidationType.NumReal: //nếu là kiểu số thực thì chỉ nhận ký số + dấu . if (Char.IsDigit(ch)) return; if (ch == '.' && fPoint==false) { fPoint = true; return; } e.KeyChar = (char)0; return; case (int)ValidationType.Text: //nếu là kiểu chuỗi văn bản thì chỉ nhận ký tự chữ ch = Char.ToLower(ch); if (ch < 'a' || 'z' < ch) e.KeyChar = (char)0; return; } } //kết thúc lệnh switch, hàm OnKeyPress, ...

6. Chọn menu Build.Build Solution ₫ể dịch và tạo file thư viện chứa các user control. Nếu có lỗi thì sữa và dịch lại. Lưu ý khi máy báo lỗi ở hàng lệnh this.AutoScaleMode = ... thì hãy chú thích hàng lệnh này hay xóa nó luôn cũng ₫ược.

10. Nếu dịch thành công, file thư viện có tên là MyUserControls.dll sẽ ₫ược tạo ra trong thư mục con Debug (hay Release tùy chế ₫ộ dịch) trong thư mục chứa Project. Ta nên copy file này vào thư mục chung chứa các file thư viện ₫ể sau này dùng tiện lợi hơn.

IV.2 Xây dựng ứng dụng dùng Inherited Control

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. UseMyTextBox), click button OK ₫ể tạo Project theo các thông số ₫ã khai báo.

Page 96: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 3

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. Dời chuột vào trong cửa sổ Toolbox, ấn phải chuột ₫ể 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 Browse ₫ể hiển thị cửa sổ duyệt tìm file, hãy duyệt tìm ₫ến thư mục chứa file MyUserControls.dll vừa xây dựng ₫ược trong các slide trước, chọn file dll rồi click button OK ₫ể "add" các usercontrol trong thư viện này vào cửa sổ Toolbox của Project ứng dụng.

5. 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 = "Nhập chuỗi bất kỳ :". Nếu cần, hãy thay ₫ổi vị trí và kích thước của Label và Form.

6. Duyệt tìm phần tử MyTextBox (trong nhóm General ở cuối cửa sổ Toolbox), chọn nó, dời chuột về vị trí thích hợp trong Form (bên phải Label vừa vẽ) và vẽ nó với kích thước mong muốn. Vào cửa sổ thuộc tính của ₫ối tượng MyTextBox vừa vẽ, ₫ặt thuộc tính (Name) = txtCommon, thuộc tính ValidateFor = Common ₫ể nó hoạt ₫ộng ở chế ₫ộ nhập ký tự bình thường.

7. Lặp 2 bước 5 và 6 ba lần ₫ể tạo thêm 3 cặp (Label, MyTextBox) khác, các MyTextBox tạo mới lần lượt có thuộc tính ValidateFor = Text, NumInt, NumReal ₫ể hoạt ₫ộng trên hoặc chuỗi văn bản, hoặc số nguyên, hoặc số thực.

Đố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 ứng dụng có dạng sau :

8. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Hãy thử nhập các loại ký tự vào các ₫ối tượng MyTextBox và ₫ánh giá kết quả.

Page 97: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 1

MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG Bài thực hành số 9.3 : Xây dựng Owner-drawn control và ứng dụng dùng nó

I. Mục tiêu :

Giúp SV làm quen với cách thức xây dựng 1 Owner-drawn control giải quyết chức năng ₫ặc thù của mình bằng cách thừa kế ₫iều khiển ₫ã có sẵn có cùng tính năng nhưng giao diện chưa phù hợp với nhu cầu riêng.

II. Nội dung : Xây dựng button HeartButton, nó là Button nhưng bộ mặt không phải là hình chữ nhật

có ₫ường viền thông thường mà là một trái tim màu ₫ỏ tươi.

III. Chuẩn ₫ầu ra : Sinh viên nắm vững và xây dựng thành thạo các Owner-drawn Control có chức năng

₫ặc thù cũng như xây dựng ứng dụng dùng lại các Owner-drawn Control.

IV. Qui trình :

IV.1 Xây dựng Owner-drawn control

1. Chạy VS .Net, chọn menu File.Open.Project ₫ể hiển thị cửa sổ duyệt file. Duyệt và tìm file *.sln quản lý Project "Windows Control Library" có sẵn từ bài thực hành 9.2 ₫ể mở lại Project này.

2. Quan sát cây Project, chúng ta ₫ã thấy có mục LoginControl.cs quản lý user control ₫ã xây dựng từ bài thực hành 9.1, mục MyTextBox.cs quản lý inherited control ₫ã xây dựng từ bài thực hành 9.2. Ấn phải chuột vào gốc của cây Project trong cửa sổ "Solution Explorer", chọn option Add.User Control ₫ể tạo mới 1 User Control, nhập tên là HeartButton.cs rồi click button Add ₫ể tạo mới nó.

3. Lúc này control mới chỉ là 1 vùng hình chữ nhật trống. Dời chuột về mục HeartButton.cs trong cửa sổ Project, ấn phải chuột trên nó rồi chọn option "View Code" ₫ể hiển thị cửa sổ soạn mã nguồn cho HeartButton control.

4. Hiệu chỉnh lại lệnh ₫ịnh nghĩa class HeartButton ₫ể thừa kế class Button (thay vì UserControl như mặc ₫ịnh). Nội dung chi tiết của class HeartButton như sau : namespace MyUserControls { public partial class HeartButton : Button { public HeartButton() { InitializeComponent(); }

//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+1] != key.G) return false; if (pbase[idx+2] != key.R) return false; if (pbase[idx+3] != key.A) return false; return true; } //hàm chuyển ảnh bitmap thành Region ₫ược qui ₫ịnh bởi ₫ường viền của ảnh Region ConvertB2R(Bitmap bitmap, Color Key)

Page 98: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 2

{ // 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)) { 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;

Page 99: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 3

} //now create the region from all the rectangles Region region = new Region(path); //clean up path.Dispose(); bitmap.UnlockBits(bitmapData); return region; } //tác vụ vẽ bộ mặt giao diện của Button protected override void OnPaint(PaintEventArgs e) { //tạo ₫ối tượng image gốc chứa ảnh trái tim màu ₫ỏ Bitmap bm = (Bitmap)Bitmap.FromFile("d:\\bgbutton.bmp"); //tạo ₫ối tượng image chứa ảnh trái tim màu ₫ỏ theo kich thuoc cua Control Bitmap newBitmap = new Bitmap(ClientSize.Width, ClientSize.Height); Graphics g = Graphics.FromImage(newBitmap); g.DrawImage(bm, new Rectangle(0, 0, newBitmap.Width, newBitmap.Height), new Rectangle(1, 1, bm.Width-2, bm.Height-2), GraphicsUnit.Pixel); //xác ₫ịnh ₫ối tượng vẽ của Button g = e.Graphics; //vẽ inage gốc theo chế ₫ộ zoom vào button g.DrawImage(newBitmap, 0, 0); Color col = newBitmap.GetPixel(1, 1); this.Region = ConvertB2R(newBitmap, col); //this.BackgroundImage = bm; //this.FormBorderStyle = FormBorderStyle.None; //₫ịnh nghĩa ₫ối tượng miêu tả cách thức hiển thị chuỗi StringFormat format1 = new StringFormat(StringFormatFlags.NoClip); format1.Alignment = StringAlignment.Center; //vẽ chuỗi caption của button g.DrawString(this.Text, this.Font, Brushes.White, this.Width / 2, this.Height / 3, format1); }

} }

5. Chọn menu Build.Build Solution ₫ể dịch và tạo file thư viện chứa các user control. Nếu có lỗi thì sữa và dịch lại. Lưu ý khi máy báo lỗi ở hàng lệnh this.AutoScaleMode = ... thì hãy chú thích hàng lệnh này hay xóa nó luôn cũng ₫ược.

6. Nếu dịch thành công, file thư viện có tên là MyUserControls.dll sẽ ₫ược tạo ra trong thư mục con Debug (hay Release tùy chế ₫ộ dịch) trong thư mục chứa Project. Ta nên copy file này vào thư mục chung chứa các file thư viện ₫ể sau này dùng tiện lợi hơn.

IV.2 Xây dựng ứng dụng dùng Owner-drawn Control

Trong chương 5, chúng ta ₫ã 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. Chúng ta ₫ã dùng 3 textbox ₫ể nhập liệu và 1 button ₫ể khởi ₫ộng việc giải phương trình và hiển thị kết quả. Bây giờ chúng ta hãy hiệu chỉnh lại chương trình giải phương trình bậc 2 ₫ể dùng 3 ₫ối tượng MyTextBox và 1 ₫ối tượng HeartButton.

1. Nhân bản thư mục VCGPTB2 (có ₫ược trong bài thực hành 5.1) thành thư mục mới tên là UseHeartButton.

Page 100: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 4

2. Chạy VS .Net, chọn menu File.Open.Project ₫ể hiển thị cửa sổ duyệt file. Duyệt và tìm file VCGPTB2.sln trong thư mục UseHeartButton ₫ể mở lại Project này.

3. Dời chuột về mục Form1.cs của cây Project trong cửa sổ "Solution Explorer", ấn kép chuột vào nó ₫ể hiển thị lại cửa sổ thiết kế trực quan cho Form chương trình.

4. Chọn và xóa 3 textbox và button có sẵn.

5. 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. Dời chuột về nhóm Components trong cửa sổ Toolbox, ấn phải chuột trên nó ₫ể 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 Browse ₫ể hiển thị cửa sổ duyệt tìm file, hãy duyệt tìm ₫ến thư mục chứa file MyUserControls.dll vừa xây dựng ₫ược trong phần ₫ầu của bài thực hành, chọn file dll rồi click button OK ₫ể "add" các usercontrol trong thư viện này vào nhóm Components của cửa sổ Toolbox của Project ứng dụng.

6. Duyệt tìm phần tử MyTextBox (thường ở cuối nhóm Components), chọn nó, dời chuột về bên phải Label “Nhập a:” và vẽ nó với kích thước mong muốn. Vào cửa sổ thuộc tính của ₫ối tượng MyTextBox vừa vẽ, ₫ặt thuộc tính (Name) = txtA, thuộc tính ValidateFor = NumReal ₫ể nó hoạt ₫ộng ở chế ₫ộ nhập số thực.

7. Lặp lại bước 6 hai lần ₫ể tạo thêm 2 ₫ối tượng MyTextBox khác, các MyTextBox tạo mới lần lượt có thuộc tính (Name) = txtB, txtC còn thuộc tính ValidateFor = NumReal.

Đố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.

8. Duyệt tìm phần tử HeartButton (thường ở cuối nhóm Components), chọn nó, dời chuột về ngay dưới MyTextBox txtC và vẽ nó với kích thước mong muốn. Vào cửa sổ thuộc tính của ₫ối tượng HeartButton vừa vẽ, ₫ặt thuộc tính (Name) = btnStart, thuộc tính Text = “Bắt ₫ầu giải”.

Sau khi thiết kế xong, form ứng dụng có dạng sau :

9. Chọn lại button ₫ể 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 ₫ối tượng HeartButton, duyệt tìm sự kiện quan tâm (Click), click chuột

vào dấu bên phải sự kiện Click ₫ể máy hiển thị danh sách các hàm xử lý ₫ã có, chọn lại hàm xử lý có tên là btnStart().

Page 101: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 5

10. 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ả.

Page 102: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 1

MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG Bài thực hành số 9.4 : Sự hiệu quả của lập trình song song

I. Mục tiêu :

Giúp SV làm quen với cách thức xây dựng 1 ứng dụng dùng thuật giải song song bằng multi-threads và thấy rõ tính hiệu quả của lập trình song song.

II. Nội dung : Xây dựng chương trình tính tích 2 ma trận có kích thước ₫ủ lớn (1000*1000) với số

lượng thread tham gia do người dùng quyết ₫ịnh.

III. Chuẩn ₫ầu ra : Sinh viên nắm vững và xây dựng thành thạo các ứng dụng dùng thuật giải song song

bằng multi-threads và thấy rõ tính hiệu quả của lập trình song song.

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_TichMatran), 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í trên trái của form và vẽ nó với kích thước mong muốn. Hiệu chỉnh thuộc tính Text = "Nhap số thread cần dùng :". 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) = txtThreads. Nếu cần, hãy thay ₫ổi vị trí và kích thước của TextBox.

6. Duyệt tìm phần tử Button (trong nhóm Common Controls), chọn nó, dời chuột về vị trí bên phải TextBox vừa vẽ và vẽ nó với kích thước mong muốn. Hiệu chỉnh thuộc tính (Name) = btnStart và Text = "Tính tích 2 ma trận".

7. Duyệt tìm phần tử ListBox (trong nhóm Common Controls), chọn nó, dời chuột về vị trí bên dưới Label và vẽ nó với kích thước chiếm hết phần còn lại của Form. Hiệu chỉnh thuộc tính (Name) = lbKetqua.

Sau khi thiết kế xong, Form có dạng sau :

Page 103: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 2

8. Dời chuột về button "Tính tích 2 ma trận", ấ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.

9. Viết code cho hàm btnStart_Click() như sau : private void btnStart_Click(object sender, EventArgs e) { int cnt = Int32.Parse(txtThreads.Text); //lấy mộc thời gian hiện tại DateTime t1 = DateTime.Now; if (cnt == 1) { //dùng thuật giải tuần tự TinhTich(new Params(0, N, 0)); } else //dùng thuật giải song song { int i; Thread t; for (i = 0; i < cnt-1; i++) { //lặp tạo và chạy cnt-1 thread con stateLst[i] = 0; t = new Thread(new ParameterizedThreadStart(TinhTich)); t.Start (new Params(i*N/cnt, (i+1)*N/cnt,i)); } //tính N/cnt hàng cuối cùng của ma trận tích TinhTich(new Params((cnt-1)*N/cnt, N, cnt-1)); //₫ợi cnt-1 thread con tính xong for (i = 0; i < cnt-1; i++) while (stateLst[i] == 0); //chờ } //lấy mộc thời gian hiện tại DateTime t2 = DateTime.Now; //tính thời gian tính tích 2 ma trận

Page 104: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 3

System.TimeSpan diff = t2.Subtract(t1); //hiển thị kết quả lên Listbox cho user xem lbKetqua.Items.Add(String.Format("{0:d} threads ==> Thoi gian chay la {1:d2} phut {2:d2} giay {3:d3} ms", cnt, diff.Minutes, diff.Seconds, diff.Milliseconds)); }

10. Hiệu chỉnh hàm khởi tạo form như sau :

public Form1() { InitializeComponent(); //xóa nội dung ListBox kết quả lbKetqua.Items.Clear(); //khởi tạo 2 ma trận A và B N = 1000; A = new double[N,N]; B = new double[N,N]; C = new double[N,N]; int h, c; for (h = 0 ; h < N; h++) for (c = 0; c < N; c++) A[h,c] = B[h,c] = c; for (h = 0; h < 4; h++) stateLst[h] = 0; }

11. 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 class chứa thông số truyền cho thread con dùng class Params { public int sr; public int er; public int id; public Params(int s, int e, int i) { sr = s; er = e; id = i; } }; //₫ịnh nghĩa 3 biến ma trận và kích thước của chúng double[,] A; double[,] B; double[,] C; int N; //₫ịnh nghĩa danh sách trạng thái các thread con int[] stateLst = new int [20]; //₫ịnh nghĩa hàm tính 1 số hàng của ma trận tích void TinhTich (object obj) { Params p = (Params)obj; int h, c, k;

Page 105: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 4

for (h = p.sr; h < p.er; h++) for (c = 0; c < N; c++) { double s = 0; for (k = 0; k < N; k++) s = s + A[h, k] * B[k, c]; C[h, c] = s; } stateLst[p.id] = 1; }

12. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Hãy thử nhập từng giá trị 1, 2, 3, 4,... rồi click chuột vào button "Tính tích 2 ma trận" ₫ể xem thời gian tính tích 2 ma trận, từ ₫ó thấy rõ tính hiệu quả của lập trình multi-threads so với lập trình tuần tự.

Page 106: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 1

MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG Bài thực hành số 9.5 : Vấn ₫ề tương tranh của lập trình song song

I. Mục tiêu :

Giúp SV làm quen với cách thức xây dựng 1 ứng dụng dùng thuật giải song song bằng multi-threads và thấy rõ vấn ₫ề tương tranh của các thread chạy ₫ồng thời.

II. Nội dung : Xây dựng chương trình cho phép user tạo/xóa/tạm dừng/tăng ₫ộ ưu tiên/giảm ₫ộ ưu

tiên từng thread, mỗi thread có tên là ký tự A-Z ₫ược người dùng gỏ vào. Khi 1 thread chạy, nó sẽ thể hiện icon miêu tả mình lên màn hình và di chuyển icon

của mình theo quỹ ₫ạo xác ₫ịnh. Từng thời ₫iểm, mỗi thread chiếm 1 vùng hiển thị hình vuông trên form ₫ể hiển thị icon của mình. Đây là tài nguyên dùng chung của các thread và có thể xảy ra tranh chấp bất kỳ lúc nào.

III. Chuẩn ₫ầu ra : Sinh viên nắm vững và xây dựng thành thạo các ứng dụng dùng thuật giải song song

bằng multi-threads và thấy rõ vấn ₫ề tương tranh của các thread chạy ₫ồng thời.

IV. Qui trình :

1. Chạy trình soạn thảo ảnh (thí dụ Paint), soạn thảo từng icon miêu tả từng thread, từ thread A ₫ến thread Z với kích thước 30*30 pixel, mỗi icon ₫ược lưu trên 1 file bitmap với tên là ImageA.bmp ₫ến ImageZ.bmp.

2. 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. ThreadDemo2), 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. Trong bài thực hành này, chúng ta không thiết kế trực quan Form ứng dụng vì Form sẽ ₫ược hiệu chỉnh ₫ộng bởi code ứng dụng.

5. Dời chuột về gốc của cây Project (có tên là ThreadDemo2), click phải chuột ₫ể hiển thị menu lệnh, duyệt tìm và chọn chức năng Add.New Items.Resource File rồi button Add ₫ể thêm 1 file quản lý tài nguyên vào Project (có tên mặc ₫ịnh là Resource1).

6. Khi cửa sổ hiển thị nội dung file Resource1 hiển thị, click vào tam giác ₫en bên phải chức năng "Add Resource", chọn mục "Add Existing File..." rồi duyệt chọn các file bitmap ₫ược soạn ở bước 1 vào. Tên nhận dạng mặc ₫ịnh của từng resource chính là tên file resource tương ứng nhưng không có phần mở rộng .bmp.

6. Chọn Form ₫ể hiển thị cửa sổ thuộc tính của Form, 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 (KeyDown), ấn kép chuột vào comboBox bên phải sự kiện KeyDown ₫ể 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 :

//hàm xử lý gỏ phím của user ₫ể quản lý thread private void Form1_KeyDown(object sender, KeyEventArgs e) {

Page 107: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 2

//xác ₫ịnh mã phím ấn, nếu không phải từ A-Z thì phớt lờ int newch = e.KeyValue; if (newch <0x41 || newch > 0x5a) return; //xác ₫ịnh chức năng mà user muốn và thực hiện if (e.Control && e.Shift) { //kill thread threadLst[newch - 65].start = false; } else if (e.Control && e.Alt) { //giảm ₫ộ ưu tiên tối thiểu threadLst[newch - 65].t.Priority = ThreadPriority.Lowest; } else if (e.Control) { //tạm dừng thread if (threadLst[newch-65].start && !threadLst[newch-65].suspend) { threadLst[newch-65].t.Suspend(); threadLst[newch-65].suspend = true; } } else if (e.Alt) { //cho thread chạy lại if (threadLst[newch-65].start && threadLst[newch-65].suspend) { threadLst[newch-65].t.Resume(); threadLst[newch-65].suspend = false; } } else if (e.Shift) { //tăng ₫ộ ưu tiên tối ₫a threadLst[newch-65].t.Priority = ThreadPriority.Highest; } else { //tạo mới thread và bắt ₫ầu chạy if (!threadLst[newch-65].start) { threadLst[newch-65].start = true; threadLst[newch-65].suspend = false; threadLst[newch - 65].t = new Thread(new ParameterizedThreadStart(Running)); threadLst[newch - 65].t.Start(threadLst[newch - 65]); } } }

7. Tiếp tục tạo hàm xử lý sự kiện Load cho Form rồi viết code như sau : private void Form1_Load(object sender, EventArgs e) { rnd = new Random(); threadLst = new MyThread[26]; int i; String buf; //Lặp thiết lập trạng thái ban ₫ầu cho 26 thread từ A-Z for (i = 0; i < 26; i++) { threadLst[i] = new MyThread(rnd,xMax,yMax); threadLst[i].suspend = threadLst[i].start = false; char c = (char)(i + 65); ResourceManager resourceManager = new ResourceManager ("ThreadDemo2.Resource1", GetType ().Assembly); Bitmap bm = (Bitmap)resourceManager.GetObject ("Image"+c.ToString()); threadLst[i].Pic = bm; threadLst[i].Xmax = 25; threadLst[i].Ymax = 20; }

Page 108: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 3

ClientSize = new Size(25 * 30, 20 * 30); this.Location = new Point(0, 0); this.BackColor = Color.Black; }

8. 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 thuộc tính cần dùng MyThread[] threadLst; const int xCell = 30; const int yCell = 30; const int xMax = 25; const int yMax = 20; public Random rnd = new Random(); //₫ịnh nghĩa hàm giả lập hành vi của thread void MySleep(long count) { long i, j, k=0; for (i = 0; i < count; i++) for (j = 0; j < 64000; j++) k = k + 1; } //₫ịnh nghĩa hàm mà mỗi thread sẽ chạy void Running(object obj) { MyThread p = (MyThread)obj; Graphics g = this.CreateGraphics(); //tạo brush với màu ₫en, tô ₫ặc Brush brush = new SolidBrush(Color.FromArgb(0, 0, 0)); while (p.start) { //lặp thực hiện công việc trong khi ở trạng thái start //giả lập hành vi của thread. MySleep(200); //xóa icon ở vị trí cũ, xác ₫ịnh và hiển thị icon ở vị trí mới try { g.FillRectangle(brush, xCell * p.Pos.X, yCell * p.Pos.Y, xCell, yCell); p.HieuchinhDinh(); g.DrawImage(p.Pic, xCell * p.Pos.X, yCell * p.Pos.Y); } catch (Exception e) { p.t.Abort(); } } //xóa icon của thread ở vị trí hiện hành trước khi xóa thread try { g.FillRectangle(brush, xCell * p.Pos.X, yCell * p.Pos.Y, xCell, yCell); } catch (Exception e) { p.t.Abort(); } //dừng và xóa Thread p.t.Abort(); }

Page 109: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 4

9. Dời cursor về ₫ầu file mã nguồn của Form, thêm các lệnh using sau ₫ây ₫ể sử dụng các namespace tương ứng :

using System.Threading; using System.Resources;

10. Dời

11. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Hãy thử :

- gỏ từng phím từ A-Z ₫ể khởi chạy thread tương ứng.

- gỏ Ctrl-X ₫ể tạm dừng chạy thread X.

- gỏ Alt-X ₫ể chạy lại thread X.

- gỏ Ctrl-Alt-X ₫ể giảm ₫ộ ưu tiên cho thread X.

- gỏ Shift-X ₫ể tăng ₫ộ ưu tiên cho thread X.

- gỏ Ctrl-Shift-X ₫ể xóa thread X.

12. Khi một thread nào ₫ó bị tạm dừng, hãy quan sát icon miêu tả nó theo thời gian, có thể icon thread khác sẽ chạy ₫ến và ₫è mất icon miêu tả thread ₫ang tạm dừng, xác xuất hiện tượng này càng lớn nếu có nhiều thread ₫ang chạy. Đây là vấn ₫ề tương tranh của các thread. Làm sao ₫ể giải quyết ?

Page 110: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 1

MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG Bài thực hành số 9.6 : Giải quyết tương tranh giữa các thread

I. Mục tiêu :

Giúp SV làm quen với cách thức xây dựng 1 ứng dụng dùng thuật giải song song bằng multi-threads và cách thức giải quyết tương tranh của các thread chạy ₫ồng thời.

II. Nội dung : Xây dựng chương trình cho phép user tạo/xóa/tạm dừng/tăng ₫ộ ưu tiên/giảm ₫ộ ưu

tiên từng thread, mỗi thread có tên là ký tự A-Z ₫ược người dùng gỏ vào. Khi 1 thread chạy, nó sẽ thể hiện icon miêu tả mình lên màn hình và di chuyển icon

của mình theo quỹ ₫ạo xác ₫ịnh. Từng thời ₫iểm, mỗi thread chiếm 1 vùng hiển thị hình vuông trên form ₫ể hiển thị icon của mình. Đây là tài nguyên dùng chung của các thread và có thể xảy ra tranh chấp bất kỳ lúc nào, do ₫ó phải giải quyết tương tranh giữa các thread khi chúng cùng muốn chiếm 1 cell hiển thị nào ₫ó.

III. Chuẩn ₫ầu ra : Sinh viên nắm vững và xây dựng thành thạo các ứng dụng dùng thuật giải song song

bằng multi-threads và thấy rõ cách thức giải quyết tương tranh của các thread chạy ₫ồng thời.

IV. Qui trình :

1. Chạy trình soạn thảo ảnh (thí dụ Paint), soạn thảo từng icon miêu tả từng thread, từ thread A ₫ến thread Z với kích thước 30*30 pixel, mỗi icon ₫ược lưu trên 1 file bitmap với tên là ImageA.bmp ₫ến ImageZ.bmp.

2. 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. ThreadDemo3), 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. Trong bài thực hành này, chúng ta không thiết kế trực quan Form ứng dụng vì Form sẽ ₫ược hiệu chỉnh ₫ộng bởi code ứng dụng.

5. Dời chuột về gốc của cây Project (có tên là ThreadDemo3), click phải chuột ₫ể hiển thị menu lệnh, duyệt tìm và chọn chức năng Add.New Items.Resource File rồi button Add ₫ể thêm 1 file quản lý tài nguyên vào Project (có tên mặc ₫ịnh là Resource1).

6. Khi cửa sổ hiển thị nội dung file Resource1 hiển thị, click vào tam giác ₫en bên phải chức năng "Add Resource", chọn mục "Add Existing File..." rồi duyệt chọn các file bitmap ₫ược soạn ở bước 1 vào. Tên nhận dạng mặc ₫ịnh của từng resource chính là tên file resource tương ứng nhưng không có phần mở rộng .bmp.

6. Chọn Form ₫ể hiển thị cửa sổ thuộc tính của Form, 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 (KeyDown), ấn kép chuột vào comboBox bên phải sự kiện KeyDown ₫ể 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 :

Page 111: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 2

//hàm xử lý gỏ phím của user ₫ể quản lý thread private void Form1_KeyDown(object sender, KeyEventArgs e) { //xác ₫ịnh mã phím ấn, nếu không phải từ A-Z thì phớt lờ int newch = e.KeyValue; if (newch < 0x41 || newch > 0x5a) return; //xác ₫ịnh chức năng mà user muốn và thực hiện if (e.Control && e.Shift) { //kill thread threadLst[newch - 65].start = false; } else if (e.Control && e.Alt) { //giảm ₫ộ ưu tiên tối thiểu threadLst[newch - 65].t.Priority = ThreadPriority.Lowest; } else if (e.Control) { //tạm dừng thread if (threadLst[newch - 65].start && !threadLst[newch - 65].suspend) { threadLst[newch - 65].t.Suspend(); threadLst[newch - 65].suspend = true; } } else if (e.Alt) { //cho thread chạy lại if (threadLst[newch - 65].start && threadLst[newch - 65].suspend) { threadLst[newch - 65].t.Resume(); threadLst[newch - 65].suspend = false; } } else if (e.Shift) { //tăng ₫ộ ưu tiên tối ₫a threadLst[newch - 65].t.Priority = ThreadPriority.Highest; } else { //tạo mới thread và bắt ₫ầu chạy if (!threadLst[newch - 65].start) { threadLst[newch - 65].start = true; threadLst[newch - 65].suspend = false; threadLst[newch - 65].t = new Thread(new ParameterizedThreadStart(Running)); threadLst[newch - 65].t.Start(threadLst[newch - 65]); } } } 

7. Tiếp tục tạo hàm xử lý sự kiện Load cho Form rồi viết code như sau : private void Form1_Load(object sender, EventArgs e) {

Page 112: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 3

rnd = new Random(); threadLst = new MyThread[26]; int i; //tạo ma trận semaphore Mutex ₫ể bảo vệ các cell nàm hình mutList = new Mutex[yMax, xMax]; int h, cot; for (h = 0; h < yMax; h++) for (cot = 0; cot < xMax; cot++) mutList[h, cot] = new Mutex(); //Lặp thiết lập trạng thái ban ₫ầu cho 26 thread từ A-Z for (i = 0; i < 26; i++) { threadLst[i] = new MyThread(rnd, xMax, yMax); threadLst[i].suspend = threadLst[i].start = false; char c = (char)(i + 65); ResourceManager resourceManager = new ResourceManager("ThreadDemo3.Resource1", GetType().Assembly); Bitmap bm = (Bitmap)resourceManager.GetObject("Image" + c.ToString()); threadLst[i].Pic = bm; threadLst[i].Xmax = 25; threadLst[i].Ymax = 20; } ClientSize = new Size(25 * 30, 20 * 30); this.Location = new Point(0, 0); this.BackColor = Color.Black; }

8. Tiếp tục tạo hàm xử lý sự kiện FormClosed cho Form rồi viết code như sau : private void Form1_FormClosed(object sender, FormClosedEventArgs e) { int i; for (i = 0; i < 26; i++) if (threadLst[i].start) { threadLst[i].start = false; //thiet lap trang thai dung thread while (!threadLst[i].stop) ; //cho thread dung thanh cong } }

9. 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 thuộc tính cần dùng Mutex[,] mutList; MyThread[] threadLst; const int xCell = 30; const int yCell = 30; const int xMax = 25; const int yMax = 20; public Random rnd = new Random();

Page 113: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 4

//₫ịnh nghĩa hàm giả lập hành vi của thread void MySleep(long count) { long i, j, k = 0; for (i = 0; i < count; i++) for (j = 0; j < 64000; j++) k = k + 1; } //₫ịnh nghĩa hàm mà mỗi thread sẽ chạy void Running(object obj) { //ép kiểu tham số về MyThread theo yêu cầu xử lý MyThread p = (MyThread)obj; //tạo ₫ối tượng vẽ Graphics g = this.CreateGraphics(); //tạo chổi màu ₫en ₫ể xóa cell cũ Brush brush = new SolidBrush(Color.FromArgb(0, 0, 0)); //xin khóa truy xuất cell (x1,y1) mutList[p.Pos.Y, p.Pos.X].WaitOne(); int x1, y1; int x2, y2; bool kq; try { while (p.start) { //lặp trong khi chưa có yêu cầu kết thúc //xác ₫ịnh tọa ₫ộ hiện hành của thread x1 = p.Pos.X; y1 = p.Pos.Y; //hiển thị logo của thread ở (x1,y1) g.DrawImage(p.Pic, xCell * x1, yCell * y1); //thực hiện công việc của thread tốn 500ms MySleep(500); //xác ₫ịnh vị trí mới của thread p.HieuchinhVitri(); x2 = p.Pos.X; y2 = p.Pos.Y; //xin khóa truy xuất cell (x2,y2) while (true) { kq = mutList[y2, x2].WaitOne(new TimeSpan(0,0,2)); if (kq==true || p.start==false) break; } // Xóa vị trí cũ g.FillRectangle(brush, xCell * x1, yCell * y1, xCell, yCell); //trả cell (x1,y1) cho các thread khác truy xuất mutList[y1, x1].ReleaseMutex(); if (kq == false && p.start == false) { //xoa thread // dừng Thread p.t.Abort(); p.stop = true; return;

Page 114: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 5

} } } catch (Exception e) { p.t.Abort(); } //dọn dẹp thread trước khi ngừng x1 = p.Pos.X; y1 = p.Pos.Y; g.FillRectangle(brush, xCell * x1, yCell * y1, xCell, yCell); //trả cell (x1,y1) cho các thread khác truy xuất mutList[y1, x1].ReleaseMutex(); // dừng Thread p.stop = true; p.t.Abort(); } 

10. Dời cursor về ₫ầu file mã nguồn của Form, thêm các lệnh using sau ₫ây ₫ể sử dụng các namespace tương ứng :

using System.Threading; using System.Resources;

11. Dời chuột về gốc của cây Project (có tên là ThreadDemo3), click phải chuột ₫ể hiển thị menu lệnh, duyệt tìm và chọn chức năng Add.Class... ₫ể hiển thị cửa sổ "Add Class", hiệu chỉnh tên file chứa class là MyThread.cs rồi click button Add ₫ể thêm 1 class MyThread vào Project. Khi cửa sổ mã nguồn của class ₫ược hiển thị, hiệu chỉnh nội dung của class như sau :

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Threading; namespace ThreadDemo3 { class MyThread { const double PI = 3.1416; public Thread t; //tham khảo ₫ến thread hiện hành public Boolean start; //trạng thái Start của thread public Boolean suspend; //trạng thái Suspend của thread public Image Pic; //icon miêu tả thread internal int Xmax; //₫ộ rộng vùng chạy của thread internal int Ymax; //₫ộ cao vùng chạy của thread public Point Pos; //vị trí của thread trong vùng chạy double dblGocChay; //góc chạy của thread //hàm khởi tạo các thông số của thread public MyThread(Random rnd, int xMax, int yMax) { Xmax = xMax; Ymax = yMax; Pos.X = (int) (rnd.Next(0, Xmax)); Pos.Y = (int) (rnd.Next(0, Ymax)); dblGocChay = ChinhGocChay(rnd.Next(0, 360)); }

Page 115: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 6

//========================================================= //Hiệu chỉnh góc chạy của thread //₫ể tránh các trường hợp thread chạy thẳng ₫ứng hay ngang //========================================================= double ChinhGocChay(double dblGocChay) { double goc = dblGocChay; if (0<= goc && goc < 90) return 45; if (90 <= goc && goc < 180) return 135; if (180 <= goc && goc < 270) return 225; if (270 <= goc) return 315; return goc; } //========================================================= //Tính góc phản xạ mới khi thread ₫ụng thành ₫ứng (bên trái hay phải). //========================================================= double DoiGocChayX(double dblGocChay) { double goc; if (dblGocChay > 0 && dblGocChay < 180) goc = 180 - dblGocChay; else goc = 180 + 360 - dblGocChay; return ChinhGocChay(goc); } //========================================================= //Tính góc phản xạ mới khi thread ₫ụng thành ngang (trên hay dưới). //========================================================= double DoiGocChayY(double dblGocChay) { return ChinhGocChay(360 - dblGocChay); } //========================================================= //Hiệu chỉnh vị trí của thread //========================================================= public void HieuchinhVitri() { double tx, ty; int x, y; x = Pos.X; y = Pos.Y; if (x == 0 || x == Xmax - 1 || y == 0 || y == Ymax - 1) { //icon ₫ựng thành ngang hay dọc -> thay ₫ổi góc chạy if (x == 0 || x == Xmax - 1) { dblGocChay = DoiGocChayX(dblGocChay); } else if (y == 0 || y == Ymax - 1) dblGocChay = DoiGocChayY(dblGocChay); } //Hiệu chỉnh tọa ₫ộ x của thread tx = 2*Math.Cos(dblGocChay * PI / 180); x = x + (int)tx; if (x < 0) { x = 0; } else if (x >= Xmax) { x = Xmax - 1;

Page 116: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 7

} //Hiệu chỉnh tọa ₫ộ y của thread ty = 2*Math.Sin(dblGocChay * PI / 180); y = y + (int)ty; if (y < 0) { y = 0; } else if (y >= Ymax) { y = Ymax - 1; } //chỉnh góc chạy khi ₫ụng 1 trong 4 góc if (x == 0 && y == 0) //góc trên trái ChinhGocChay(dblGocChay + 45); else if (x == 0 && y == Ymax - 1) //góc dưới trái ChinhGocChay(dblGocChay + 45); else if (x == Xmax - 1 && y == 0) //góc trên phải ChinhGocChay(dblGocChay + 45); else if (x == Xmax - 1 && y == Ymax - 1) //góc dưới phải ChinhGocChay(dblGocChay + 45); //Lưu vị trí mới Pos.X = (int)x; Pos.Y = (int)y; } } }

12. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Hãy thử :

- gỏ từng phím từ A-Z ₫ể khởi chạy thread tương ứng.

- gỏ Ctrl-X ₫ể tạm dừng chạy thread X.

- gỏ Alt-X ₫ể chạy lại thread X.

- gỏ Ctrl-Alt-X ₫ể giảm ₫ộ ưu tiên cho thread X.

- gỏ Shift-X ₫ể tăng ₫ộ ưu tiên cho thread X.

- gỏ Ctrl-Shift-X ₫ể xóa thread X.

13. Khi một thread nào ₫ó bị tạm dừng, hãy quan sát icon miêu tả nó theo thời gian, có thể icon thread khác sẽ chạy ₫ến và phải chờ thread tạm dừng. Tương tự, có thể có nhiều thread ₫ang chạy nhưng phải chờ lẫn nhau nên chúng không thể chạy tiếp ₫ược. Đây là hiện tượng deadlock, rất nguy hiểm. Làm sao ₫ể giải quyết ?

Page 117: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 1

MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG Bài thực hành số 10.1 : Lập trình ₫ể thực hiện các lệnh truy vấn SQL

I. Mục tiêu :

Giúp SV làm quen với việc viết code dùng các ₫ối tượng ADO .Net phục vụ việc thực hiện các lệnh truy vấn SQL vào database trực tiếp trong chương trình.

II. Nội dung : Xây dựng chương trình nhỏ demo việc thực hiện các lệnh truy vấn SQL ₫ể tạo bảng

chứa các sản phẩm tồn kho từ 2 bảng có sẵn : bảng các sản phẩm nhập và bảng các sản phẩm xuất.

Sử dụng các ₫ối tượng ADO .Net trong namespace System.data.OleDb.

III. Chuẩn ₫ầu ra : Sinh viên nắm vững và viết thành thạo các ₫oạn code dùng các ₫ối tượng ADO .Net

phục vụ việc thực hiện các lệnh truy vấn SQL vào database trực tiếp trong chương trì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 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. TaoSPTon1), 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ị. Thêm lệnh using sau ₫ây vào ₫ầu file : using System.data.OleDb;

4. Viết code cho thân hàm Main như sau : static void Main(string[] args) { //₫ịnh nghĩa các biến ₫ối tượng cần dùng String ConnectionString; OleDbConnection cn; OleDbCommand cmd = new OleDbCommand(); //xây dựng chuỗi ₫ặc tả database cần truy xuất ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=c:\\MyDatabase.mdb;"; //tạo ₫ối tượng Connection ₫ến database & mở Connection cn = new OleDbConnection(ConnectionString); cn.Open(); //cấu hình cho ₫ối tượng Command cmd.Connection = cn; //thực hiện lệnh SQL xóa bảng SPTon nếu ₫ã có cmd.CommandText = "Drop Table SPTon"; try { cmd.ExecuteNonQuery(); } catch { } //thực hiện lệnh SQL tạo bảng sản phẩm tồn cmd.CommandText = "Create Table SPTon(MaSP Text, Soluong int)"; cmd.ExecuteNonQuery(); //thực hiện lệnh SQL tạo các sản phẩm tồn có MaSP tồn tại trong bảng SPNhap

Page 118: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 2

cmd.CommandText = "Insert into SPTon select SPNhap.MaSP, IIf(IsNull(SPNhap.Soluong), 0, SPNhap.Soluong)-IIf(IsNull(SPXuat.Soluong), 0, SPXuat.Soluong) as Soluong from SPXuat right join SPNhap on SPXuat.MaSP = SPNhap.MaSP"; cmd.ExecuteNonQuery(); //thực hiện lệnh SQL tạo bảng sản phẩm Tam cmd.CommandText = "Create Table Tam(MaSP Text, Soluong int)"; cmd.ExecuteNonQuery(); //thực hiện lệnh SQL tạo các sản phẩm tồn có MaSP tồn tại trong bảng SPXuat cmd.CommandText = "Insert into Tam select SPXuat.MaSP, IIf(IsNull(SPNhap.Soluong), 0, SPNhap.Soluong) -IIf(IsNull(SPXuat.Soluong), 0, SPXuat.Soluong) as Soluong from SPNhap right join SPXuat on SPXuat.MaSP = SPNhap.MaSP"; cmd.ExecuteNonQuery(); //Trộn 2 bảng kết quả lại thành bảng SPTon cmd.CommandText = "Insert into SPTon select MaSP, Soluong from Tam where Soluong < 0"; cmd.ExecuteNonQuery(); //Xóa bảng Tam cmd.CommandText = "Drop Table Tam"; cmd.ExecuteNonQuery(); }

5. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng.

6. Sau khi ứng dụng chạy xong, chạy ứng dụng Access, mở file database c:\MyDatabase.mdb, kiểm tra nội dung bảng SPTon ₫ể ₫ánh giá kết quả có ₫úng yêu cầu không.

Page 119: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 1

MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG Bài thực hành số 10.2 : Lập trình ₫ể thực hiện các lệnh truy vấn SQL

I. Mục tiêu :

Giúp SV làm quen với việc viết code dùng các ₫ối tượng ADO .Net phục vụ việc thực hiện các lệnh truy vấn SQL vào database trực tiếp trong chương trình.

II. Nội dung : Xây dựng chương trình nhỏ demo việc thực hiện các lệnh truy vấn SQL ₫ể tạo bảng

chứa các sản phẩm tồn kho từ 2 bảng có sẵn : bảng các sản phẩm nhập và bảng các sản phẩm xuất.

Sử dụng các ₫ối tượng ADO .Net trong namespace System.data.Odbc.

III. Chuẩn ₫ầu ra : Sinh viên nắm vững và viết thành thạo các ₫oạn code dùng các ₫ối tượng ADO .Net

phục vụ việc thực hiện các lệnh truy vấn SQL vào database trực tiếp trong chương trì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 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. TaoSPTon2), 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ị. Thêm lệnh using sau ₫ây vào ₫ầu file : using System.data.Odbc;

4. Viết code cho thân hàm Main như sau : static void Main(string[] args) { //₫ịnh nghĩa các biến ₫ối tượng cần dùng String ConnectionString; OdbcConnection cn; OdbcCommand cmd = new OdbcCommand(); //xây dựng chuỗi ₫ặc tả database cần truy xuất ConnectionString = "Driver={Microsoft Access Driver (*.mdb)}; DBQ=d:\\MyDatabase.mdb"; //tạo ₫ối tượng Connection ₫ến database & mở Connection cn = new OdbcConnection(ConnectionString); cn.Open(); //cấu hình cho ₫ối tượng Command cmd.Connection = cn; //thực hiện lệnh SQL xóa bảng SPTon nếu ₫ã có cmd.CommandText = "Drop Table SPTon"; try { cmd.ExecuteNonQuery(); } catch { } //thực hiện lệnh SQL tạo bảng sản phẩm tồn cmd.CommandText = "Create Table SPTon(MaSP Text, Soluong int)"; cmd.ExecuteNonQuery(); //thực hiện lệnh SQL tạo các sản phẩm tồn có MaSP tồn tại trong bảng SPNhap

Page 120: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 2

cmd.CommandText = "Insert into SPTon select SPNhap.MaSP, IIf(IsNull(SPNhap.Soluong), 0, SPNhap.Soluong)-IIf(IsNull(SPXuat.Soluong), 0, SPXuat.Soluong) as Soluong from SPXuat right join SPNhap on SPXuat.MaSP = SPNhap.MaSP"; cmd.ExecuteNonQuery(); //thực hiện lệnh SQL tạo bảng sản phẩm Tam cmd.CommandText = "Create Table Tam(MaSP Text, Soluong int)"; cmd.ExecuteNonQuery(); //thực hiện lệnh SQL tạo các sản phẩm tồn có MaSP tồn tại trong bảng SPXuat cmd.CommandText = "Insert into Tam select SPXuat.MaSP, IIf(IsNull(SPNhap.Soluong), 0, SPNhap.Soluong) -IIf(IsNull(SPXuat.Soluong), 0, SPXuat.Soluong) as Soluong from SPNhap right join SPXuat on SPXuat.MaSP = SPNhap.MaSP"; cmd.ExecuteNonQuery(); //Trộn 2 bảng kết quả lại thành bảng SPTon cmd.CommandText = "Insert into SPTon select MaSP, Soluong from Tam where Soluong < 0"; cmd.ExecuteNonQuery(); //Xóa bảng Tam cmd.CommandText = "Drop Table Tam"; cmd.ExecuteNonQuery(); }

5. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng.

6. Sau khi ứng dụng chạy xong, chạy ứng dụng Access, mở file database c:\MyDatabase.mdb, kiểm tra nội dung bảng SPTon ₫ể ₫ánh giá kết quả có ₫úng yêu cầu không.

7. Duyệt tìm và so sánh các khác biệt giữa 2 ₫oạn code của hàm Main() trong 2 bài thực hành 10.1 và 10.2, cố gắng lý giải các khác biệt này.

Page 121: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 1

MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG Bài thực hành số 10.3 : Lập trình dùng Databinding ₫ể khỏi viết code truy xuất

database I. Mục tiêu :

Giúp SV làm quen với việc xây dựng ứng dụng dùng kỹ thuật databinding của VC# ₫ể truy xuất database mà không cần viết code truy xuất database, nhờ ₫ó hạn chế tối ₫a công sức, thời gian lập trình ₫ồng thời hạn chế tối ₫a những rủi ro, lỗi của chương trình.

II. Nội dung : Xây dựng chương trình nhỏ demo việc thực hiện việc xem/hiệu chỉnh nội dung các

record dữ liệu trong 1 bảng dữ liệu của database dùng kỹ thuật databinding ₫ể không cần viết code.

III. Chuẩn ₫ầu ra : Sinh viên nắm vững và xây dựng thành thạo các form truy xuất database dùng kỹ

thuật databinding mà không cần viết code.

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 "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. DBAccess), 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. Duyệt tìm phần tử DataGridView (trong nhóm Data), chọn nó, dời chuột vào trong Form và vẽ nó với kích thước mong muốn (chiếm hết form). Hiệu chỉnh thuộc tính (Name) = grdCustomers.

5. Ngay sau khi vẽ xong DataGridView, máy sẽ hiển thị cửa sổ "DataGridView Tasks". Nếu sơ xuất làm mất nó thì bạn hãy click chuột vào button nhỏ ở phía trên phải DataGridView ₫ể hiển thị lại. Click chuột vào icon chỉ xuống trong listbox "Choose data source" ₫ể hiển thị cửa sổ hỗ trợ. Click chuột vào mục "Add Project Data Source", ₫ể hiển thị cửa sổ "Choose a Data Source type". chọn icon Database rồi click button Next ₫ể hiển thị cửa sổ "Choose Your Database Connection".

6. Click button New Connection ₫ể hiển thị cửa sổ "Add Connection", xác ₫ịnh Provider truy xuất database, thí dụ như Provider "Microsoft Access Database File (OLE DB)" ₫ể truy xuất file Access, provider "Microsoft SQL Server" ₫ể truy xuất database do SQL Server quản lý...

7. Xác ₫ịnh database cần truy xuất trong "Database file name" rồi click button OK ₫ể quay về cửa sổ trước. Click button Next ₫ể hiển thị cửa sổ "Choose Your Database Object".

8. Mở rộng mục Tables ₫ể hiển thị ₫ầy ₫ủ các tên bảng dữ liệu có trong database, duyệt tìm và ₫ánh dấu chọn vào bảng Customers rồi click button Finish ₫ể hoàn tất việc khai báo trực quan.

Page 122: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 2

9. Bây giờ chương trình ₫ã ₫ược viết xong. hãy chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Cửa sổ ứng dụng sẽ hiển thị ₫ối tượng DataGridView, ₫ối tượng này hiển thị ₫ầy ₫ủ danh sách thông tin các khách hàng trong bảng Customers, người dùng có thể "scroll" lên/xuống hay trái/phải ₫ể xem thông tin thích hợp.

Page 123: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 1

MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG Bài thực hành số 10.4 : Lập trình dùng Databinding ₫ể chỉ viết code khởi tạo

I. Mục tiêu :

Giúp SV làm quen với việc xây dựng ứng dụng dùng kỹ thuật databinding của VC# ₫ể truy xuất database mà không cần viết code truy xuất database, chỉ cần viết code khởi tạo nhỏ, nhờ ₫ó hạn chế tối ₫a công sức, thời gian lập trình ₫ồng thời hạn chế tối ₫a những rủi ro, lỗi của chương trình.

II. Nội dung : Xây dựng chương trình nhỏ cho phép xem thông tin chi tiết về tình hình mua hàng

của khách hàng dùng kỹ thuật databinding ₫ể chỉ cần viết code khởi tạo nhỏ, chứ không cần viết code truy xuất database chi tiết.

Form có giao diện như hình vẽ dưới ₫ây.

III. Chuẩn ₫ầu ra : Sinh viên nắm vững và xây dựng thành thạo các form truy xuất database dùng kỹ

thuật databinding mà không cần viết code truy xuất database, chỉ cần viết code khởi tạo nhỏ.

IV. Qui trình :

Bài thực hành này sẽ viết chương trình có form giao diện sử dụng như sau :

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. DBAccess2), click button OK ₫ể tạo Project theo các thông số ₫ã khai báo.

Page 124: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

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. Thay ₫ổi kích thước của form lớn ra theo yêu cầu.

5. Duyệt tìm phần tử Button (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 = "Tới" và thuộc tính (Name) = btnToi.

6. Lặp lại bước 5 ₫ể vẽ Button thứ 2 với thuộc tính Text = "Lùi" và thuộc tính (Name) = btnLui.

7. 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 = "Tên khách hàng :".

8. Lặp lại bước 7 ₫ể vẽ 3 Label còn lại với thuộc tính Text tuần tự là "Địa chỉ liên hệ :", "Số Phone : ", "Số Fax :"

9. Duyệt tìm phần tử ComboBox (trong nhóm Common Controls), chọn nó, dời chuột về bên phải Label "Tên khách hàng :" và vẽ nó với kích thước mong muốn. Hiệu chỉnh thuộc tính (Name) = cbCust.

10. 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 "Địa chỉ liên hệ :" và vẽ nó với kích thước mong muốn. Hiệu chỉnh thuộc tính (Name)= txtContact.

11. Lặp lại bước 10 ₫ể vẽ 2 TextBox còn lại với thuộc tính (Name) tuần tự là txtPhoneNo, txtFaxNo.

12. Duyệt tìm phần tử GroupBox (trong nhóm Common Controls), chọn nó, dời chuột về vị trí ngay dưới Label "Số Fax :" và vẽ nó với kích thước mong muốn. Hiệu chỉnh thuộc tính Text = "Danh sách các ₫ơn ₫ặt hàng của khách hàng ₫ang ₫ược chọn :".

13. Duyệt tìm phần tử DataGridView (trong nhóm Data), chọn nó, dời chuột vào trong GroupBox vừa vẽ và vẽ nó với kích thước mong muốn. Hiệu chỉnh thuộc tính (Name)= grdOrders.

14. Lặp lại bước 12 và 13 ₫ể vẽ GroupBox có thuộc tính Text = "Chi tiết của ₫ơn ₫ặt hàng ₫ang ₫ược chọn :" và DataGridView bên trong có thuộc tính (Name) = grdOrderDetails.

15. Tạo hàm xử lý sự kiện cho 2 button btnToi và btnLui rồi viết code cho chúng như sau : //hàm xử lý Click chuột trên button "Tới" private void btnToi_Click(object sender, EventArgs e) { CurrencyManager cm = (CurrencyManager)this.BindingContext [dsView, "Customers"]; //nếu không phải khách hàng cuối thì tiến tới 1 khách hàng if (cm.Position < cm.Count - 1) cm.Position++; } //hàm xử lý Click chuột trên button"Lùi" private void btnLui_Click(object sender, EventArgs e) { //nếu không phải khách hàng ₫ầu tiên thì lùi 1 khách hàng if (this.BindingContext[dsView, "Customers"].Position > 0)

Page 125: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 3

this.BindingContext[dsView, "Customers"].Position--; }

16. Thêm lệnh using sau vào ₫ầu file ₫ặc tả class Form :

using System.Data.OleDb;

17. Thêm các lệnh ₫ịnh nghĩa các thuộc tính dữ liệu cần dùng sau ₫ây vào ở vị trí ₫ầu class ₫ặc tả Form : //₫ịnh nghĩa các thuộc tính dữ liệu cần dùng private String ConnectionString; private DataViewManager dsView; private DataSet ds; private OleDbConnection cn;

18. Hiệu chỉnh lại hàm constructor của Form ₫ể có nội dung như sau : public Form1() { InitializeComponent(); //xây dựng chuỗi ₫ặc tả database cần truy xuất ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source = c:\\NorthWind.mdb;"; //tạo ₫ối tượng Connection ₫ến database cn = new OleDbConnection(ConnectionString); //tạo ₫ối tượng DataSet ds = new DataSet("CustOrders"); //tạo ₫ối tượng DataApdater quản lý danh sách các khách hàng OleDbDataAdapter da1 = new OleDbDataAdapter ("SELECT * FROM Customers", cn); //ánh xạ Tablename "Table" tới bảng dữ liệu "Customers" da1.TableMappings.Add("Table","Customers"); //chứa bảng Customers vào Dataset da1.Fill(ds); //tạo ₫ối tượng DataApdater quản lý danh sách các ₫ơn ₫ặt hàng OleDbDataAdapter da2 = new OleDbDataAdapter ("SELECT * FROM Orders", cn); //ánh xạ Tablename "Table" tới bảng dữ liệu "Orders" da2.TableMappings.Add("Table","Orders"); // chứa bảng Orders vào Dataset da2.Fill(ds); //tạo ₫ối tượng DataApdater quản lý danh sách các mặt hàng OleDbDataAdapter da3 = new OleDbDataAdapter ("SELECT * FROM [Order Details]", cn); //ánh xạ Tablename "Table" tới bảng dữ liệu "Orders" da3.TableMappings.Add("Table","OrderDetails"); // chứa bảng [Orders Details] vào Dataset da3.Fill(ds); //thiết lập quan hệ "RelCustOrd" giữa bảng Customers và Orders System.Data.DataRelation relCustOrd; System.Data.DataColumn colMaster1; System.Data.DataColumn colDetail1; colMaster1 = ds.Tables["Customers"].Columns["CustomerID"]; colDetail1 = ds.Tables["Orders"].Columns["CustomerID"];

Page 126: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 4

relCustOrd = new System.Data.DataRelation ("RelCustOrd",colMaster1,colDetail1); //"add" quan hệ vừa tạo vào dataSet ds.Relations.Add(relCustOrd); //thiết lập quan hệ "relOrdDet" giữa bảng Orders & [Order Details] System.Data.DataRelation relOrdDet; System.Data.DataColumn colMaster2; System.Data.DataColumn colDetail2; colMaster2 = ds.Tables["Orders"].Columns["OrderID"]; colDetail2 = ds.Tables["OrderDetails"].Columns["OrderID"]; relOrdDet = new DataRelation("RelOrdDet",colMaster2,colDetail2); //"add" quan hệ vừa tạo vào dataSet ds.Relations.Add(relOrdDet); //Xác ₫ịnh DataViewManager của DataSet. dsView = ds.DefaultViewManager; //thiết lập Databinding giữa database với 2 DataGridView grdOrders.DataSource = dsView; grdOrders.DataMember = "Customers.RelCustOrd"; grdOrderDetails.DataSource = dsView; grdOrderDetails.DataMember = "Customers.RelCustOrd.RelOrdDet"; //thiết lập Databinding giữa database với ComboBox cbCust.DataSource = dsView; cbCust.DisplayMember = "Customers.CompanyName"; cbCust.ValueMember = "Customers.CustomerID"; //thiết lập Databinding giữa database với 3 Textbox txtContact.DataBindings.Add("Text",dsView,"Customers.ContactName"); txtPhoneNo.DataBindings.Add("Text",dsView,"Customers.Phone"); txtFaxNo.DataBindings.Add("Text",dsView,"Customers.Fax"); }

19. Chọn menu Debug.Start Debugging ₫ể dịch và chạy ứng dụng. Lúc ₫ầu, form sẽ hiển thị thông tin về khách hàng ₫ầu tiên trong bảng, khi bạn click vào button "Tới" hay "Lùi", thông tin khách hàng tương ứng sẽ tự ₫ược hiển thị. Bạn cũng có thể chọn 1 khách hàng tùy ý trong ComboBox "Tên khách hàng :" ₫ể chương trình tự hiển thị thông tin chi tiết về khách hàng ₫ó.

20. Tóm lại Databinding trong VC# giúp ta giảm nhẹ rất nhiều công sức viết chương trình truy xuất database : chúng ta chỉ viết ₫oạn code thiết lập databinding giữa các ₫ối tượng giao diện với dữ liệu tương ứng trong database chứ chúng ta không cần viết ₫oạn code cập nhật nội dung của các phần tử giao diện theo sự biến ₫ộng của database, chúng ta cũng không cần viết code cập nhật database theo nội dung mà người dùng thay ₫ổi trên các ₫ối tượng giao diện.

Page 127: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 1

MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG Bài thực hành số 11.1 : Viết phần mềm kích hoạt/dừng process

I. Mục tiêu :

Giúp SV làm quen với việc dùng class Process của namespace System.Diagnostics ₫ể quản lý process.

II. Nội dung : Xây dựng chương trình nhỏ cho phép người dùng chọn file khả thi cần chạy, kích hoạt

chạy nó và dừng/xóa nó khi cần thiết.

III. Chuẩn ₫ầu ra : Sinh viên nắm vững và sử dụng thành thạo class Process ₫ể quản lý process.

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 "Windows Form 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. ProcessManager), 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ử Label (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 Label 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 = "Nhập ₫ường dẫn file khả thi cần chạy :".

6. Duyệt tìm phần tử TextBox (trong nhóm Common Controls), chọn nó, dời chuột về phía dưới Label vừa vẽ và vẽ TextBox với kích thước mong muốn. Xem cửa sổ thuộc tính của TextBox vừa vẽ, duyệt tìm và hiệu chỉnh thuộc tính (Name) = txtPath.

7. Duyệt tìm phần tử Button (trong nhóm Common Controls), chọn nó, dời chuột về bên phải TextBox vừa vẽ và Button với kích thước mong muốn. Xem cửa sổ thuộc tính của Button vừa vẽ, duyệt tìm và hiệu chỉnh thuộc tính Text = "Browse…", duyệt tìm và thay ₫ổi thuộc tính (Name) = btnBrowse.

8. Lặp lại bước 7 ₫ể vẽ thêm button ngay dưới TextBox với thuộc tính Text = "Start", (Name) = btnStart.

9. Lặp lại bước 8 ₫ể vẽ thêm button ngay bên phải button Start với thuộc tính Text = "Stop", (Name) = btnStop.

Sau khi thiết kế xong, Form có dạng sau :

Page 128: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 2

10. Dời chuột về button btnBrowse, ấ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 btnBrowse, 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, viết thân cho hàm này như sau :

private void btnBrowse_Click(object sender, EventArgs e) { //tạo form duyệt chọn file khả thi cần chạy OpenFileDialog dlg = new OpenFileDialog(); //hiển thị form duyệt chọn file khả thi cần chạy 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ì ghi nhận tên file if (ret == DialogResult.OK) txtPath.Text = dlg.FileName; }

11. Dời chuột về button btnStart, ấ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ị 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 btnStart_Click(object sender, EventArgs e) { //tạo mới ₫ối tượng quản lý Process. myProcess = new Process(); try { //thiết lập ₫ường dẫn file cần chạy myProcess.StartInfo.FileName = txtPath.Text; //thiết lập chế ₫ộ không dùng Shell quản lý process myProcess.StartInfo.UseShellExecute = false; //thiết lập chế ₫ộ tạo cửa sổ riêng cho process mới myProcess.StartInfo.CreateNoWindow = true; //kích hoạt process myProcess.Start(); } catch (Exception ex) { MessageBox.Show(ex.Message); }

Page 129: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 3

}

12. Dời chuột về button btnStop, ấ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ị 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 btnStop_Click(object sender, EventArgs e) { myProcess.Kill(); }

13. Dời chuột về ₫ầu class Form1 rồi thêm lệnh ₫ịnh nghĩa thuộc tính cần dùng như sau : Process myProcess;

14. Dời chuột về ₫ầu file mã nguồn Form1 rồi thêm lệnh using như sau : using System.Diagnostics;

15. 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 Browse, cửa sổ duyệt chọn file sẽ hiển thị, hãy duyệt và chọn 1 file khả thi cần chạy. Khi cần kích thoạt chạy thật sự, hãy click chuột vào button Start. Khi cần xóa chương trình ₫ang chạy thì click chuột vào button Stop.

Page 130: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 1

MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG Bài thực hành số 11.2 : Viết phần mềm demo tính hiệu quả của lập trình multi-

thread I. Mục tiêu :

Giúp SV làm quen với việc dùng class Thread của namespace System.Threadings ₫ể quản lý thread.

Giúp SV thấy ₫ược tính hiệu quả của lập trình multi-thread so với lập trình tuần tự.

II. Nội dung : Xây dựng chương trình nhỏ cho phép người dùng chọn số thread cần dùng ₫ể tính

tích của 2 ma trận có kích thước ₫ủ lớn. Sau khi tính xong, chương trình sẽ hiển thị thời gian chạy ₫ể người dùng biết ₫ộ hiệu quả khi dùng số thread khác nhau.

III. Chuẩn ₫ầu ra : Sinh viên nắm vững và sử dụng thành thạo class Thread ₫ể quản lý thread.

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 "Windows Form 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. ThreadDemo1), 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ử Label (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 Label 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 = "Nhập số thread cần chạy :".

6. Duyệt tìm phần tử TextBox (trong nhóm Common Controls), chọn nó, dời chuột về ngay phải Label vừa vẽ và vẽ TextBox với kích thước ₫ủ ₫ể nhập số nguyên nhỏ. Xem cửa sổ thuộc tính của TextBox vừa vẽ, duyệt tìm và hiệu chỉnh thuộc tính (Name) = txtThreads.

7. Duyệt tìm phần tử Button (trong nhóm Common Controls), chọn nó, dời chuột về bên phải TextBox vừa vẽ và vẽ Button với kích thước mong muốn. Xem cửa sổ thuộc tính của Button vừa vẽ, duyệt tìm và hiệu chỉnh thuộc tính Text = "Ưu tiên thấp", duyệt tìm và thay ₫ổi thuộc tính (Name) = btnCham.

8. Lặp lại bước 7 ₫ể vẽ thêm button ngay bên phải button vừa vẽ với thuộc tính Text = "Ưu tiên cao", (Name) = btnNhanh.

9. Lặp lại bước 8 ₫ể vẽ thêm button ngay bên phải button btnNhanh với thuộc tính Text = "Tính tích 2 ma trận", (Name) = btnStart.

10. Duyệt tìm phần tử ListBox (trong nhóm Common Controls), chọn nó, dời chuột về bên dưới Label và vẽ ListBox với kích thước mong muốn. Xem cửa sổ thuộc tính của ListBox vừa vẽ, duyệt tìm và hiệu chỉnh thuộc tính (Name) = lbKetqua.

Page 131: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 2

Sau khi thiết kế xong, Form có dạng sau :

11. Dời chuột về button btnCham, ấ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 btnCham, 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, viết thân cho hàm này như sau :

private void btnCham_Click(object sender, EventArgs e) { //thiết lập chế ₫ộ quyền ưu tiên realtime cho chương trình myPrio = ProcessPriorityClass.BelowNormal; }

11. Dời chuột về button btnNhanh, ấ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ị 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 btnNhanh_Click(object sender, EventArgs e) { //thiết lập chế ₫ộ quyền ưu tiên realtime cho chương trình myPrio = ProcessPriorityClass.RealTime; }

12. Dời chuột về button btnStart, ấ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ị 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 btnStart_Click(object sender, EventArgs e) { //xác ₫ịnh ₫ối tượng quản lý process hiện hành

MyProc = Process.GetCurrentProcess(); //thay ₫ổi quyền ưu tiên theo yêu cầu người dùng MyProc.PriorityClass = myPrio; //xác ₫ịnh số thread tham gia tính tích 2 ma trận int cnt = Int32.Parse(txtThreads.Text); int i;

Page 132: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 3

//ghi nhận thời ₫iểm bắt ₫ầu tính tích DateTime t1 = DateTime.Now; if (cnt == 1) { //dùng thuật giải tuần tự TinhTich(new Params(null, 0, N, 0)); } else //dùng thuật giải song song gồm cnt-1 thread con và 1 thread chính có sẵn { Thread t; for (i = 0; i < cnt-1; i++) {//lặp tạo và chạy từng thread con stateLst[i] = 0; //ghi nhận thread i chưa chạy xong

//tạo thread mới ₫ể chạy hàm TinhTich t = new Thread(new ParameterizedThreadStart(TinhTich));

//thiết lập quyền ưu tiên cho thread i t.Priority = tPrio[i % 5];

//hiển thị ₫ộ ưu tiên của thread i lbKetqua.Items.Add(String.Format("Thread {0:d} co do uu tien = {1:d}", i, t.Priority.ToString()));

//kích hoạt thread i chạy và truyền các tham số cần thiết cho nó t.Start (new Params(t, i*N/cnt, (i+1)*N/cnt,i)); }

//bản thân thread cha cũng tính N/cnt hàng cuối của ma trận tích TinhTich(new Params(null, (cnt-1)*N/cnt, N, cnt-1));

//chờ ₫ợi các thread con hoàn thành for (i = 0; i < cnt-1; i++) while (stateLst[i] == 0); //cho } //ghi nhận thời ₫iểm kết thúc tính tích DateTime t2 = DateTime.Now; System.TimeSpan diff; //hiển thị ₫ộ ưu tiên hiện hành của chương trình lbKetqua.Items.Add("Ung dung da chay voi quyen " + myPrio.ToString()); //hiển thị thời gian tính của từng thread con for (i = 0; i < cnt - 1; i++) { diff = dateLst[i]; lbKetqua.Items.Add(String.Format("Thread {0:d} chay ton {1:d2} phut {2:d2} giay {3:d3} ms", i, diff.Minutes, diff.Seconds, diff.Milliseconds)); } diff = t2.Subtract(t1); //hiển thị thời gian tổng cộng ₫ể tính tích lbKetqua.Items.Add(String.Format("{0:d} threads ==> Thoi gian chay la {1:d2} phut {2:d2} giay {3:d3} ms", cnt, diff.Minutes, diff.Seconds, diff.Milliseconds)); } 

13. Dời chuột về ₫ầu class Form1 rồi thêm lệnh ₫ịnh nghĩa các kiểu dữ liệu, các thuộc tính, các hàm dịch vụ cần dùng như sau :

class Params //₫ịnh nghĩa class ₫ối tượng chứa các tham số cần truyền cho thread con { public Thread t; //₫ối tượng quản lý thread tương ứng public int sr; //hàng bắt ₫ầu tính public int er; //hàng kết thúc tính +1

Page 133: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 4

public int id; //chỉ số thread trong danh sách quản lý public Params(Thread t, int s, int e, int i) { this.t = t; sr = s; er = e; id = i; } }; //₫ịnh nghĩa 3 biến ma trận double[,] A; double[,] B; double[,] C; //₫ịnh nghĩa biến chứa số hàng/cột của ma trận int N; //₫ịnh nghĩa danh sách trạng thái thi hành của các thread con int[] stateLst = new int [20]; //₫ịnh nghĩa danh sách thời gian thi hành của các thread con System.TimeSpan[] dateLst = new System.TimeSpan[20]; //₫ịnh nghĩa biến miêu tả quyền ưu tiên của chương trình ProcessPriorityClass myPrio = ProcessPriorityClass.Normal; Process MyProc; //₫ịnh nghĩa danh sách các quyền ưu tiên cho các thread ThreadPriority[] tPrio = { ThreadPriority.Lowest, ThreadPriority.BelowNormal, ThreadPriority.Normal, ThreadPriority.AboveNormal, ThreadPriority.Highest}; //₫ịnh nghĩa hàm các hàng ma trận tích theo yêu cầu trong tham số void TinhTich (object obj) { DateTime t1 = DateTime.Now; Params p = (Params)obj; int h, c, k; for (h = p.sr; h < p.er; h++) for (c = 0; c < N; c++) { double s = 0; for (k = 0; k < N; k++) s = s + A[h, k] * B[k, c]; C[h, c] = s; } //ghi nhận ₫ã hoàn thành nhiệm vụ stateLst[p.id] = 1; //ghi nhận thời gian tính dateLst[p.id] = DateTime.Now.Subtract(t1); }

14. Tìm hàm khởi tạo Form1 rồi thêm các lệnh khởi tạo các ma trận A và B như sau : public Form1() { InitializeComponent(); //thêm vào các lệnh khởi tạo sau ₫ây

Page 134: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 5

lbKetqua.Items.Clear(); //khởi tạo các ma trận A, B, C N = 1000; A = new double[N,N]; B = new double[N,N]; C = new double[N,N]; int h, c; for (h = 0 ; h < N; h++) for (c = 0; c < N; c++) A[h,c] = B[h,c] = c; }  

15. Dời chuột về ₫ầu file mã nguồn Form1 rồi thêm lệnh using như sau : using System.Diagnostics; using System.Threading;

16. Chọn menu Debug.Start Debugging ₫ể dịch và chạy thử ứng dụng.

17. Khi Form chương trình hiển thị, hãy nhập số 1 vào Textbox số thread cần chạy, click chuột vào button "Tính tích 2 ma trận", chờ xem thời gian chạy tốn bao lâu rồi ghi nhận.

18. Lặp lại bước 17 với số thread tăng dần, rồi ghi nhận lại thời gian chạy của từng trường hợp.

19. So sánh thời gian chạy ₫ể ₫ánh giá ₫ộ hiệu quả của multi-thread vời số lượng thread khác nhau.

Page 135: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 1

MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG Bài thực hành số 11.3 : Viết phần mềm demo sự tương tranh giữa các thread

I. Mục tiêu :

Giúp SV làm quen với việc dùng class Thread của namespace System.Threadings ₫ể quản lý thread.

Giúp SV thấy ₫ược vấn ₫ề tương tranh giữa các thread khi chúng cùng truy xuất tài nguyên dùng chung.

II. Nội dung : Xây dựng chương trình cho phép người dùng thực hiện quản lý các thread có tên là A-

Z như kích hoạt chạy, tạm dừng, chạy lại, tăng/giảm quyền ưu tiền, dừng và xóa thread... bằng các thao tác ấn phím. Mỗi thread khi chạy sẽ hiển thị icon miêu tả mình lên form, icon sẽ chạy theo 1 phương xác ₫ịnh và khi ₫ụng thành form thì dội lại theo nguyên lý vật lý.

Quan sát cảnh icon của thread này ₫è mất icon của thread khác, ₫ây là vấn ₫ề tương tranh giữa các thread trong việc truy xuất các cell hiển thị trên form.

III. Chuẩn ₫ầu ra : Sinh viên nắm vững và sử dụng thành thạo class Thread ₫ể quản lý thread. Sinh viên nắm vững vấn ₫ề tương tranh giữa các thread khi chúng truy xuất tài

nguyên dùng chung.

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 "Windows Form 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. ThreadDemo2), 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ế. Bài thực hành này không thiết kế form mà chỉ viết code cho chương trình vì form ₫ược hiệu chỉnh kích thước ₫ộng và nội dung hiển thị trong form cũng ₫ược hiểu chỉnh ₫ộng bởi các thread ₫ang chạy.

4. 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 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. 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 Form1_Load(object sender, EventArgs e) { //tạo ₫ối tượng quản lý việc truy xuất tài nguyên trong project System.Reflection.Assembly myAssembly = System.Reflection.Assembly.GetExecutingAssembly(); //Lặp thiết lập trạng thái ban ₫ầu cho 26 thread từ A-Z for (i = 0; i < 26; i++) { threadLst[i] = new MyThread(rnd, xMax, yMax); threadLst[i].stop = threadLst[i].suspend = threadLst[i].start = false; char c = (char)(i + 65); //₫ọc bitmap miêu tả thread c từ file

Page 136: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 2

myStream = myAssembly.GetManifestResourceStream("ThreadDemo2.Resources.Image" + c.ToString() + ".bmp"); threadLst[i].Pic = new Bitmap(myStream); threadLst[i].Xmax = 25; threadLst[i].Ymax = 20; } ClientSize = new Size(25 * 30, 20 * 30); this.Location = new Point(0, 0); this.BackColor = Color.Black; }

5. Tạo hàm xử lý sự kiện KeyDown cho Form. 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 :

//hàm xử lý gỏ phím của user ₫ể quản lý thread private void Form1_KeyDown(object sender, KeyEventArgs e) { //xác ₫ịnh mã phím ấn, nếu không phải từ A-Z thì phớt lờ int newch = e.KeyValue; if (newch < 0x41 || newch > 0x5a) return; //xác ₫ịnh chức năng mà user muốn và thực hiện if (e.Control && e.Shift) { //kill thread // dừng Thread threadLst[newch - 65].start = false; } else if (e.Control) { //giảm ₫ộ ưu tiên tối thiểu threadLst[newch - 65].t.Priority = ThreadPriority.Lowest; MessageBox.Show(threadLst[newch - 65].t.Priority.ToString()); } else if (e.Control && e.Alt) { //tạm dừng thread if (threadLst[newch - 65].start && !threadLst[newch - 65].suspend) { threadLst[newch - 65].t.Suspend(); threadLst[newch - 65].suspend = true; } } else if (e.Alt) { //cho thread chạy lại if (threadLst[newch - 65].start && threadLst[newch - 65].suspend) { threadLst[newch - 65].t.Resume(); threadLst[newch - 65].suspend = false; } } else if (e.Shift) { //tăng ₫ộ ưu tiên tối ₫a threadLst[newch - 65].t.Priority = ThreadPriority.Highest; MessageBox.Show(threadLst[newch - 65].t.Priority.ToString()); }

Page 137: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 3

else { //tạo mới thread và bắt ₫ầu chạy if (!threadLst[newch - 65].start) { threadLst[newch - 65].start = true; threadLst[newch - 65].suspend = false; threadLst[newch - 65].t = new Thread(new ParameterizedThreadStart(Running)); if (newch == 65) threadLst[newch - 65].t.Priority = ThreadPriority.Highest; else threadLst[newch - 65].t.Priority = ThreadPriority.Lowest; threadLst[newch - 65].t.Start(threadLst[newch - 65]); } } } 

6. Tạo hàm xử lý sự kiện FormClosed cho Form. 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 Form1_FormClosed(object sender, FormClosedEventArgs e) { int i; //lặp kiểm tra xem có thread con nào còn chạy không, nếu có thì xóa nó for (i = 0; i < 26; i++) if (threadLst[i].start) { threadLst[i].start = false; while (!threadLst[i].stop) ; } }

7. Dời chuột về ₫ầu class Form1 rồi thêm lệnh ₫ịnh nghĩa các kiểu dữ liệu, các thuộc tính, các hàm dịch vụ cần dùng như sau :

//₫ịnh nghĩa các thuộc tính cần dùng Stream myStream; MyThread[] threadLst; const int xCell = 30; const int yCell = 30; const int xMax = 25; const int yMax = 20; //tạo ₫ối tượng sinh số ngẫu nhiên public Random rnd = new Random(); //₫ịnh nghĩa hàm giả lập hành vi của thread void MySleep(long count) { long i, j, k = 0; for (i = 0; i < count; i++) for (j = 0; j < 64000; j++) k = k + 1; } //₫ịnh nghĩa hàm mà mỗi thread sẽ chạy void Running(object obj) { //ép kiểu tham số về MyThread theo yêu cầu xử lý

Page 138: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 4

MyThread p = (MyThread)obj; //tạo ₫ối tượng vẽ Graphics g = this.CreateGraphics(); //tạo chổi màu ₫en ₫ể xóa cell cũ Brush brush = new SolidBrush(Color.FromArgb(0, 0, 0)); int x1, y1; int x2, y2; int x, y; bool kq=true; try { while (p.start) { //lặp trong khi chưa có yêu cầu kết thúc //xác ₫ịnh tọa ₫ộ hiện hành của thread x1 = p.Pos.X; y1 = p.Pos.Y; //hiển thị logo của thread ở (x1,y1) g.DrawImage(p.Pic, xCell * x1, yCell * y1); Color c = p.Pic.GetPixel(1,1); int yR, yG, yB; if (c.R > 128) yR = 0; else yR = 255; if (c.G > 128) yG = 0; else yG = 255; if (c.B > 128) yB = 0; else yB = 255; Pen pen = new Pen(Color.FromArgb(yR, yG, yB), 2); if (p.tx >= 0 && p.ty >= 0) { //hiện mũi tên góc dưới phải x = xCell * x1 + xCell - 2; y = yCell * y1 + yCell - 2; g.DrawLine(pen, x, y, x - 10, y); g.DrawLine(pen, x, y, x, y-10); } else if (p.tx >= 0 && p.ty < 0) { //hiện mũi tên góc trên phải x = xCell * x1 + xCell - 2; y = yCell * y1 + 2; g.DrawLine(pen, x, y, x - 10, y); g.DrawLine(pen, x, y, x, y + 10); } else if (p.tx < 0 && p.ty >= 0) { //hiện mũi tên góc dưới trái x = xCell * x1 + 2; y = yCell * y1 + yCell - 2; g.DrawLine(pen, x, y, x + 10, y); g.DrawLine(pen, x, y, x, y - 10); } else {//hiện mũi tên góc trên trái x = xCell * x1 + 2; y = yCell * y1 + 2; g.DrawLine(pen, x, y, x + 10, y); g.DrawLine(pen, x, y, x, y + 10); } //giả lập thực hiện công việc của thread tốn 500ms MySleep(500); //xác ₫ịnh vị trí mới của thread p.HieuchinhVitri(); x2 = p.Pos.X; y2 = p.Pos.Y; // Xóa vị trí cũ

Page 139: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 5

g.FillRectangle(brush, xCell * x1, yCell * y1, xCell, yCell); if (kq == false && p.start == false) { //xoa thread // dừng Thread p.t.Abort(); p.stop = true; return; } } } catch (Exception e) { p.t.Abort(); } //dọn dẹp thread trước khi ngừng x1 = p.Pos.X; y1 = p.Pos.Y; g.FillRectangle(brush, xCell * x1, yCell * y1, xCell, yCell); // dừng Thread p.stop = true; p.t.Abort(); } 

8. Dời chuột về ₫ầu file mã nguồn Form1 rồi thêm lệnh using như sau : using System.Threading; using System.Resources; using System.IO; 9. Ấn phải chuột vào phần tử gốc của cây Project trong cửa sổ Solution Explorer, chọn

option Add.Class, ₫ặt tên là MyThread.cs ₫ể tạo ra file ₫ặc tả class chứa các tham số phục vụ cho từng thread con chạy. Khi cửa sổ hiển thị mã nguồn của class MyThread hiển thị, viết code cho class này như sau :

class MyThread { const double PI = 3.1416; public Thread t; //tham khảo ₫ến thread hiện hành public Boolean start; //trạng thái Start của thread public Boolean stop; //trạng thái Start của thread public Boolean suspend; //trạng thái Suspend của thread public Boolean WaitOne = false; //trạng thái chờ truy xuất cell public Bitmap Pic; //icon miêu tả thread internal int Xmax; //₫ộ rộng vùng chạy của thread internal int Ymax; //₫ộ cao vùng chạy của thread public Point Pos; //vị trí của thread trong vùng chạy double dblGocChay; //góc chạy của thread internal double tx, ty; //bước tăng theo x và y //hàm khởi tạo các thông số của thread public MyThread(Random rnd, int xMax, int yMax) { Xmax = xMax; Ymax = yMax; Pos.X = (int)(rnd.Next(0, Xmax)); Pos.Y = (int)(rnd.Next(0, Ymax)); dblGocChay = ChinhGocChay(rnd.Next(0, 360)); } //========================================================= //Hiệu chỉnh góc chạy của thread

Page 140: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 6

//₫ể tránh các trường hợp thread chạy thẳng ₫ứng hay ngang //========================================================= double ChinhGocChay(double dblGocChay) { double goc = dblGocChay; if (0 <= goc && goc < 90) return 45; if (90 <= goc && goc < 180) return 135; if (180 <= goc && goc < 270) return 225; if (270 <= goc) return 315; return goc; } //========================================================= //Tính góc phản xạ mới khi thread ₫ụng thành ₫ứng (bên trái hay phải). //========================================================= double DoiGocChayX(double dblGocChay) { double goc; if (dblGocChay > 0 && dblGocChay < 180) goc = 180 - dblGocChay; else goc = 180 + 360 - dblGocChay; return ChinhGocChay(goc); } //========================================================= //Tính góc phản xạ mới khi thread ₫ụng thành ngang (trên hay dưới). //========================================================= double DoiGocChayY(double dblGocChay) { return ChinhGocChay(360 - dblGocChay); } //========================================================= //Hiệu chỉnh vị trí của thread //========================================================= public void HieuchinhVitri() { int x, y; x = Pos.X; y = Pos.Y; if (x == 0 || x == Xmax - 1 || y == 0 || y == Ymax - 1) { //icon ₫ụng thành ngang hay dọc -> thay ₫ổi góc chạy if (x == 0 || x == Xmax - 1) { dblGocChay = DoiGocChayX(dblGocChay); } else if (y == 0 || y == Ymax - 1) dblGocChay = DoiGocChayY(dblGocChay); } //Hiệu chỉnh tọa ₫ộ x của thread tx = 2 * Math.Cos(dblGocChay * PI / 180); x = x + (int)tx; if (x < 0)

Page 141: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 7

{ x = 0; } else if (x >= Xmax) { x = Xmax - 1; } //Hiệu chỉnh tọa ₫ộ y của thread ty = 2 * Math.Sin(dblGocChay * PI / 180); y = y + (int)ty; if (y < 0) { y = 0; } else if (y >= Ymax) { y = Ymax - 1; } //chỉnh góc chạy khi ₫ụng 1 trong 4 góc if (x == 0 && y == 0) //góc trên trái ChinhGocChay(dblGocChay + 45); else if (x == 0 && y == Ymax - 1) //góc dưới trái ChinhGocChay(dblGocChay + 45); else if (x == Xmax - 1 && y == 0) //góc trên phải ChinhGocChay(dblGocChay + 45); else if (x == Xmax - 1 && y == Ymax - 1) //góc dưới phải ChinhGocChay(dblGocChay + 45); //Lưu vị trí mới Pos.X = (int)x; Pos.Y = (int)y; } } 

10. Dời chuột về ₫ầu file mã nguồn của class MyThread rồi thêm lệnh using như sau : using System.Threading; using System.Drawing; 11. Ấn phải chuột vào phần tử gốc của cây Project trong cửa sổ Solution Explorer, chọn

option Add.New Folder ₫ể thêm folder với tên là Resources, ta sẽ dùng folder này chứa các file bitmap ₫ược dùng trong chương trình.

12. Ấn phải chuột vào folder Resources, chọn option Existing Items, duyệt chọn 26 file bitmap miêu tả 26 icon A-Z ₫ể add chúng vào folder Resources.

12. Chọn 26 mục vừa add vào folder Resources ₫ể hiển thị cửa sổ thuộc tính chúng của chúng, hiệu chỉnh lại thuộc tính Build Action về giá trị mới là "Embedded Resource".

13. Chọn menu Debug.Start Debugging ₫ể dịch và chạy thử ứng dụng.

14. Khi Form chương trình hiển thị, hãy thực hiện gỏ phím qui ₫ịnh như sau ₫ể quản lý các thread :

Ấn phím từ A-Z ₫ể kích hoạt chạy thread có tên tương ứng. Ấn phím Ctrl-Alt-X ₫ể tạm dừng chạy thread X. Ấn phím Alt-X ₫ể chạy tiếp thread X. Ấn phím Shift-X ₫ể tăng ₫ộ ưu tiên chạy cho thread X.

Page 142: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 8

Ấn phím Ctrl-X ₫ể giảm ₫ộ ưu tiên chạy cho thread X. Ấn phím Ctrl-Shift-X ₫ể dừng và thoát thread X.

Khi số thread chạy tương ₫ối nhiều, hãy quan sát hiện tượng icon của thread này tiến ₫ến và ₫è icon của thread khác. Đây là vần ₫ề tương tranh giữa các thread khi chúng cùng truy xuất tài nguyên dùng chung (cell hiển thị).

Page 143: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 1

MÔN : LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG Bài thực hành số 11.4 : Viết phần mềm giải quyết tương tranh giữa các thread

I. Mục tiêu :

Giúp SV làm quen với việc dùng class Thread của namespace System.Threadings ₫ể quản lý thread.

Giúp SV làm quen với việc dùng class Mutex của namespace System.Threadings ₫ể loại trừ tương hỗ giữa các thread khi chúng cùng truy xuất vào tài nguyên dùng chung.

II. Nội dung : Xây dựng chương trình cho phép người dùng thực hiện quản lý các thread có tên là A-

Z như kích hoạt chạy, tạm dừng, chạy lại, tăng/giảm quyền ưu tiền, dừng và xóa thread... bằng các thao tác ấn phím. Mỗi thread khi chạy sẽ hiển thị icon miêu tả mình lên form, icon sẽ chạy theo 1 phương xác ₫ịnh và khi ₫ụng thành form thì dội lại theo nguyên lý vật lý.

Dùng Mutex ₫ể quản lý từng cell hiển thị, thread nào muốn hiển thị cell nào thì phải gọi tác vụ WaitOne() của Mutex của cell tương ứng. Khi không dùng cell cũ nữa, thread phải gọi tác vụ ReleaseMutex() của Mutex của cell ₫ó.

III. Chuẩn ₫ầu ra : Sinh viên nắm vững và sử dụng thành thạo class Thread ₫ể quản lý thread. Sinh viên nắm vững vấn ₫ề tương tranh giữa các thread khi chúng truy xuất tài

nguyên dùng chung. Sinh viên nắm vững và sử dụng thành thạo class Mutex ₫ể loại trừ tương hỗ giữa các

thread khi chúng cùng truy xuất vào tài nguyên dùng chung.

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 "Windows Form 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. ThreadDemo3), 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ế. Bài thực hành này không thiết kế form mà chỉ viết code cho chương trình vì form ₫ược hiệu chỉnh kích thước ₫ộng và nội dung hiển thị trong form cũng ₫ược hiểu chỉnh ₫ộng bởi các thread ₫ang chạy.

4. 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 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. 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 Form1_Load(object sender, EventArgs e) { //tạo ₫ối tượng quản lý việc truy xuất tài nguyên trong project System.Reflection.Assembly myAssembly = System.Reflection.Assembly.GetExecutingAssembly(); threadLst = new MyThread[26]; int i; //tạo ma trận semaphore Mutex ₫ể bảo vệ các cell nàm hình mutList = new Mutex[yMax, xMax]; int h, cot;

Page 144: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 2

for (h = 0; h < yMax; h++) for (cot = 0; cot < xMax; cot++) mutList[h, cot] = new Mutex(); //Lặp thiết lập trạng thái ban ₫ầu cho 26 thread từ A-Z for (i = 0; i < 26; i++) { threadLst[i] = new MyThread(rnd, xMax, yMax); threadLst[i].stop = threadLst[i].suspend = threadLst[i].start = false; char c = (char)(i + 65); //₫ọc bitmap miêu tả thread c từ file myStream = myAssembly.GetManifestResourceStream("ThreadDemo3.Resources.Image" + c.ToString() + ".bmp"); threadLst[i].Pic = new Bitmap(myStream); threadLst[i].Xmax = 25; threadLst[i].Ymax = 20; } ClientSize = new Size(25 * 30, 20 * 30); this.Location = new Point(0, 0); this.BackColor = Color.Black; }

5. Tạo hàm xử lý sự kiện KeyDown cho Form. 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 :

//hàm xử lý gỏ phím của user ₫ể quản lý thread private void Form1_KeyDown(object sender, KeyEventArgs e) { //xác ₫ịnh mã phím ấn, nếu không phải từ A-Z thì phớt lờ int newch = e.KeyValue; if (newch < 0x41 || newch > 0x5a) return; //xác ₫ịnh chức năng mà user muốn và thực hiện if (e.Control && e.Shift) { //kill thread // dừng Thread threadLst[newch - 65].start = false; } else if (e.Control) { //giảm ₫ộ ưu tiên tối thiểu threadLst[newch - 65].t.Priority = ThreadPriority.Lowest; MessageBox.Show(threadLst[newch - 65].t.Priority.ToString()); } else if (e.Control && e.Alt) { //tạm dừng thread if (threadLst[newch - 65].start && !threadLst[newch - 65].suspend) { threadLst[newch - 65].t.Suspend(); threadLst[newch - 65].suspend = true; } } else if (e.Alt) { //cho thread chạy lại if (threadLst[newch - 65].start && threadLst[newch - 65].suspend)

Page 145: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 3

{ threadLst[newch - 65].t.Resume(); threadLst[newch - 65].suspend = false; } } else if (e.Shift) { //tăng ₫ộ ưu tiên tối ₫a threadLst[newch - 65].t.Priority = ThreadPriority.Highest; MessageBox.Show(threadLst[newch - 65].t.Priority.ToString()); } else { //tạo mới thread và bắt ₫ầu chạy if (!threadLst[newch - 65].start) { threadLst[newch - 65].start = true; threadLst[newch - 65].suspend = false; threadLst[newch - 65].t = new Thread(new ParameterizedThreadStart(Running)); if (newch == 65) threadLst[newch - 65].t.Priority = ThreadPriority.Highest; else threadLst[newch - 65].t.Priority = ThreadPriority.Lowest; threadLst[newch - 65].t.Start(threadLst[newch - 65]); } } } 

6. Tạo hàm xử lý sự kiện FormClosed cho Form. 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 Form1_FormClosed(object sender, FormClosedEventArgs e) { int i; //lặp kiểm tra xem có thread con nào còn chạy không, nếu có thì xóa nó for (i = 0; i < 26; i++) if (threadLst[i].start) { threadLst[i].start = false; while (!threadLst[i].stop) ; } }

7. Dời chuột về ₫ầu class Form1 rồi thêm lệnh ₫ịnh nghĩa các kiểu dữ liệu, các thuộc tính, các hàm dịch vụ cần dùng như sau :

//₫ịnh nghĩa các thuộc tính cần dùng Stream myStream; Mutex[,] mutList; MyThread[] threadLst; const int xCell = 30; const int yCell = 30; const int xMax = 25; const int yMax = 20; //tạo ₫ối tượng sinh số ngẫu nhiên public Random rnd = new Random(); //₫ịnh nghĩa hàm giả lập hành vi của thread

Page 146: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 4

void MySleep(long count) { long i, j, k = 0; for (i = 0; i < count; i++) for (j = 0; j < 64000; j++) k = k + 1; } //₫ịnh nghĩa hàm mà mỗi thread sẽ chạy void Running(object obj) { //ép kiểu tham số về MyThread theo yêu cầu xử lý MyThread p = (MyThread)obj; //tạo ₫ối tượng vẽ Graphics g = this.CreateGraphics(); //tạo chổi màu ₫en ₫ể xóa cell cũ Brush brush = new SolidBrush(Color.FromArgb(0, 0, 0)); //xin khóa truy xuất cell (x1,y1) mutList[p.Pos.Y, p.Pos.X].WaitOne(); int x1, y1; int x2, y2; int x, y; bool kq=true; try { while (p.start) { //lặp trong khi chưa có yêu cầu kết thúc //xác ₫ịnh tọa ₫ộ hiện hành của thread x1 = p.Pos.X; y1 = p.Pos.Y; //hiển thị logo của thread ở (x1,y1) g.DrawImage(p.Pic, xCell * x1, yCell * y1); Color c = p.Pic.GetPixel(1,1); int yR, yG, yB; if (c.R > 128) yR = 0; else yR = 255; if (c.G > 128) yG = 0; else yG = 255; if (c.B > 128) yB = 0; else yB = 255; Pen pen = new Pen(Color.FromArgb(yR, yG, yB), 2); if (p.tx >= 0 && p.ty >= 0) { //hiện mũi tên góc dưới phải x = xCell * x1 + xCell - 2; y = yCell * y1 + yCell - 2; g.DrawLine(pen, x, y, x - 10, y); g.DrawLine(pen, x, y, x, y-10); } else if (p.tx >= 0 && p.ty < 0) { //hiện mũi tên góc trên phải x = xCell * x1 + xCell - 2; y = yCell * y1 + 2; g.DrawLine(pen, x, y, x - 10, y); g.DrawLine(pen, x, y, x, y + 10); } else if (p.tx < 0 && p.ty >= 0) { //hiện mũi tên góc dưới trái x = xCell * x1 + 2; y = yCell * y1 + yCell - 2; g.DrawLine(pen, x, y, x + 10, y);

Page 147: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 5

g.DrawLine(pen, x, y, x, y - 10); } else {//hiện mũi tên góc trên trái x = xCell * x1 + 2; y = yCell * y1 + 2; g.DrawLine(pen, x, y, x + 10, y); g.DrawLine(pen, x, y, x, y + 10); } //giả lập thực hiện công việc của thread tốn 500ms MySleep(500); //xác ₫ịnh vị trí mới của thread p.HieuchinhVitri(); x2 = p.Pos.X; y2 = p.Pos.Y; //xin khóa truy xuất cell (x2,y2) while (true) { kq = mutList[y2, x2].WaitOne(new TimeSpan(0,0,2)); if (kq==true || p.start==false) break; } // Xóa vị trí cũ g.FillRectangle(brush, xCell * x1, yCell * y1, xCell, yCell); //trả cell (x1,y1) cho các thread khác truy xuất mutList[y1, x1].ReleaseMutex(); if (kq == false && p.start == false) { //xoa thread // dừng Thread p.t.Abort(); p.stop = true; return; } } } catch (Exception e) { p.t.Abort(); } //dọn dẹp thread trước khi ngừng x1 = p.Pos.X; y1 = p.Pos.Y; g.FillRectangle(brush, xCell * x1, yCell * y1, xCell, yCell); //trả cell (x1,y1) cho các thread khác truy xuất mutList[y1, x1].ReleaseMutex(); // dừng Thread p.stop = true; p.t.Abort(); } 

8. Dời chuột về ₫ầu file mã nguồn Form1 rồi thêm lệnh using như sau : using System.Threading; using System.Resources; using System.IO; 9. Ấn phải chuột vào phần tử gốc của cây Project trong cửa sổ Solution Explorer, chọn

option Add.Class, ₫ặt tên là MyThread.cs ₫ể tạo ra file ₫ặc tả class chứa các tham số phục vụ cho từng thread con chạy. Khi cửa sổ hiển thị mã nguồn của class MyThread hiển thị, viết code cho class này như sau :

class MyThread { const double PI = 3.1416;

Page 148: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 6

public Thread t; //tham khảo ₫ến thread hiện hành public Boolean start; //trạng thái Start của thread public Boolean stop; //trạng thái Start của thread public Boolean suspend; //trạng thái Suspend của thread public Boolean WaitOne = false; //trạng thái chờ truy xuất cell public Bitmap Pic; //icon miêu tả thread internal int Xmax; //₫ộ rộng vùng chạy của thread internal int Ymax; //₫ộ cao vùng chạy của thread public Point Pos; //vị trí của thread trong vùng chạy double dblGocChay; //góc chạy của thread internal double tx, ty; //bước tăng theo x và y //hàm khởi tạo các thông số của thread public MyThread(Random rnd, int xMax, int yMax) { Xmax = xMax; Ymax = yMax; Pos.X = (int)(rnd.Next(0, Xmax)); Pos.Y = (int)(rnd.Next(0, Ymax)); dblGocChay = ChinhGocChay(rnd.Next(0, 360)); } //========================================================= //Hiệu chỉnh góc chạy của thread //₫ể tránh các trường hợp thread chạy thẳng ₫ứng hay ngang //========================================================= double ChinhGocChay(double dblGocChay) { double goc = dblGocChay; if (0 <= goc && goc < 90) return 45; if (90 <= goc && goc < 180) return 135; if (180 <= goc && goc < 270) return 225; if (270 <= goc) return 315; return goc; } //========================================================= //Tính góc phản xạ mới khi thread ₫ụng thành ₫ứng (bên trái hay phải). //========================================================= double DoiGocChayX(double dblGocChay) { double goc; if (dblGocChay > 0 && dblGocChay < 180) goc = 180 - dblGocChay; else goc = 180 + 360 - dblGocChay; return ChinhGocChay(goc); } //========================================================= //Tính góc phản xạ mới khi thread ₫ụng thành ngang (trên hay dưới). //========================================================= double DoiGocChayY(double dblGocChay) { return ChinhGocChay(360 - dblGocChay); }

Page 149: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 7

//========================================================= //Hiệu chỉnh vị trí của thread //========================================================= public void HieuchinhVitri() { int x, y; x = Pos.X; y = Pos.Y; if (x == 0 || x == Xmax - 1 || y == 0 || y == Ymax - 1) { //icon ₫ụng thành ngang hay dọc -> thay ₫ổi góc chạy if (x == 0 || x == Xmax - 1) { dblGocChay = DoiGocChayX(dblGocChay); } else if (y == 0 || y == Ymax - 1) dblGocChay = DoiGocChayY(dblGocChay); } //Hiệu chỉnh tọa ₫ộ x của thread tx = 2 * Math.Cos(dblGocChay * PI / 180); x = x + (int)tx; if (x < 0) { x = 0; } else if (x >= Xmax) { x = Xmax - 1; } //Hiệu chỉnh tọa ₫ộ y của thread ty = 2 * Math.Sin(dblGocChay * PI / 180); y = y + (int)ty; if (y < 0) { y = 0; } else if (y >= Ymax) { y = Ymax - 1; } //chỉnh góc chạy khi ₫ụng 1 trong 4 góc if (x == 0 && y == 0) //góc trên trái ChinhGocChay(dblGocChay + 45); else if (x == 0 && y == Ymax - 1) //góc dưới trái ChinhGocChay(dblGocChay + 45); else if (x == Xmax - 1 && y == 0) //góc trên phải ChinhGocChay(dblGocChay + 45); else if (x == Xmax - 1 && y == Ymax - 1) //góc dưới phải ChinhGocChay(dblGocChay + 45); //Lưu vị trí mới

Page 150: Trang 1 - Tài Liệu Học Tậpdulieu.tailieuhoctap.vn/books/cong-nghe-thong-tin/lap... · 2015-07-20 · - duyệt tuần tự từ ₫ầu ₫ến cuối ₫a thức ₫ể cộng

Trang 8

Pos.X = (int)x; Pos.Y = (int)y; } } 

10. Dời chuột về ₫ầu file mã nguồn của class MyThread rồi thêm lệnh using như sau : using System.Threading; using System.Drawing; 11. Ấn phải chuột vào phần tử gốc của cây Project trong cửa sổ Solution Explorer, chọn

option Add.New Folder ₫ể thêm folder với tên là Resources, ta sẽ dùng folder này chứa các file bitmap ₫ược dùng trong chương trình.

12. Ấn phải chuột vào folder Resources, chọn option Existing Items, duyệt chọn 26 file bitmap miêu tả 26 icon A-Z ₫ể add chúng vào folder Resources.

12. Chọn 26 mục vừa add vào folder Resources ₫ể hiển thị cửa sổ thuộc tính chúng của chúng, hiệu chỉnh lại thuộc tính Build Action về giá trị mới là "Embedded Resource".

13. Chọn menu Debug.Start Debugging ₫ể dịch và chạy thử ứng dụng.

14. Khi Form chương trình hiển thị, hãy thực hiện gỏ phím qui ₫ịnh như sau ₫ể quản lý các thread :

Ấn phím từ A-Z ₫ể kích hoạt chạy thread có tên tương ứng. Ấn phím Ctrl-Alt-X ₫ể tạm dừng chạy thread X. Ấn phím Alt-X ₫ể chạy tiếp thread X. Ấn phím Shift-X ₫ể tăng ₫ộ ưu tiên chạy cho thread X. Ấn phím Ctrl-X ₫ể giảm ₫ộ ưu tiên chạy cho thread X. Ấn phím Ctrl-Shift-X ₫ể dừng và thoát thread X.

Khi số thread chạy tương ₫ối nhiều, hãy quan sát hiện tượng icon của thread này tiến ₫ến và ₫è icon của thread khác. Đây là vần ₫ề tương tranh giữa các thread khi chúng cùng truy xuất tài nguyên dùng chung (cell hiển thị).