Showing posts with label C Plus Plus. Show all posts
Showing posts with label C Plus Plus. Show all posts

[Thuật toán đồ thị / code C++] Thuật toán Dijkstra tìm đường đi ngắn nhất trên đồ thị G

Thuật toán Dijkstra tìm đường đi ngắn nhất trên đồ thị G


Mô tả bài toán: cho đồ thị vô hướng G=(V,E) hãy xác định đường đi ngắn nhất từ đỉnh D tới đỉnh C của đồ thị G.

Ý tưởng thuật toán: sử dụng thuật toán Dijkstra.
+ Mô tả dữ liệu đầu vào và đầu ra của bài toán:
+ Dữ liệu vào: đồ thị đã liên thông và cho trong tập tin InputDijkstra.txt.
 - Dòng đầu ghi số n là số đỉnh của một đồ thị (0<n<100)
 - Dòng thứ hai lưu đỉnh D và đỉnh C.
 - Dòng i+2 (1 < i < n ) chứa n số A[i,1],A[i,2]…A[i,n] mỗi số cách nhau bởi một khoảng trắng.
Dữ liệu ra: xuất ra màn hình đường đi ngắn nhất từ đỉnh D đến C và giá trị đường đi ngắn nhẩt tìm được.

Ví dụ:
[Cài đặt bài toán - code C++]

#include <stdio.h>
#include <conio.h>
#include <iostream.h>
#include <values.h>
#define max 100

void Doc_File(int A[max][max], int &n, int &D, int &C) {
   FILE*f = fopen("InputDijkstra.txt","rb");
   fscanf(f,"%d%d%d",&n,&D,&C);
   cout<<"Ma Tran Lien Ket Tuong Ung.\n";
   cout<<D<<" "<<C<<endl;
   for(int i =0;i<n;i++) {
          for(int j =0;j<n;j++) {
              fscanf(f,"%d",&A[i][j]);
              cout<<A[i][j]<<" ";
   }
   cout<<endl;
  }
fclose(f);
D--; C--;
}

// thuat toan Dijkstra

void Dijkstra(int A[max][max], int n, int D, int C) {
  char DanhDau[max];
  int Nhan[max], Truoc[max], XP, min;
  for(int i=0; i<n; i++){
        Nhan[i] = MAXINT;
        DanhDau[i] = 0;
        Truoc[i] = D;
  }
  Nhan[D] = 0;
  DanhDau[D] = 1;
  XP = D;
  while(XP != C){
       for(int j=0; j<n; j++)
          if(A[XP][j]>0 && Nhan[j]>A[XP][j]+Nhan[XP] && DanhDau[j]==0) {
              Nhan[j] = A[XP][j]+Nhan[XP];
              Truoc[j] = XP;
          }
          min = MAXINT;
        for(j = 0; j<n; j++)
               if(min>Nhan[j]&& DanhDau[j]==0){
                      min = Nhan[j];
                      XP = j;
              }
        DanhDau[XP] = 1;
   }
    cout<<"Duong Di Ngan Nhat La:"<<Nhan[C]<<endl;
    cout<<C+1<<" <- "<<Truoc[C]+1;
    i = Truoc[C];
    while(i!=D){
          i = Truoc[i];
          cout<<" <- "<<i+1;
      }
}

void main() {
    int A[max][max],n,Dau,Cuoi;
    Doc_File(A,n,Dau,Cuoi);
    Dijkstra(A,n,Dau,Cuoi);
     getch();
}

[Thuật toán đồ thị / code C++] Thuật toán Dijkstra - tìm đường đi ngắn nhất từ đỉnh D đến đỉnh C trên đồ thị G.

Mô tả bài toán: cho đồ thị vô hướng G=(V,E) hãy xác định đường đi ngắn nhất từ đỉnh D tới đỉnh C của đồ thị G.

Ý tưởng thuật toán: sử dụng thuật toán Dijkstra (tìm hiểu thêm về thuật toán Dijkstra tại đây).

Mô tả dữ liệu đầu vào và đầu ra của bài toán:

+ Dữ liệu vào: đồ thị đã liên thông và cho trong tập tin Dijkstra.inp.
- Dòng đầu ghi số n là số đỉnh của một đồ thị (0<n<100)
- Dòng thứ hai lưu đỉnh D và đỉnh C.
- Dòng i+2 (1 <= i <= n ) chứa n số A[i,1],A[i,2]…A[i,n] mỗi số cách nhau bởi một khoảng trắng.

+ Dữ liệu ra: xuất ra màn hình đường đi ngắn nhất từ đỉnh D đến C và giá trị đường đi ngắn nhẩt tìm được.




[Cài đặt thuật toán với Turbo C++]

#include <stdio.h>
#include <conio.h>
#include <iostream.h>
#include <values.h>
#define max 100
#define FileIn "Dijkstra.inp"

// doc file chua do thi G
void Doc_File(int A[max][max], int &n, int &D, int &C) {
  FILE*f = fopen(FileIn,"rb");
  fscanf(f,"%d%d%d",&n,&D,&C);
  cout<<"Ma Tran Lien Ket Tuong Ung.\n";
  cout<<D<<" "<<C<<endl;
  for(int i =0;i<n;i++) {
    for(int j =0;j<n;j++) {
       fscanf(f,"%d",&A[i][j]);
       cout<<A[i][j]<<" ";
    }
   cout<<endl;
  }
  fclose(f);
  D--; C--;
 }

// thuat toan Dijkstra
void Dijkstra(int A[max][max], int n, int D, int C) {
  char DanhDau[max];
  int Nhan[max], Truoc[max], XP, min;
  for(int i=0; i<n; i++){
  Nhan[i] = MAXINT;
  DanhDau[i] = 0;
  Truoc[i] = D;
 }
 Nhan[D] = 0;
 DanhDau[D] = 1;
 XP = D;
 while(XP != C){
    for(int j=0; j<n; j++)
       if(A[XP][j]>0 && Nhan[j]>A[XP][j]+Nhan[XP] && DanhDau[j]==0) {
          Nhan[j] = A[XP][j]+Nhan[XP];
          Truoc[j] = XP;
       }
       min = MAXINT;
       for(j = 0; j<n; j++)
         if(min>Nhan[j]&& DanhDau[j]==0){
            min = Nhan[j];
           XP = j;
        }
      DanhDau[XP] = 1;
  }
  cout<<"Duong Di Ngan Nhat La:"<<Nhan[C]<<endl;
  cout<<C+1<<" <- "<<Truoc[C]+1;
  i = Truoc[C];
  while(i!=D){
     i = Truoc[i];
     cout<<" <- "<<i+1;
  }
 }
// ham chinh
void main() {
   int A[max][max],n,Dau,Cuoi; // ma tan A chua do thi
   Doc_File(A,n,Dau,Cuoi);
   Dijkstra(A,n,Dau,Cuoi);
   getch();
}


[ C++ ] Tính đa hình, phương thức ảo, lớp trừu tượng trong C++ [Lập trình hướng đối tượng với C++]

[ C++ ] Tính đa hình, phương thức ảo, lớp trừu tượng trong C++ [Lập trình hướng đối tượng với C++]


* TÍNH ĐA HÌNH (Polymorphism)

Phương thức của lớp cha khi thực hiện sẽ được thay thế bằng một phương thức của lớp con thì phương thức này gọi là có tính đa hình. Tính đa hình giúp cho việc lập trình đơn giản và dễ mở rộng. Để cài đặt phương thức có tính đa hình ta dùng phương thức ảo và phương thức thuần ảo.

Tính đa hình, phương thức ảo, lớp trừu tượng trong C++


* PHƯƠNG THỨC ẢO (virtual method)

Phương thức ảo là phương thức được định nghĩa ở lớp cơ sở (lớp cha) mà các lớp dẫn xuất (lớp con) muốn sử dụng phải định nghĩa lại. Dùng từ khoá virtual để khai báo phương thức ảo:

Cú pháp: 


           virtual <kiểu trả về> <tên phương thức >(<d/s tham số>)
             {
                …
              }

Phương thức khởi tạo không được là phương thức ảo nhưng phương thức hủy bỏ có thể là phương thức ảo. Dùng phương thức ảo chậm hơn phương thức thông thường vì khi thực hiện mới được xác định cụ thể.


Ví dụ [Code Tubor C++ 3.0/4.5]:

#include <iostream.h>
#include <conio.h>
class A
{
  public:
  virtual void Chao() //phuong thuc ao
 {
  cout<<"\nA chao cac ban";
 }
};

// class B
class B:public A
{
  public:
  void Chao()
   {
     cout<<"\nB chao cac ban";
   }
 };


// class C
class C:public A
{
  public:
  void Chao()
  {
    cout<<"\nC chao cac ban";
  }
};
// ham main
void main()
{
   A a;
   A *pa= new A; pa->Chao(); //goi chao cua A
   B b;
   pa=&b; pa->Chao(); //goi chao cua B
   C c;
   pa=&c; pa->Chao(); //goi chao cua C
   getch();
}



Nhận xét:

- Phương thức Chao() có tính đa hình: cùng lời gọi pa->chao() nhưng lần 1 gọi chao cua A, lan 2 gọi chao cua B, lan 3 goi chao cua C.

- Nếu trong lớp B, C không định nghĩa lại phương thức chào thì cả ba lần đều gọi chào của A.

- Nếu phương thức chao() trong lớp A không khai báo virtual thì phương thức chao() sẽ không có tính đa hình, khi đó cả ba lần đều gọi chào của A.

- Có thể gán địa chỉ của đt thuộc lớp con vào biến con trỏ, trỏ tới đt thuộc lớp cha nhưng không thể làm ngược lại (áp dụng nguyên tắc “con gán vào cha” đối với biến kiểu đối tượng hoặc biến kiểu con trỏ, trỏ tới đối tượng)

* PHƯƠNG THỨC TRỪU TƯỢNG, LỚP TRỪU THƯỢNG

Phương thức trừu tượng (thuần ảo) là phương thức ảo nhưng không có lệnh (phương thức rỗng). Phương thức thuần ảo có dạng:

Cú pháp: 

             virtual <kiểu trả về> <tên phương thức >(<d/s tham số>) = 0;

Lớp có phương thức ảo gọi là lớp trừu tượng (abstract class). Nếu một lớp thừa kế lớp trừu tượng mà không định nghĩa lại phương thức thuần ảo thì lớp thừa kế cũng là lớp trừu tượng.

Lưu ý: không được tạo đối tượng thuộc lớp trừu tượng.

Thường ta chọn phương thức ở lớp cha, mà chưa thể xác định cách thực hiện, làm phương thức  thuần ảo. Ở lớp con ta sẽ định nghĩa lại phương thức thuần ảo, để xác định cụ thể cách thức thực hiện.

Ví dụ:

Nhập một danh sách gồm giảng viên và sinh viên, in ra danh sách những người được thưởng. Biết rằng điều kiện được thưởng là giảng viên có số bài báo >3, sinh vien có điểm thi tốt nghiệp >8.

[Code Tubor C++ 3.0/4.5]

#include <iostream.h>
#include <conio.h>

class Nguoi
{
  char hoten[30];
  public:
  virtual void nhap() //phuong thức ảo
 {
   cout<<"\nHo ten:"; cin.getline(hoten,30);
  }
  virtual int thuong()=0; //phuong thức thuần ảo
  virtual void xuat() //phuong thức ảo
  {
    cout<<"\nHo ten:"<<hoten;
  }
 };
// class Sinhvien
class Sinhvien:public Nguoi
 {
  float dttn;
  public:
  void nhap() //dinh nghia l?i phuong th?c nh?p
  {
    Nguoi::nhap();
    cout<<"\nDiem thi tn:"; cin>>dttn;
   }
   int thuong() //định nghĩa lại phương thức thưởng
   {
      return (dttn>8?1:0);
   }
   void xuat() //dinh nghia lại phuong thức xuất
   {
     cout<<"\n-Sinh vien:";
     Nguoi::xuat();
     cout<<"\nDiem thi tn:"<<dttn;
    }
  };
// class Giangvien
class Giangvien:public Nguoi
 {
   int sobaibao;
   public:
   void nhap()
   {
     Nguoi::nhap();
     cout<<"\nSo bai bao:"; cin>>sobaibao;
   }
   int thuong()
   {
     return (sobaibao>3?1:0);
   }
   void xuat()
   {
     cout<<"\n-Giang vien:";
     Nguoi::xuat();
     cout<<"\nSo bai bao:"<<sobaibao;
    }
 };
// hàm main
void main()
{
   Nguoi *ds[100]; int k=0, chon, i;
   while(1)
   {
      cout<<"\n*Gv/Sv/Ngung (1,2,3):"; cin>>chon; cin.get();
      if (chon==3) break;
      if (chon==1) ds[k]=new Giangvien();
      if (chon==2) ds[k]=new Sinhvien();
      ds[k]->nhap(); k++;
   }
   cout<<"\n*Danh sach nhung nguoi duoc thuong";
   for (i=0; i<k; i++)
      if (ds[i]->thuong()) ds[i]->xuat();
  getch();
}







Hãy mở rộng bài tập trên bằng cách thêm một lớp nhân viên, biết rằng nhân viên có số ngày nghỉ trong năm < 5  là được thưởng.

Nhận xét:

Do phương thức “nhập, thưởng, xuất” là phương thức ảo của lớp người (lớp cha) nên các phương thức này khi thực thi sẽ có tính đa hình: có khi gọi “nhập, thưởng, xuất” của lớp giảng viên (lớp con), có khi thì gọi “nhập, thưởng, xuất” của lớp sinh viên (lớp con) tuỳ theo con trỏ ds[i] đang giữ địa chỉ của đối tượng giảng viên hay sinh viên.


Một số tài liệu và khoá học bổ ích dành cho bạn: 

# Giáo Trình: Kỹ Thuật Lập Trình C/C++ Căn Bản Và Nâng Cao [Click để xem]

# Khoá học online: Học lập trình C/C++ TỪ A - Z [Click để xem]




Chúc các bạn thành công!

 

----------

[Tự học lập trình C/C++] Bài 14: Lập trình hướng đối tượng (OOP) với C++

---------------------------------
* TÓM TẮT LÝ THUYẾT
---------------------------------
1. Giới thiêu lập trình hướng đối tượng (OOP) với C++
- C++ là ngôn ngữ "lai" giữa lập trình Cấu trúc và Lập trình hướng đối tượng.
- Lập trình hướng đối tượng (OOP- Object-Oriented Programming) là một cách tư duy mới, tiếp cận hướng đối tượng để giải quyết vấn đề bằng máy tính. Thuật ngữ OOP ngày càng trở nên thông dụng trong lĩnh vực công nghệ thông tin.
- Lập trình hướng đối tượng (OOP) là một phương pháp thiết kế và phát triển phần mềm dựa trên kiến trúc lớp và đối tượng.  
- Trong lập trình hướng đối tượng trong mỗi chương trình chúng ta có một số các đối tượng (object) có thể tương tác với nhau , thuộc các lớp (class) khác nhau, mỗi đối tượng tự quản lý lấy các dữ liệu của riêng chúng.

2. Khai báo lớp (class), đối tượng (object)
i) Đối tượng (object)
Đối tượng là một thực thể phần mềm bao bọc các thuộc tính và các phương thức liên quan.  

ii) Lớp (class)
Lớp (class) là một thiết kế (blueprint) hay một mẫu ban đầu (prototype) định nghĩa các thuộc tính và các phương thức chung cho tất cả các đối tượng của cùng một loại nào đó.  
Một đối tượng là một thể hiện cụ thể của một lớp.

iii) Khai báo lớp và đối tượng
a. Khai báo lớp
+ Lớp gồm 2 thành phần:
 - Thuộc tính (attribute)
 - Phương thức (method)

+ Khai báo:
class  <Tên lớp>
    {        
         public:
             (danh sách các thành viên [bao gồm cả thuộc tính và phương thức]  có đặc tính công cộng)                
         private:
            (danh sách các thành viên [bao gồm cả thuộc tính và phương thức] có đặc tính riêng tư)         
        protected:
            (danh sách các thành viên [bao gồm cả thuộc tính và phương thức] có đặc tính bảo tồn)       
    };  // dấu chấm phẩy chấm dứt câu lệnh

+ Việc sử dụng lớp trong một chương trình C++ có hai phần chính là phần định nghĩa lớp và phần khai báo và truy cập các thành viên của một đối tượng có kiểu là một lớp cho trước.

Ví dụ:
class SV{
// thuoc tinh
public:
char hoTen[30];
int tuoi;
float diem;

// phuong thuc
public:
void NhapDiem();
float TinhDiem();

};


b. Khai báo đối tượng
<Tên lớp> <tên đối tương> = <Tên lớp> ([Tham số khởi dựng]);

Ví dụ:
// t là đối tượng của lớp SV
SV t = SV();


3. Phương thức khởi dụng (constructions) và phương thức hủy (Destructor)
 i) Phương thức khởi dụng (constructions)
+ Các phương thức thiết lập có nhiệm vụ thiết lập thông tin ban đầu cho một đối tượng thuộc về lớp ngay khi đối tượng được khai báo.

+ Đặc điểm của phương thức thiết lập:
 - Tên của phương thức thiết lập trùng với tên lớp.
- Phương thức thiết lập không có giá trị trả về.
  - Một lớp có thể có nhiều phương thức thiết lập khác nhau.
- Trong quá trình tồn tại của đối tượng, chỉ có một lần duy nhất mà phương thức thiết lập được gọi thực hiện mà thôi đó là khi đối tượng ra đời.
- Phân loại phương thức thiết lập: Có thể chia phương thức thiết lập thành 3 loại
  - Phương thức thiết lập mặc định (default contructor): là phương thức thiết lập không nhận tham số đầu vào. Các thông tin ban đầu cho đối tượng của lớp bằng những giá trị mặc định (do lập trình viên quy định). Phương thức thiết lập mặc định không có đối số.
- Phương thức thiết lập sao chép (copy contructor): là phương thức thiết lập nhận tham số đầu vào là 1 đối tượng thuộc cùng 1 lớp. Các thông tin ban đầu của đối tượng sẽ hoàn toàn giống thông tin của đối tượng tham số đầu vào.
- Phương thức thiết lập có tham số: là phương thức thiết lập không thuộc 2 loại trên. Các thông tin ban đầu của đối tượng sẽ phụ thuộc vào giá trị các tham số của phương thức thiết lập.

Ví dụ: xây dựng class CphaSo
class CPhanSo
{
        private:          
            int tu;          
            int mau;
 
        public:
            CPhanSo();          
            CPhanSo(const CPhanSo&);
            CPhanSo(int);          
            CPhanSo(int,int);
};

// Khởi dụng mặc định
CPhanSo::CPhanSo()
{
           tu = 0;  
           mau = 1;
}

//Khởi dựng sao chép
CPhanSo::CPhanSo(const CPhanSo& x)
{  
          tu = x.tu;  
          mau = x.mau;
}

//Khởi dụng 1 tham số
CPhanSo::CPhanSo(int t)
{
             tu = t;  
             mau = 1;
}

   // Khởi dựng 2 tham số
CPhanSo::CPhanSo(int t, int m)
{
         tu = t;
         mau = m;
}

 ii) Phương thức hủy (Destructor)
+ Phương thức hủy có nhiệm vụ thu hồi lại bộ nhớ được cấp phát cho đối tượng thuộc lớp ngay khi đối tượng hết phạm vi hoạt động.

+ Các đặc điểm của phương thức hủy:
- Phương thức hủy có tên trùng với tên lớp (có thêm dấu ~ phía trước).
- Phương thức hủy không có giá trị trả về và cũng không nhận tham số đầu vào.
- Mỗi lớp chỉ có nhiều nhất một phương thức hủy. Nếu lập trình viên không xây dựng hàm hủy thì trình biên dịch sẽ tạo ra một phương thức hủy mặc định.
- Phương thức hủy chỉ được tự động gọi thực hiên một lần duy nhất (khi đối tượng hết phạm vi hoạt động).
- Phương thức hủy phải được xây dựng khi trong phương thức khởi tạo, ta có sử dụng các hàm cấp phát bộ nhớ thì ta bắt buộc phải xây dựng phương thức hủy để thu hồi các bộ nhớ này lại.

Ví dụ:
class CString
{
private:
    char *_text;    
    int  size;
public:
        CString(char *ch);//Phương thức khởi tạo  
    ~CString(); // Phương thức hủy
};

// Định nghĩa phương thức khởi tạo
CString::CString( char *ch ) 
{  
    size = strlen(ch) + 1;  
    //Cấp phát bộ nhớ cho biến _text  
    _text = new char[size];    
    if(_text)      
        strcpy( _text, ch);
}

// Định nghĩa phương thức hủy
CString::~CString()
{
 
    // Thu hồi bộ nhớ cấp phát cho biến _text
    if (_text)
        delete[] _text;
}

4. Kế thừa (Inheritance)
- Kế thừa là một đặc trưng quan trọng trong lập trình hướng đối tượng (OOP). Sự kế thừa trong các ngôn ngữ lập trình như C++, Java, C#, VB.Net,.. cơ bản là giống nhau.
- Trong lập trình C++, có thêm khái niệm đa kế thừa mà các ngôn ngữ khác đã bỏ chức năng này do sự nhập nhằng khi sử dụng.
- Kế thừa là cách tạo lớp mới từ các lớp đã được định nghĩa từ trước

Ví dụ: 
//  class B kế thừa class A.
 class A{
        ....
      };

     class B:A{
         ...
     };

   * Lưu ý:
    - Một lớp cha có thể có nhiều lớp con (có phép kế thừa)  
    - Đến lượt mình mỗi lớp con lại có thể có các con khác  
    - Trong C++ cho phép đa kế thừa (một lớp con có thể nhận hơn 1 lớp cha)

5. Phương thức ảo (virtual)
 - Phương thức ảo là phương thức được định nghĩa ở lớp cơ sở (lớp cha) mà các lớp dẫn xuất (lớp con) muốn sử dụng phải định nghĩa lại. Dùng từ khoá virtual để khai báo phương thức ảo:

 - Cú pháp:
 
    virtual <kiểu DL> <tên P.Thức>([tham số])    
       {
          …
       }

 -  Phương thức khởi tạo không được là phương thức ảo nhưng phương thức hủy bỏ có thể là phương thức ảo. Dùng phương thức ảo chậm hơn phương thức thông thường vì khi thực hiện mới được xác định cụ thể.

6. Phương thức trừu tượng, và lớp trừu tượng (abstract)
  - Phương thức trừu tượng (thuần ảo) là phương thức ảo nhưng không có lệnh (phương thức rỗng). Phương thức thuần ảo có dạng:

  - Cú pháp:
     virtual <kiểu DL> <tên ph.thức>([tham số]) = 0;

  - Lớp có phương thức ảo gọi là lớp trừu tượng (abstract class). Nếu một lớp thừa kế lớp trừu tượng mà không định nghĩa lại phương thức thuần ảo thì lớp thừa kế cũng là lớp trừu tượng.

  * Lưu ý: 
   - không được tạo đối tượng thuộc lớp trừu tượng.
   - Thường chọn phương thức ở lớp cha, mà chưa thể xác định cách thực hiện, làm phương thức  thuần ảo. Ở lớp con ta sẽ định nghĩa lại phương thức thuần ảo, để xác định cụ thể cách thức thực hiện.

7. Lớp bạn, hàm bạn (Friend)
Trong khi viết các chương trình trong C++, đôi khi chúng ta cần cấp quyền truy xuất cho một hàm tới các thành viên không là các thành viên chung của một lớp. Một truy xuất như thế được thực hiện bằng cách khai báo hàm như là bạn của lớp. Có hai lý do có thể cần đến truy xuất này là:

  - Có thể là cách định nghĩa hàm chính xác. 
  - Có thể là cần thiết nếu như hàm cài đặt không hiệu quả.
- Cách viết một hàm bạn: Để một hàm trở thành hàm bạn, có hai cách viết:

Cách 1: Đặt từ khóa friend trước các hàm được khai báo trong lớp, sau đó xây dựng hàm bên ngoài như bình thường.

class A
{
private:
 //Cac thuoc tinh
public:
 friend void h1(...);
 friend int h2(...);
 ....
  };

void h1(...)
{
 ...
}

int h2(...)
{
 ...
}
 
Cách 2: Dùng từ khóa friend để xây dựng hàm trong định nghĩa lớp.

class A
{
private:
 //Cac thuoc tinh
public:
   friend void h1(...)  
  {
   ...
  }
 
  friend int h2(...)  
  {
   ...

   }

 ...

};

  - Tính chất của hàm bạn:
+ Trong thân hàm bạn của một lớp có thể truy nhập tới các thuộc tính của các đối tượng thuộc lớp này. Đây là khác nhau duy nhất giữa hàm bạn và hàm thông thường.
+ Hàm bạn không phải là phương thức của một lớp, lời gọi của hàm bạn giống như lời gọi của hàm thông thường.


---------------------------------
** VÍ DỤ ***
---------------------------------

Ví dụ 1:

+ Yêu cầu:
Xây dựng lớp cha (Nguoi), lớp con (HocSinh).

+ Code:

#include<conio.h>
#include<stdio.h>
#include<iostream>
#include<string.h>

using namespace std;


// lop cha
class Nguoi
{
protected:
char hoTen[30];  
        int namSinh;  
  private:  
   char soThich[50]; // so thich
  public:  
  // khoi tao lop Nguoi
    Nguoi(){
       strcpy(hoTen,"Nguyen Van A");    
      namSinh=1990;    
      strcpy(soThich,"Lap trinh");  
    }
 
    // In thông tin
void InTT();
};

// lop con
class HocSinh : public Nguoi
{
  protected:
    int maHS;
  public:
    void Nhap();
    void InTT();
};

// InTT cua cha (Nguoi)

void Nguoi::InTT()
{
  cout << "\n Nam sinh : " << namSinh;
  cout << "\n Ho ten : " << hoTen;
  cout << "\n So thich : " << soThich;
}

// InTT cua con (HocSinh)
void HocSinh::InTT()
{
  cout << "\n Ma hoc sinh : " << maHS;
  cout << "\n Nam sinh : " << namSinh;
  cout << "\n Ho ten : " << hoTen;
}

//  Nhap thong tin
void HocSinh::Nhap()
{
  cout << "\n Nam sinh : "; cin>> namSinh;
  cout << "\n Ho ten : "; gets(hoTen);
  cout << "\n Ma hoc sinh: "; cin>> maHS;
}

// ham main
int main(){
    // khai bao doi tuong Nguoi
    Nguoi a;  a.InTT();
   // khai bao doi tuong HocSinh
    HocSinh t;   t.Nhap();  t.InTT();
   return 0;
}

--------------

Ví dụ 2: 

+ Yêu cầu: Phương thức ảo

+ Code:

#include<conio.h>
#include<stdio.h>
#include<iostream>
#include<string.h>

using namespace std;

class A
{
 public: 
 //phuong thuc ao
  virtual void Chao()
  {
    cout<<"\nA chao cac ban";
  }
};

class B:public A
{
 public:
void Chao()
  {
    cout<<"\nB chao cac ban";
  }
};

class C:public A
{
 public:
void Chao()
  {
    cout<<"\nC chao cac ban";
  }
};

// ham main
int main()
{
 A a;
 A *pa= new A;
 pa->Chao(); //goi chao cua A
 B b;
 pa=&b;
 pa->Chao(); //goi chao cua B
 C c;
 pa=&c;
 pa->Chao(); //goi chao cua C
 return 0;
}

/* Giải thích:
- Phương thức Chao() có tính đa hình: cùng lời gọi pa->chao() nhưng lần 1 gọi chao cua A, lan 2 gọi chao cua B, lan 3 goi chao cua C.

- Nếu trong lớp B, C không định nghĩa lại phương thức chào thì cả ba lần đều gọi chào của A.

- Nếu phương thức chao() trong lớp A không khai báo virtual thì phương thức chao() sẽ không có tính đa hình, khi đó cả ba lần đều gọi chào của A.

- Có thể gán địa chỉ của đt thuộc lớp con vào biến con trỏ, trỏ tới đt thuộc lớp cha nhưng không thể làm ngược lại (áp dụng nguyên tắc “con gán vào cha” đối với biến kiểu đối tượng hoặc biến kiểu con trỏ, trỏ tới đối tượng)
*/

--------------

Ví dụ 3:

+ Yêu cầu:
Nhập một danh sách gồm giảng viên và sinh viên, in ra danh sách những người được thưởng. Biết rằng điều kiện được thưởng là giảng viên có số bài báo >3, sinh vien có điểm thi tốt nghiệp >8.

+ Code:

#include<conio.h>
#include<stdio.h>
#include<iostream>
#include<string.h>

using namespace std;

class Nguoi
{
 char hoten[30];
 public:
//phuong thuc ao
 virtual void nhap()
 {
  cout<<"\nHo ten:"; cin.getline(hoten,30);
 }

//phuong thuc thuc ao (truu tuong)

 virtual int thuong()=0;

//phuong thuc ao

 virtual void xuat()
 {
  cout<<"\nHo ten:"<<hoten;
 }
};

// class sinhvien

class Sinhvien:public Nguoi
{
 float dttn;
 public:
//dinh nghia lai phuong thuc nhap
 void nhap()
 {  Nguoi::nhap();
 cout<<"\nDiem thi tn:"; cin>>dttn;
 }

//dinh nghia lai phuong thuc thuong

 int thuong()
 {
   return (dttn>8?1:0);
 }
 void xuat()
 {
  cout<<"\n-Sinh vien:";
  Nguoi::xuat();
  cout<<"\nDiem thi tn:"<<dttn;
 }
};

class Giangvien:public Nguoi
{
  int sobaibao;
 public:
 void nhap()
 {
  Nguoi::nhap();
  cout<<"\nSo bai bao:"; cin>>sobaibao;
 }
 int thuong()
 {
   return (sobaibao>3?1:0);
 }

 void xuat()
 {
  cout<<"\n-Giang vien:";
  Nguoi::xuat();
  cout<<"\nSo bai bao:"<<sobaibao;
 }
};

// ham main
int main()
{
  Nguoi *ds[100]; int k=0, chon, i;
 while(1)
  {
  cout<<"\n*Chon: Gv / Sv / Close (1,2,3):";
  cin>>chon;  cin.get();
  if (chon==3) break;
  if (chon==1) ds[k]=new Giangvien();
  if (chon==2) ds[k]=new Sinhvien();
  ds[k]->nhap(); k++;
 }

 cout<<"\n*Danh sach nhung nguoi duoc thuong";
 for (i=0; i<k; i++)
   if (ds[i]->thuong()) ds[i]->xuat();
return 0;

}

-----------------

Ví dụ 4: (hàm bạn, lớp bạn)

+ Yêu cầu: Viết hàm Area để tính diện tích hình chữ nhật, Area là hàm bạn của lớp Rectangle

+ Code:

#include<conio.h>
#include<stdio.h>
#include<iostream>
#include<string.h>

using namespace std;

class Rectangle
{
private:
 int w;
 int h;
public:
 Rectangle(int, int);
 // khai bao ham ban Area
 friend int Area(Rectangle);
};
Rectangle::Rectangle(int w, int h){
 this->w = w;
 this->h = h;
 }
// ham ban
int Area(Rectangle rec){
 return (rec.w*rec.h);
}
// ham main
int main()
{
   Rectangle rec(2, 5);
   cout<<"Dien tich HCN:  "<<Area(rec);
   return 0;
}

Một số tài liệu và khoá học bổ ích dành cho bạn: 

# Giáo Trình: Kỹ Thuật Lập Trình C/C++ Căn Bản Và Nâng Cao [Click để xem]

# Khoá học online: Học lập trình C/C++ TỪ A - Z [Click để xem]


------------------------
Xem bài khác:

----------

[Đồ họa trong C\C++] Sử dụng các hàm đồ họa thông dụng trong C\C++ [C\C++]

Đồ hoạ trong C\C++


Tất cả các hàm dùng trong chế độ đồ họa của C\C++ đều được khai trong thư viện <graphics.h>

Chế độ màn hình văn bản (console) đen trắng hay có màu thông thường thì đều được biểu diễn 25 dòng 80 cột.


>> Giáo Trình C++ Và Lập Trình Hướng Đối Tượng


[Đồ họa trong C\C++] Sử dụng các hàm đồ họa thông dụng trong C\C++ [C\C++]

Chế độ đồ hoạ màn hình được chia thành các điểm ảnh (pixel), bằng cách in từng điểm ảnh ta có thể vẽ hình bất kỳ. Màn hình VGA thông thường ở độ phân giải cao có 480 hàng và 640 cột điểm ảnh. Góc trên bên trái màn hình có toạ độ là (x,y)=(0,0), góc dưới bên phải màn hình có toạ độ là (x,y)=(639,479), trục x hướng sang phải, trục y hướng xuống dưới.


Để chạy đồ hoạ ta cần có tệp Egavga.bgi (tệp điều kiển màn hình VGA), các tệp Goth.chr, litt.chr, sans.chr, trip.chr (chứa các font chữ).
Trong màn hình hiển đồ luôn có một con trỏ vẽ, đó là nơi điểm ảnh được in ra nếu dùng lệnh putpixel, con trỏ vẽ không hiện lên màn hình như trong chế độ văn bản.

Thông thường chúng ta sử dụng đồ hoạ ở chế độ 16 màu.

Tài liệu bài giảng miễn phí


Các bước thực hiện:


1. Khởi động chế độ đồ hoạ.

* Khởi động chế độ đồ hoạ ta cần một số hàm sau :

- Hàm void initgraph(int *graphdriver, int *graphmode, char *s) dùng để khởi động chế độ đồ hoạ, trong đó s là đường dẫn tới tệp egavga.bgi, nếu s=””(rỗng) thì máy tự tìm tệp egavga.bgi trên thư mục chủ. 
Giá trị của graphdriver và graphmode được xác định trong bảng sau:
  + Nếu graphdriver=VGA (hay 9) thì giá trị của graphmode có thể là VGALO (hay 0) ứng với độ phân giải màn hình 640 x200 điểm ảnh, graphdriver=VGAHI (hay 2) ứng với độ phân giải 640 x 480 điểm ảnh.
  + Nếu graphdriver=DETECT (hay 0) thì trương trình tự tìm kiểu màn hình đang dùng và gán cho graphdriver, tự động xác định chế độ đồ hoạ có độ phân giải cao nhất gán cho graphmode.

- Hàm int graphresult(void) cho mã lỗi khi khởi động đồ hoạ hay dùng các hàm đồ hoạ. hàm cho giá trị bằng 0 tức là không có lỗi, cho giá trị khác không (mã lỗi) thì có lỗi.

- Hàm char *grapherrormsg(int k) cho lời giải thích bằng tiếng anh của lỗi đồ hoạ, có mã lỗi là k.

- Hàm void closegraph(void) dùng để đóng chế độ đồ hoạ.

* Cấu trúc chung của một chương trình đồ hoạ:
- Khởi động hệ thống đồ hoạ.
- Xác định màu nền (màu màn hình), màu nét vẽ, màu tô và kiểu tô (mẫu tô).
- Vẽ,tô màu các hình mà ta mong muốn.
- Các thao tác đồ hoạ khác như cho hiện chữ....
- Đóng hệ thống đồ hoạ trở về mode văn bản.

Vi dụ: Khởi động đồ hoạ nếu thành công thì vẽ một hình chữ nhật , ngược lại thông báo mã lỗi và tên lỗi bằng tiếng anh.

[Code Turbo C\C++]
#include <stdio.h>
#include <conio.h>
#include <graphics.h>
#include <stdlib.h>
void main()
{
   int gd=0,gm=0, maloi; // gd : graphdriver, gm: graphmode,
   initgraph(&gd,&gm,"C:/TC/BGI"); // khoi dong do hoa
if ( (maloi=graphresult()) != 0)
{
  printf("khong the khoi dong do hoa \n");
  printf("ma loi : %d \n",maloi);
  printf("nguyen nhan loi : %s",grapherrormsg(maloi));
  printf("\n an phim bat ky de thoat");
  getch();
  exit(1);
}
bar(1,1,100,100);
getch();
closegraph();
}

* Để thuận tiện cho việc lập trình đồ hoạ C\C++ cung cấp một số hàm thường dùng trong đồ hoạ như sau:

- Hàm int getmaxx(void) : cho toạ độ màn hình x lớn nhất của kiểu màn hình đang dùng.
- Hàm int getmaxy(void) : cho toạ độ màn hình y lớn nhất của kiểu màn hình đang dùng.
- Hàm int getmaxcolor(void): cho giá trị màu lớn nhất đang dùng.
- Hàm void setbkcolor(int color) : đặt màu nền, màu nền ngầm định ngay sau khi khởi động đồ hoạ sẽ là màu đen BLACK (0).
- Hàm int getbkcolor(void) : lấy màu nền hiện tại.
- Hàm void setcolor(int color ) : đặt màu nét vẽ. Màu ngầm định ngay khi khởi động là WHITE (15).
- Hàm int getcolor(void) : lấy màu vẽ hiện tại.
- Hàm void cleardevice(void) : xoá toàn bộ màn hình đồ hoạ (chức năng tương tự clrscr() trong chế độ mode văn bản).
- Hàm void restorecrtmode (void) : khôi phục lại chế độ màn hình như trước khi khởi động đồ hoạ.
- Hàm int getgraphmode(void) : lấy kiểu màn hình đồ hoạ hiện tại.
- Hàm void setgraphmode(int mode) : lựa chọn kiểu đồ hoạ khác với kiểu ngầm định đặt bởi initgraph, xoá màn hình.
- Hàm moveto(int x,int y) : di chuyển con trỏ vẽ tới toạ độ (x,y) trên màn hình.
- Hàm int getx(void) : cho toạ độ x của con trỏ vẽ hiện tại.
- Hàm int gety(void) : cho toạ độ y của con trỏ vẽ hiện tại.

Ví dụ: Đặt màu nền, màu vẽ, rồi lưu lại giá trị của màu nền, màu vẽ, lấy toạ độ max của kiểu màn hình đang dùng sau đó đóng đồ hoạ và in giá trị này.

[Code Turbo C\C++]
#include <stdio.h>
#include <conio.h>
#include <graphics.h>
#include <stdlib.h>
void main()
{
  int driver=0, mode = 0, maloi; /* driver để chế độ DETECT tự phát hiện kiểu màn hình đang dùng. */
 initgraph(&driver,&mode,"C:/TC/BGI"); /* khởi động đồ hoạ với tệp egavga.bgi ở thư mục            c:\tc\bgi. Nếu đặt là “” (xâu rỗng) thì tự tìm tệp này ở thư mục chứa tệp .c hay .cpp của chương trình */
if ( (maloi=graphresult()) !=0 ) // nếu không khởi động được đồ hoạ thì báo lỗi
{
   printf("khong the khoi dong do hoa \n");
   printf("ma loi : %d \nnguyen nhan loi %s ",maloi, grapherrormsg(maloi) );
   getch();
   exit(1);
}
setbkcolor(WHITE); // đặt màu nền là màu trắng ,có thể là setbkcolor(15)
setcolor(RED); // đặt màu vẽ là màu đỏ, có thể đặt setcolor (4);
line(10,10,100,100); // vẽ một đường thẳng
getch(); // tạm dừng màn hình đợi ấn phím bất kỳ
int bk=getbkcolor() , cl=getcolor(); // lưu giá trị màu nền và màu vẽ
int x=getmaxx(), y=getmaxy(); // lưu toạ độ lớn nhất của kiểu màn hình đang sử dụng
closegraph();
printf("getbkcolor = %d getcolor= %d",bk,cl);
printf("\ngetmaxx = %d getmaxy= %d",x,y);
getch();
}

2. Các hàm dùng vẽ điểm, đường và miền.
- Hàm void putpixel(int x, int y, int color) : tô điểm có toạ độ(x,y) trên màn hình theo màu color.
- Hàm int getpixel(int x, int y) : trả về màu của điểm ảnh tại vị trí có toạ độ (x,y).

Ví dụ: Vẽ bầu trời sao, dừng màn hình lấy giá trị màu tại điểm ảnh có toạ độ (100,100)

#include <stdio.h>
#include <conio.h>
#include <graphics.h>
#include <stdlib.h>
void main()
{
  int driver=0, mode = 0, maloi;
  initgraph(&driver,&mode,"C:/TC/BGI");
  if ( (maloi=graphresult()) !=0 )
  {
     printf("khong the khoi dong do hoa \n");
     printf("ma loi : &d \nnguyen nhan loi %s ",maloi, grapherrormsg(maloi) );
     getch();
     exit(1);
  }
  randomize(); // khởi tạo hàm radom (cho số ngẫu nhiên)
  int i=0;
  while (i<200)
  {
    putpixel(random(639), random(476), WHITE); /* random(639) tức là cho số ngẫu nhiên trong khoảng 0->639, vẽ một điểm có toạ độ x,y cho ngẫu nhiên với màu trắng */
    i++;
  }
  getch();
  int mau=getpixel(100,100); /* lấy màu của điểm ảnh trên màn hình tại vị trí có toạ độ (100,100) */
  closegraph();
  printf(“mau cua diem anh tai vi tri co toa do (100,100) la : %d”,mau);
  getch();
}

- Hàm void line(int x1,int y1,int x2,int y2) : vẽ đường thằng nối 2 điểm có toạ độ (x1,y1) và (x2,y2), sau khi vẽ xong con trỏ vẽ quay về vị trí cũ (không thay đổi vị trí)

- Hàm void lineto(int x,int y) : vẽ đường thẳng từ vị trí con trỏ vẽ hiện tại đến điểm có toạ độ (x,y),vẽ xong con trỏ tới điểm có toạ độ (x,y).

- Hàm void linerel(int dx, int dy) : vẽ đường thẳng từ vị trí con trỏ vẽ hiện tại (giả sử con trỏ vẽ hiện tại có toạ độ (x,y) ) đến điểm có toạ độ (x+dx , y+dy), vẽ xong con trỏ tới điểm mới.

- Hàm void setlinestyle(int kiểu, int mẫu, int độ_lớn) : quy định dạng, mẫu và độ lớn của nét vẽ
 + Kiểu có giá trị từ 0 đến 4 :
 + Độ_lớn xác định độ lớn của đường vẽ nó có hai giá trị : NORM_WIDTH (1) nét bình thường, THICK_WIDTH (2) nét vẽ to.
 + Mẫu sử dụng khi kiểu = 4 để tạo mẫu của đường vẽ theo ý người lập trình. 

Ví dụ: int mau=0x1111 ; setlinestyle(4,mau,1); line(1,0,100,100); giá trị của mau ở hệ 16 là 0x1111, hay trong hệ nhị phân là 0001 0001 0001 0001 (ứng với các bit 0 thì điểm ảnh không sáng, ứng với các bit 1 thì điểm ảnh sáng).

Với mẫu ở trên ta được một đường thằng gồm các chấm cách nhau liên tiếp 3px.
Nếu kiểu <4 thì mẫu phải bằng 0
Ví dụ: Mô phỏng vẽ đường thằng với mẫu tự tạo như ở trên, và mẫu mặc định.
[Code Turbo C\C++]

#include <conio.h>
#include <stdio.h>
#include <graphics.h>
#include <stdlib.h>
void main()
{
   int kieu=4, mau=0x1111, do_lon=1;
   int gd=0,gm=0,maloi;
   initgraph(&gd,&gm,"C:/TC/BGI");
   if ( (maloi=graphresult() ) != 0)
  {
     printf("ma loi : %d \nnguyen nhan loi : %s",maloi,grapherrormsg(maloi));
     getch();
     exit(1);
   }
   setlinestyle(3,0,1); // vẽ với mẫu có sẵn
   lineto(100,100);
   setlinestyle(kieu,mau,do_lon); // vẽ với mẫu tự tạo
   line(0,110, 200,200);
   setlinestyle(0,0,1); // vẽ đường thẳng với mẫu có sẵn
   linerel(300,200);
   getch();
   closegraph();
}

Một số hàm sau đây dùng để vẽ một số hình học quen thuộc với góc vẽ được xác định bởi gd và gc tức góc đầu đến góc cuối. Được quay theo chiều ngược chiều kim đồng hồ

- Hàm void arc(int x, int y, int gd, int gc, int r) : vẽ một cung tròn với tâm có toạ độ (x,y) , bán kính r, từ góc đầu tiên là gr đến góc cuối là gc (góc tính bằng độ). Màu của nét vẽ do hàm setcolor() đặt;

- Hàm void circle(int x, int y, int r) : vẽ đường tròn với tâm có toạ độ (x,y), bán kính r.

- Hàm ellipse(int x, int y, int gd, int gc, int rx, int ry) : vẽ một cũng ellipse với tâm là (x,y) từ góc đầu gd đến góc cuối gc, bán kính trục x là rx, bán kính trục y là ry.

- Hàm void rectangle(int x1, int y1, int x2, int y2) : vẽ một đường chữ nhật có đỉnh trên bên trái là (x1,y1) đỉnh dưới bên phải là (x2,y2).

- Hàm void setfillstyle(int mẫu, int màu) : đặt mẫu tô và màu tô cho các hình đặc và miền đóng.  +Màu có giá trị từ 0 đến 15 (xem lại ở bảng màu). 
 + Mẫu có giá trị từ 0 đến 12 được cho ở bảng dưới. Với mẫu có giá trị 12 thì tự thiết kế mẫu tô theo 8byte

- Hàm void pieslice(int x, int y, int gd, int gc, int r) : vẽ và tô màu một hình quạt có tâm là (x,y), bá kính r, từ góc đầu gd đến góc cuối gc.

- Hàm void sector(int x, int y, int gd, int gc, int rx, int ry) : vẽ và tô màu một mảnh ellipse có tâm là (x,y), từ góc đầu đến gd, đến góc cuối gc, có bán kính trục x là rx, bán kính trục y là ry.

- Hàm fillellipse(int x, int y, int rx, int ry) : hàm vẽ và tô màu một elip có tâm (x,y) và bán kính hai trục là rx, ry.

- Hàm void bar(int x1, int y1, int x2, int y2) vẽ và tô màu một hình chữ nhật.

- Hàm void bar3d(int x1, int y1, int x2, int y2, int depth, int top) : vẽ một khối hộp chữ nhật, màu vẽ xác định bởi hàm setcolor. Mặt trước có toạ độ góc trên trái là (x1,y1) góc dưới phải là (x2,y2), được tô màu bởi hàm setfillstyle. Chiều sâu của khối hộp là depth điểm. Nếu top =0 (TOPOFF) thì hộp không có lắp.

Ví dụ: minh hoạ sử dụng các hàm trên.

#include <stdio.h>
#include <conio.h>
#include <graphics.h>
#include <stdlib.h>
void main()
{
  int driver=0, mode = 0, maloi;
  initgraph(&driver,&mode,"C:/TC/BGI");
  if ( (maloi=graphresult()) !=0 )
  {
    printf("khong the khoi dong do hoa \n");
    printf("ma loi : %d \nnguyen nhan loi %s ",maloi, grapherrormsg(maloi) );
    getch();
    exit(1);
}
setcolor(WHITE); // đặt màu cho nét vẽ là màu trắng
arc(320,240,45,135,100); //vẽ một cung tròn với góc từ 450 đến 1350
getch(); // tạm dừng màn hình
cleardevice(); // xoá màn hình đồ hoạ
ellipse(320,240,0,360,150,110); /* vẽ một cung elip với góc vẽ từ 00 đến 3600 (vẽ một elip) */
getch();
cleardevice();
circle(320,240,160); // vẽ đường tròn
getch();
cleardevice();
rectangle(140,60,500,420); // vẽ đường chữ nhật
getch();
cleardevice();
setfillstyle(1,YELLOW); // đặt mẫu tô và màu tô cho những hàm có phần tô miền
pieslice(320,240,45,300,200); /*vẽ và tô màu một hình quạt với màu và mẫu tô được xác định bởi setfillstyle */
getch();
cleardevice();
for (int i=0; i<12; i++) // tô miền đóng với 12 mẫu tô khác nhau
{
   setfillstyle(i,getmaxcolor()); // kiểu tô dược thay lần lượt giá trị từ 0 -> 11
   sector(320,240,45,250,300,200); // vẽ và tô màu một mảnh elip
   getch();
}
cleardevice();
setfillstyle(1,LIGHTMAGENTA);
bar(20,260,300,460); // vẽ và tô màu một hình chữ nhật
bar3d(340,120,520,360,50,1); vẽ và tô màu một hình hộp
getch();
closegraph();
}

- Hàm void drawpoly(int n, int a[]) : vẽ đường gấp khúc qua n điểm
(x1, y1), (x2,y2), ... , (xn,yn). Trong đó a={x1,y1,x2,y2,....xn,yn}. Nếu điểm cuối cùng trùng với điểm đầu ta được đường gấp khúc khép kín.

- Hàm void fillpoly(int n, int a[]) vẽ và tô màu một đa giác có n đỉnh
(x1,y1), ( x2,y2) , ... , (xn,yn). Trong đó a={x1,y1,x2,y2,....xn,yn}.

- Hàm floodfill(int x, int y, int màu_biên) : tô màu một miền kín trên màn hình được bao quanh bởi một đường có màu là màu_biên, (x,y) là một điểm tuỳ ý ở bên trong miền kín. Màu tô và mẫu tô xác định bởi hàm setfillstyle. Nếu (x,y) nằm ngoài miền kín thì vùng ngoài miền kín được tô. Nếu trên màn hình không có miền kín như đã chỉ thì cả màn hình được tô màu.

Ví dụ: vẽ đường gấp khúc , đường gấp khúc khép kín và sử dụng floodfill để tô kín miền kín vừa vẽ, sử dụng fillpoly để vẽ và tô đa giác với 12 mẫu tô khác nhau.

#include <stdio.h>
#include <conio.h>
#include <graphics.h>
#include <stdlib.h>
void main()
{
  int driver=0, mode = 0, maloi;
  initgraph(&driver,&mode,"C:/TC/BGI");
  if ( (maloi=graphresult()) !=0 )
 {
   printf("khong the khoi dong do hoa \n");
   printf("ma loi : %d \nnguyen nhan loi %s ",maloi, grapherrormsg(maloi) );
   getch();
   exit(1);
}
int p1[10]={20,240,620,20,490,460,320,440,70,240};
int p2[8]={20,240,620,20,590,460,320,240};
int p3[10]={20,240,620,20,490,460,320,440,20,240};
setcolor(5); // đặt màu vẽ là 5
drawpoly(5,p1); // vẽ một đường gấp khúc
getch();
cleardevice();
setfillstyle(1,BLUE); // đặt kiểu tô và màu tô
drawpoly(5,p3); // vẽ đường gấp khúc kín
floodfill(22,240,5); // tô kín đường gấp khúc kín vẽ ở trên
getch();
cleardevice();
setcolor(LIGHTCYAN); // đặt lại màu vẽ mới

for(int i=0; i< 12; i++)
{ setfillstyle(i, 3); //đặt lần lượt 12 kiểu tô khác nhau
   fillpoly(4,p2); /*vẽ và tô kín đa giác với kiểu tô và màu tô được xác định bởi setfillstyle */
   getch();
}
closegraph();
}

3. Cửa sổ trong chế độ đồ hoạ.

Thông thường khi khởi động chế độ đồ hoạ với màn hình VGA ta được độ phân giải 640x480, đó gọi là cửa sổ đồ hoạ gốc được tạo đầu tiên. C\C++ cung cấp thêm một số hàm để tạo thêm các cửa số con khác nằm trong cửa số chính này và cửa số con được ưu tiên hơn cửa sổ chính.


Cửa sổ chính 1, còn các cửa sổ con nằm ở trong 

Để xác định một cửa sổ ta sử dụng 2 hàm sau:
- Hàm void setviewport(int x1, int y1, int x2, int y2, int clip) : tạo một cửa sổ có góc trên bên trái(x1,y1), góc dưới bên phải là (x2,y2). Nếu clip =1 thì không cho phép vẽ ra ngoài cửa sổ. Nếu clip =0 thì cho phép vẽ ra ngoài cửa sổ (ta thường dùng để lập hệ toạ độ âm dương của toán học trên màn hình). Sau khi vẽ cửa số con trỏ ở toạ độ (0,0) của cửa số hiện hành. Sau khi khởi động đồ hoạ cửa sổ ngầm định là (0,0,639,479,clip).

- Hàm void clearviewport(void) : xoá tất cả những gì có trong cửa sổ.


#include <stdio.h>
#include <conio.h>
#include <graphics.h>
#include <stdlib.h>
void main()
{ int driver=0, mode = 0, maloi;
initgraph(&driver,&mode,"C:/TC/BGI");
if ( (maloi=graphresult()) !=0 )
{
printf("khong the khoi dong do hoa \n");
printf("ma loi : %d \nnguyen nhan loi %s ",maloi, grapherrormsg(maloi) );
getch();
exit(1);
}
setbkcolor(WHITE); // đặt màu nền cho cửa sổ mặc định
setviewport(50,50,200,200,1); // tạo một cửa sổ mới
setfillstyle(1,BLUE); // đặt kiểu và màu tô
floodfill(51,51,WHITE); // tô kín cửa sổ mới
setcolor(RED); // đặt màu vẽ mới
line(100,100,350,100); // vẽ đường nằm ngang trên cửa sổ mới
getch();
clearviewport(); // xoá toàn bộ những gì có trong cửa sổ hiện hành
line(100,100,350,300); // vẽ một đường thẳng khác trên cửa sổ hiện hành
getch();
closegraph();
}


Yêu cầu thay đổi thông số clip từ 1 sang 0 để thấy rõ việc tạo cửa sổ mới và khi vẽ trên cửa sổ.

- Hàm void getviewsettings( struct viewporttype *p) : lấy thông tin về cửa sổ hiện hành, kiểu viewporttype được định nghĩa trong thư viện graphics như sau:

Struct viewporttype {
   Int left; int top; int right; int bottom; int clip;
} ;

Ví dụ: lấy và in thông tin về cửa sổ hiện tại


#include <stdio.h>
#include <conio.h>
#include <graphics.h>
#include <stdlib.h>
void main()
{ int driver=0, mode = 0, maloi;
initgraph(&driver,&mode,"C:/TC/BGI");
if ( (maloi=graphresult()) !=0 )
{
printf("khong the khoi dong do hoa \n");
printf("ma loi : %d \nnguyen nhan loi %s ",maloi, grapherrormsg(maloi) );
getch();
exit(1);
}
struct viewporttype p1,p2;
getviewsettings(&p1); // lấy thông tin về cửa sổ mặc định khi khởi động đồ hoạ
setviewport(10,10,300,200,0); // tạo mới một cửa sổ
getviewsettings(&p2); // lấy thông tin của cửa sổ vừa tạo mới
closegraph();
printf("thong tin cua man hinh khi bat dau khoi dong do hoa\n");
printf("(%d,%d) la goc tren ben trai cua so \n",p1.left,p1.top);
printf("(%d,%d) la goc duoi ben phai cua so\n",p1.right,p1.bottom);
printf("thong so clip la %d",p1.clip);
printf("\n\n thong tin cua so moi duoc tao ra \n");
printf("(%d,%d) la goc tren ben trai cua so \n",p2.left,p2.top);
printf("(%d,%d) la goc duoi ben phai cua so\n",p2.right,p2.bottom);
printf("thong so clip la %d",p2.clip);
getch();
}

4. Viết chữ trong đồ hoạ.
Để viết chữ trong chế độ đồ hoạ thì trước tiên ta phải chọn font chữ, cỡ chữ, hướng in, căn chỉnh chiều dọc hay ngang đối với điểm in.

- Hàm void settextstyle(int phông, int hướng, int cỡ) : hàm thiết đặt font chữ, hướng in, cỡ chữ.
 + Tham số phông quy định font chữ, các giá trị sau:
 + Tham số hướng quy định hướng in, nhận các giá trị
HORIZ_DIR (0) : in ngang (giá trị ngầm định).
VERT_DIR (1) : in dọc.
 + Tham số cỡ quy định cỡ chữ, có giá trị từ 1 đến 10 (to nhất).

- Hàm void settextjustify(int ngang, int dọc) : quy định nơi hiển thị văn bản của outtextxy theo quan hệ với toạ độ (x,y), của outtext theo quan hệ với vị trí hiện tại của con trỏ (giả sử (x,y)).
 + Tham số ngang có giá trị
 + Tham số dọc có các giá trị
 Hàm outtextxy(int x, int y, char *s) : in xâu s theo vị trí (x,y).

Ví dụ: settextstyle(0,0,3) ; settextjustify(1,1) ; outtext (230,230, “Bac Ninh Que Toi”);

- Hàm void outtext(char *s) : in xâu s theo vị trí hiện tại của con trỏ vẽ.
- Hàm int texthight(char *s) : trả về chiều cao theo pixel của xâu s.
- Hàm int textwidth(char *s) : trả về bề rộng của xâu s.
- Hàm sprintf(char *s, char *xâu_điều_khiển, danh_sách_các_biến); làm việc giống hàm printf nhưng không in ra màn hình mà cho kết quả vào xâu s. Hàm này được khai trong thư viện stdio.h
Ví dụ int n=5; char s[200];
Sprintf(s,“bien n co gia tri la %d”,n);
Sau khi thực hiện lệnh trên xâu s được kết quả là “bien n co gia tri la 5”

Ví dụ minh hoạ in chữ ra màn hình

#include <stdio.h>
#include <conio.h>
#include <graphics.h>
#include <stdlib.h>
void main()
{ int driver=0, mode = 0, maloi;
initgraph(&driver,&mode,"C:/TC/BGI");
if ( (maloi=graphresult()) !=0 )
{
printf("khong the khoi dong do hoa \n");
printf("ma loi : %d \nnguyen nhan loi %s ",maloi, grapherrormsg(maloi) );
getch();
exit(1);
}
setcolor(GREEN);
for (int i=0; i<=4; i++ )
{settextstyle(i,0,1); // đặt font chữ thay đổi từ 0 đến 4, hướng in là ngang cỡ 1
outtextxy(100,230,"Nguyen Ba Cuong - Cong Nghe Phan Mem"); /* in xâu tại vị trí bắt đầu là (100,230) */
getch();
cleardevice();
}
settextstyle(3,1,1); // thay đổi font và hướng in (hướng dọc)
outtext("Nguyen Ba Cuong - Cong Nghe Phan Mem"); // in tại vị trí con trỏ vẽ hiện hành
getch();
closegraph();
}

5. Tạo hình ảnh chuyển động.

- Hàm unsigned imagesize(int x1,int y1, int x2, int y2) cho số byte cần thiết để lưu ảnh trong phạm vi hình chữ nhật (x1,y1,x2,y2).

- Hàm void getimage(int x1, int y1, int x2, int y2, void *p): chép các điểm ảnh trong vùng chữ nhật (x1,y1,x2,y2) vào vùng nhớ do con trỏ p trỏ tới (vùng nhớ này và con trỏ p cho bởi hàm malloc, độ lớn vùng nhớ cho bởi hàm imagesize).

- Hàm void putimage(int x, int y, void *p, int kiểu_chép): chép ảnh tử vùng nhớ do con trỏ p trỏ tới ra màn hình sao cho góc trên trái vùng ảnh có toạ độ (x,y). Giá trị của kiểu chép được cho trong bảng sau :

a. Tạo ảnh chuyển động không có màn hình nền

B1- Tạo ảnh bằng màu vẽ.
B2- xoá ảnh bằng màu nền.
B3- tạo lại ảnh bằng màu vẽ tại vị trí mới.

Ví dụ : cho quả bóng chuyển động ngang trên màn hình, hết chiều ngang màn hình bóng quay lại.


#include <stdio.h>
#include <conio.h>
#include <graphics.h>
#include <stdlib.h>
#include <dos.h>
void bong(int x, int y, int r, int mau)
{ setcolor(mau);
setfillstyle(1,mau);
pieslice(x,y,0,360,r);
}
void main()
{ int driver=0, mode = 0, maloi;
initgraph(&driver,&mode,"C:/TC/BGI");
if ( (maloi=graphresult()) !=0 )
{
printf("khong the khoi dong do hoa \n");
printf("ma loi : %d \nnguyen nhan loi %s ",maloi, grapherrormsg(maloi) );
getch();
exit(1);
}
setbkcolor(CYAN);
int x=30,y=100;
do
{
if (x>=640-30) x=50;
bong(x,y,30,CYAN);
x+=4;
bong(x,y,30,RED);
delay(200); // tạm dừng 200 mili giây (hàm này trong thư viện dos.h)
}while (!kbhit()); // lặp vô hạn tới khi ấn một phím bất kỳ thì dừng
getch();
closegraph();
}

b. Tạo ảnh chuyển động mà không xoá màn hình nền.

Vẽ ảnh trong vùng chữ nhật (x1,y1,x2,y2), dùng hàm imagesize tính số byte càn thiết để lưu ảnh trong vùng chữ nhật vừa vẽ (giả sử là n byte), dùng hàm malloc để cấp phát vùng nhớ n byte và cho con trỏ p trỏ và vùng nhớ này, dùng hàm getimage chép ảnh từ vùng chữ nhật vào vùng nhớ p, xoá màn hình, tạo màn hình nền, dùng lệnh putimage với kiểu chép XOR_PUT để in ảnh lưu trong P ra màn hình với toạ đọ góc trên bên trái là(x,y),tạm dừng chương trình một lát, dùng putimage với kiểu chép XOR_PUT in lại ảnh lưu trong P ra màn hình cũng tại (x,y) để xoá ảnh cũ (vì 1 xor 1 cho 0), thay đổi các thành phần của toạ độ (x,y) in ảnh tai toạ độ mới...

Ví dụ: Vẽ quả bóng màu đỏ và nhớ vào vùng nhớ p, xoá màn hình, vẽ bầu trời sao, cho quả bóng chuyển động ngẫu nhiên trên màn hình đến khi ấn một phím bất kỳ.

#include <stdio.h>
#include <conio.h>
#include <graphics.h>
#include <stdlib.h>
#include <dos.h>
void bong(int x, int y, int r, int mau)
{
  setcolor(mau);
  setfillstyle(1,mau);
  pieslice(x,y,0,360,r);
}
void main()
{
int driver=0, mode = 0, maloi;
initgraph(&driver,&mode,"C:/TC/BGI");
if ( (maloi=graphresult()) !=0 )
{
  printf("khong the khoi dong do hoa \n");
  printf("ma loi : %d \nnguyen nhan loi %s ",maloi, grapherrormsg(maloi) );
  getch();
  exit(1);
}
setcolor(RED);
setfillstyle(1,RED);
pieslice(50,50,0,360,50);
char *p;
int n= imagesize(0,0,100,100);
p=(char *)malloc(n);
getimage(0,0,100,100,p);
getch();
cleardevice();
randomize();
for (int i=0;i<=300; i++)
{
  int k=random(16);
  setcolor(k);
  setfillstyle(1,k);
  pieslice(random(640), random(480), 0,360,2);
}
int x=random(640-100), y=random(480-100),x1,y1;
do{
  putimage(x,y,p,1); /* in bóng màu đỏ với phép XOR (vẽ bóng trên màn hình chỗ nào đã có màu lần trước thì màu đó được in đè lên bóng do ta sử dụng xor); */
  delay(100); // tạm dừng
  putimage(x,y,p,1); /* in với phép XOR một lần nữa (xoá bóng vừa in trên màn hình do bóng lần trước in là màu đỏ lại in lại màu đỏ nhưng theo phép xor thì 1 XOR 1 =0 tức là 2 màu đỏ đè lên nhau sẽ ra màu nền cũ trước đó) */
  do{ /* mục đích của vòng do while này nhằm không cho quả bóng hiển thị ngoài vùng màn hình (0,0,540,340) và tạo giá trị toạ độ ngẫu nhiên mới cho bóng */
  x1 =x+random(50) -25;
  y1 =y+random(50) -25;
 } while ( (x1<0) || ( x1> (639-100) ) || (y1<0) || (y1>(439-100) ) ) ;

x=x1;
y=y1;
}while(!kbhit()) ;
getch();
closegraph();
}


Categories

AI (13) AI programming (1) ASP (1) Android (32) App Honeygain (4) Assembly (17) Biểu diễn thuật toán (1) Bubble-Sort (1) Bài giảng (2) Bài giảng lập trình C và Cpp (21) Bài viết hay (108) Bản đồ tư duy (1) C Plus Plus (103) C/C++ (16) CDSL phân tán (1) CSS (2) Cơ sở dữ liệu (11) Danh ngôn lập trình (1) Datamining (4) Genetic Algorithm (1) Giáo trình (2) Giải thuật tiến hóa - thuật toán di truyền (2) Google App Engine (2) Góc học tập (34) HTML (1) Hướng dẫn kiếm tiền online tại nhà (6) Hướng dẫn sử dụng Emu8086 (1) Học lập trình (131) Học lập trình C và CPP qua ví dụ (17) Java (54) Java Căn bản (6) JavaScript (5) Kỹ năng đọc hiệu quả (1) Kỹ thuật lập trình (16) Kỹ thuật đồ họa máy tính (10) Lý thuyết Cơ sở dữ liệu (2) Lý thuyết đồ thị (11) Lập trình Cơ sở dữ liệu (2) Lập trình Python (2) Lập trình căn bản (8) Lập trình hướng đối tượng với Java (7) Lập trình mobile (9) Lập trình mạng (6) Lập trình nhúng (1) Lập trình trí tuệ nhân tạo (2) ML (1) MMO (6) MS Access (1) Machine learning (2) Mạng máy tính (1) Mẹo tìm kiếm trên Google (1) Nghiên cứu khoa học (3) Ngôn ngữ lập trình (2) Những cuốn sách hay mà bạn nên đọc khi còn trẻ (1) Pascal (3) Phương pháp tính toán tối ưu (2) Phương pháp tối ưu (2) Quản lý dự án CNTT (1) SEO (1) SQL (5) Swift (9) Sách hay (4) Thiết kế Web (2) Thuật toán (51) Thuật toán Sắp Xếp -Sort (9) Thuật toán Tìm kiếm - Search (5) Thuật toán di truyền (4) Thực hành Android (2) Tin học văn phòng (5) Tiện ích máy tính (3) Toán rời rạc (13) Treo máy kiếm tiền (3) Trí tuệ nhân tạo (18) Tài liệu tham khảo (5) Tìm hiểu Blockchain (2) Tự học Android (3) Tự học Android qua ví dụ (1) Tự học JavaScript (1) Tự học lập trình (9) Tự học lập trình Android (17) Tự học lập trình C và CPP (14) Tự học lập trình java qua các ví dụ (8) XML (1) blockchain (2) bài giảng quản lý dự án CNTT (1) bài tập java (3) bài tập lập trình (4) cấu trúc dữ liệu giải thuật (15) hướng dẫn viết báo (1) học lập trình Java (11) học máy (5) hợp ngữ (8) lập trình viên (3) phưng pháp đơn hình (2) thuật toán AI (2) tài liệu CNTT miễn phí (4) tính toán tối ưu (1) tự học lập trình iOS (8) tự học lập trình python (1) ví dụ Assembly (1) Đại số gia tử và ứng dụng (1) Đồ họa (4)