Học Pascal

ĐỒ HỌA PASCAL

I. MÀN HÌNH TRONG CHẾ ĐỘ ĐỒ HỌA ( GRAPHIC)

Hình ảnh trong chế độ đồ họa được tạo ra bằng các điểm ảnh (Pixel), số điểm ảnh của màn hình đồ họa tùy thuộc vào từng loại CARD màn hình và MODE qui định cho màn hình đó.

Việc lập trình trong chế độ đồ họa cần phải xác định được loại màn hình đang sử dụng và chương trình phải vận hành được trên nhiều loại màn hình khác nhau.

Tọa độ của một điểm ảnh trên màn hình đồ họa cũng giống như trong chế độ văn bản (TEXT) với điểm ảnh đầu tiên trên góc trái màn hình là (0,0), tọa độ đỉnh dưới phải tùy thuộc vào độ phân giải của màn hình, CARD màn hình và MODE màn hình.

Tọa độ màn hình PascalĐể dử dụng được chế độ đồ họa trên màn hình, ta cần phải có các File sau:

GRAPH.TPU Chứa các lệnh đồ họa

* .BGI                                     Chứa Font màn hình

* .CHR                                               Chứa Font ký tư

II. KHỞI TẠO VÀ THOÁT KHỎI CHẾ ĐỘ ĐỒ HỌA

2.1. Khởi tạo chế độ đồ họa

Thủ tục INITGRAPH(Gd,Gm:Integer; Path:String);

trong đó:

- Gd: Chỉ CARD màn hình.

Thông thường, một chương trình phải được chạy trên nhiều loại màn hình khác nhau nên ta có thể khai báo:

Gd = Detect               ( = 0 )

Với hằng Detect, máy sẽ tự động tìm CARD màn hình tương ứng để chạy chương trình.

- Gm: Chỉ MODE màn hình.

Trong trường hợp khai báo Gd = Detect thì không cần thiết phải khai báo Gm vì máy tính sẽ tự xác định loại CARD màn hình và thiết lập chế độ MODE màn hình tương ứng với CARD màn hình đó.

- Path: Đường dẫn đến nơi chứa các file *.BGI. Nếu Path = ‘’ thì ta hiểu là các file *.BGI nằm trong thư mục hiện hành.

Hàm GRAPHRESULT:Integer;

Hàm này trả về kết quả của việc khởi động đồ họa.

=  0 : Thành công.

<>0 : Bị lỗi.

Tên của lỗi được xác định bởi hàm GRAPHERRORMSG(Er:Integer):String;

Hàm này cho ra một xâu ký tự thông báo lỗi của đồ họa xác định bởi đối số Er.

* Hằng số GrOK = 0: Việc khởi động đồ họa có lỗi.

Ví dụ:

Uses Graph;
Procedure ThietLapDoHoa;
var gd,gm,Gr:integer;
Begin
DetectGraph(Gd,Gm);
InitGraph(gd,gm,'C:\TP\BGI');
Gr:=GraphResult;
If Gr&lt;&gt;GrOK then
Begin
writeln('Loi Do hoa: ',GraphErrorMsg(Gr));
Halt(1);
End;
End;
BEGIN
ThietLapDoHoa;
. . .
END.

Chú ý: Ta có thể khởi tạo mode đồ hoạ với chế độ 256 màu bằng cách sử dụng hàm InstallUserDriver(Name:String;Ptr:Pointer):Integer; với điều kiện trên đĩa phải có file SVGA256.BGI.

Procedure ThietLapDoHoa;
var gd,gm,Gr:integer;
Begin
Gd:= InstallUserDriver(‘SVGA256’,NIL);
Gm:=2; {Mode 640x480x256}
InitGraph(gd,gm,'C:\TP\BGI');
End;

2.2. Thoát khỏi chế độ đồ họa

Thủ tục  CLOSEGRAPH;

Sau đây là cấu trúc chung của một chương trình đồ họa:.

Uses Crt,Graph;
Procedure ThietLapDoHoa;
var gd,gm,Gr:integer;
Begin
DetectGraph(Gd,Gm);
InitGraph(gd,gm,'C:\TP\BGI');
Gr:=GraphResult;
If Gr&lt;&gt;GrOK then
Begin
writeln('Loi Do hoa: ',GraphErrorMsg(Gr));
Halt(1);
End;
End;
BEGIN
ThietLapDoHoa;
. . .
CloseGraph;
END.

III. TỌA ĐỘ VÀ CON TRỎ TRÊN MÀN HÌNH ĐỒ HỌA

3.1. Hàm GetMaxX:Integer;

Cho tọa độ cột lớn nhất của màn hình.

3.2. Hàm GetMaxY:Integer;

Cho tọa độ dòng lớn nhất của màn hình.

3.3. Thủ tục MOVETO(x,y:Integer);

Di chuyển con trỏ từ vị trí đang đứng đến tọa độ (x,y).

3.4. Thủ tục MOVEREL(dx,dy:Integer);

Di chuyển con trỏ từ vị trí đang đứng đến tọa độ mới cách tọa độ cũ khoảng cách là dx, dy.

3.5. Vẽ một điểm trên màn hình:

Dùng thủ tục PUTPIXEL(x,y:Integer; color:Word);

3.6. Lấy màu của một điểm tại tọa độ x,y:

Hàm GETPIXEL(x,y:Integer):Word;

IV. ĐẶT MÀU TRÊN MÀN HÌNH ĐỒ HỌA

4.1. Đặt màu cho đối tượng cần vẽ

Dùng thủ tục SETCOLOR(Color:Byte);

4.2. Đặt màu nền

Dùng thủ tục SETBKCOLOR(Color:Byte);

V. CỬA SỔ TRONG CHẾ ĐỘ ĐỒ HỌA

5.1. Đặt cửa sổ trên màn hình

Thủ tục SETVIEWPORT(x1,y1,x2,y2:Integer; Clip:Boolean);

Với x1,y1: đỉnh trên trái của cửa sổ.

x2,y2: đỉnh dưới phải của cửa sổ.

Clip = TRUE: những gì vượt khỏi màn hình sẽ bị cắt bỏ.

Clip = FALSE: những gì vượt khỏi màn hình sẽ không bị cắt bỏ.

* Khi tạo cửa sổ thì tọa độ trên màn hình sẽ thay đổi theo.

Tọa độ mới = Tọa độ cũ – Tọa độ đỉnh trên trái.

5.2. Xóa hình ảnh trong cửa sổ

- Xóa hình ảnh trong cửa sổ, ta dùng thủ tục CLEARVIEWPORT;

- Xóa toàn bộ màn hình, ta dùng thủ tục CLEARDEVICE;

VI. VIẾT CHỮ TRONG CHẾ ĐỘ ĐỒ HỌA

6.1. Chọn Font chữ

Ta dùng thủ tục SETTEXTSTYLE(font,Dir,size:Word);

- Các font có thể chứa các hằng sau:

DefaultFont = 0;        TriplexFont = 1;        SmallFont = 2;

SansSerifFont = 3;                GothicFont = 4;

- Dir có các hằng sau:

HorizDir = 0  Từ trái qua phải.

VetDir = 1      Từ dưới lên trên.

- Size: độ lớn của chữ.

6.2. Chọn phân bố chữ

Dùng thủ tục SETTEXTJUSTIFY(Hz,Vt:Word);

Chọn vị trí của chữ xung quanh tọa độ định sẵn.

- Hz là phân bố chữ theo trục ngang. Có các hằng sau:

LeftText = 0   Chữ viết nằm bên phải trục đứng.

CenterText = 1          Chữ viết nằm ở giữa trục đứng.

RightText = 2 Chữ viết nằm bên trái trục đứng.

- Vt là bố trí chữ theo hướng dọc đối với tọa độ qui định xuất chuỗi. Các hằng liên quan:

BottomText = 0         Chữ viết nằm bên trên trục ngang.

CenterText = 1          Chữ viết nằm ở giữa trục ngang.

TopText = 2               Chữ viết nằm bên dưới trục ngang.

6.3. Viết một xâu ký tự lên màn hình

- Xuất một xâu ký tự tại vị trí con trỏ:

Dùng thủ tục OUTTEXT(St:String);

- Xuất một xâu ký tự tại tọa độ x,y:

Dùng thủ tục OUTTEXTXY(x,y:Word; St:String);

Chú ý: Cách xuất chuỗi của hai thủ tục trên được qui định trong thủ tục SETTEXTJUSTIFY và SETTEXTSTYLE.

VII. VẼ CÁC HÌNH CƠ BẢN

7.1. Chọn kiểu đường

Dùng thủ tục SETLINESTYLE(Ls,Pt,Tk:Word);

Thủ tục này xác định kiểu đường được vẽ trong đồ họa.

Ls: kiểu đường vẽ. Ls có các giá trị sau:

0: Đường liền nét

1: Nét đứt

2: Nét chấm gạch

3: Nét gạch

4: Đường do người thiết kế tạo ra.

Pt: xác định màu vẽ.

. Nếu Ls = 0..3 thì Pt=0 (Lấy giá trị Default)

. Nếu Ls = 4 thì Pt là số nguyên chỉ màu của kiểu đường.

Tk: xác định độ dày của đường.

Tk = 1: bình thường.

Tk = 3: đậm nét.

7.2. Vẽ đoạn thẳng

LINE(x1,y1,x2,y2:Integer); vẽ từ điểm (x1,y1) đến điểm (x2,y2)

LINETO(x,y:Integer); vẽ từ vị trí con trỏ đến điểm (x,y)

LINEREL(dx,dy:Integer); vẽ từ vị trí con trỏ đến điểm cách đó một khoảng dx,dy.

7.3. Vẽ hình chữ nhật

Dùng thủ tục RECTANGLE(x1,y1,x2,y2:Integer);

7.4. Vẽ cung tròn

Thủ tục ARC(x,y:Integer; g1,g2,R:Word);

Vẽ cung tròn có tâm (x,y) bán kính R, góc bắt đầu là g1 và góc kết thúc là g2.

7.5. Vẽ đường tròn – Ellip

Thủ tục vẽ đường tròn: CIRCLE(x,y:Integer; R:Word);

Thủ tục ELLIPSE(x,y:integer; g1,g2,Rx,Ry:Word);

Vẽ Ellip có tâm (x,y) bán kính ngang Rx, bán kính dọc Ry, góc bắt đầu là g1 và góc kết thúc là g2.

7.6. Định MODE đường vẽ

Thủ tục SETWRITEMODE(Mode:Integer);

- Định Mode vẽ cho các đường thẳng.

- Ta có thể chọn Mode bằng các hằng:

CopyPut = 0;  XORPut = 1;

Trong đó:

. CopyPut là Mode chèn, đường mới sẽ không xóa đường cũ.

. XORPut là Mode xóa, đường mới sẽ xóa đường cũ.

XIII. TÔ MÀU CÁC HÌNH

8.1. Chọn kiểu tô

Thủ tục SETFILLSTYLE(Pt,Cl:Word);

Với:

- Pt: Mẫu tô của hình. Có các hằng từ 0 đến 12.

0: Tô bằng màu nền.

1: Tô bằng màu viền.

2: Tô bằng các dấu —

……………………………..

- Cl: Màu tô của hình.

8.2. Vẽ hình chữ nhật có tô màu ở bên trong

Thủ tục BAR(x1,y1,x2,y2:Integer);

Vẽ hình chữ nhật có tô màu và mẫu tô được xác định bởi thủ tục SETFILLSTYLE.

8.3. Vẽ hình hộp chữ nhật

Thủ tục BAR3D(x1,y1,x2,y2,Dh:Word; Top:Boolean);

Vẽ hình hộp chữ nhật có tọa độ đỉnh trên là (x1,y1), đỉnh dưới là (x2,y2) và chiều dày là Dh.

Vẽ hình hộp chữ nhật đồ họa Pascal

Top = TRUE: Hình hộp có nắp.

Top = FALSE: Hình hộp không có nắp.

8.4.Vẽ hình Ellip

Thủ tục FILLELLIPSE(x,y:Integer; Rx,Ry:Word);

8.5. Vẽ hình quạt tròn

Thủ tục PIESLICE(x,y:Integer; g1,g2,R:Word);

Vẽ hình quạt tròn có tâm (x,y), góc đầu g1, góc cuối g2, bán kính R.

8.6. Vẽ hình quạt Ellip

thủ tục SECTOR(x,y:Integer; g1,g2,Rx,Ry:Word);

8.7. Làm loang màu một vùng kín

Thủ tục FLOODFILL(x,y:Integer; Color:Word);

Trong đó:

(x,y): điểm nằm trong vùng kín.

Color: màu muốn tô.

8.8. Vẽ đa giác

Đối với một đa giác bất kỳ có N đỉnh, ta phải khai báo N+1 đỉnh để vẽ đường gấp khúc với tọa độ điểm đầu trùng với tọa độ điểm cuối.

Để vẽ đa giác ta dùng thủ tục:           DRAWPOLY(Np:Word; Var P);

trong đó:

  • Np: số đỉnh của đa giác + 1
  • P: chứa tọa độ các đỉnh, là một mảng có Np thành phần có kiểu dữ liệu là PointType được định nghĩa trong Unit Graph như sau:

TYPE           PointType = Record

x,y: Integer;

End;

IX. CÁC KỸ THUẬT TẠO HÌNH CHUYỂN ĐỘNG

9.1. Kỹ thuật lật trang màn hình

CARD màn hình có nhiều trang, mỗi trang được đánh số 0,1,2,…

Để vẽ hình lên một trang màn hình, ta dùng thủ tục:

SETACTIVEPAGE(Page:Word);

Trong đó, Page là số của trang màn hình. Thủ tục này được đặt trước khi có lệnh vẽ lên màn hình.

Để đưa trang màn hình ra màn hình, ta dùng thủ tục:

SETVISUALPAGE(Page:Word);

Page: trang màn hình muốn xem.

Thông thường, màn hình sẽ làm việc và hiện ra trên trang 0. Do đó, để vừa xem màn hình vừa vẽ lên trang màn hình khác, ta thường dùng hai thủ tục trên đi kèm với nhau.

Để thực hiện tự động chương trình khi sử dụng cú pháp lật hình này, ta thường theo một giải thuật sau:

  • Tạo biến page1,page2:Word;
  • Tạo vòng lặp

Repeat

SetVisualPage(page1); (* Xem trang màn hình page1 *)

SetActivePage(page2); (* Vẽ hình lên trang page2 *)

…….

< Các thủ tục vẽ hình >

…….

(* Hoán vị 2 biến page1, page2 *)

Temp:=page1;

page1:=page2;

page2:=Temp;

Until <Điều kiện thoát>;

9.2. Lưu và di chuyển một vùng màn hình

Chúng ta có thể lưu một vùng màn hình vào bộ nhớ rồi sau đó lại dán nó lên màn hình tại một vị trí khác.

Lưu một vùng màn hình vào bộ nhớ được thực hiện bằng thủ tục:

GETIMAGE(x1,y1,x2,y2:Integer; Var P:Pointer);

trong đó P là con trỏ để lưu nội dung của vùng (x1,y1,x2,y2).

Việc đăng ký một vùng nhớ động phải được khai báo dung lượng cần thiết. Dung lượng vùng nhớ được thực hiện bằng hàm:

IMAGESIZE(x1,y1,x2,y2:Integer):Word;

Để hiện hình ảnh từ bộ nhớ ra màn hình, ta dùng thủ tục:

PUTIMAGE(x,y:Integer; P:Pointer; Mode:Word);

trong đó:

(x,y): Tọa độ đỉnh trái hình chữ nhật mà ta muốn đưa ra.

P  : Con trỏ lưu vùng hình chữ nhật.

Mode: Hằng số chỉ phương thức hiện ra màn hình. Mode chứa một trong các hằng sau:

NormalPut = 0: Xuất ra như đã lưu (phép MOV)

XORPut = 1: Phép XOR, xóa hình cũ nếu hai hình giao nhau.

ORPut = 2: Phép OR, lấy cả hai hình nếu hai hình giao nhau.

ANDPut = 3: Phép AND, nếu hai hình giao nhau thì lấy phần chung.

NOTPut = 4: Phép NOT, cho ra âm bản.

Về việc thực hiện ta tiến hành như sau:

  • Khai báo một biến con trỏ P:Pointer;
  • Đăng ký một vùng nhớ động do P qủan lý bằng thủ tục

GETMEM(P,ImageSize(x1,y1,x2,y2));

  • Lưu hình ảnh bằng thủ tục GETIMAGE(x1,y1,x2,y2,P^);
  • Xuất ra màn hình bằng thủ tục PUTIMAGE(x,y,P^,Mode);

BÀI TẬP MẪU

Bài tập 10.1: Viết dòng chữ có bóng trong chế độ 256 màu.

Uses crt,Graph;
var gd,gm:integer;
Procedure WriteStr(dx,dy:Integer;st:String);
Var i,j:Integer;
Begin
settextstyle(5,0,8);
j:=16;
(* Viet chu bong *)
for i:=0 to 15 do
begin
setcolor(j);
outtextxy(dx+i,dy+i,st);
inc(j);
end;
setcolor(40);
outtextxy(dx+i,dy+i,st);
End;
Begin
gd:=INSTALLUSERDRIVER('SVGA256',NIL);
GM:=4;
initgraph(gd,gm,'c:\bp\BGI');
WriteStr(1,100,' Pham Anh Phuong');
readln;
CloseGraph;
End.

Bài tập 10.2: Vẽ các hình chữ nhật ngẫu nhiên trên màn hình.
Uses Crt,Graph;
Procedure ThietLapDohoa;
Var Gd,Gm:Integer;
Begin
Gd:=0;
InitGraph(Gd,Gm,’D:\BP\BGI’);
End;
Function RandColor:Byte;
Begin
RandColor:=Random(MaxColors – 1)+1;
End;
Procedure DeMo;
Var  x1,y1,x2,y2:Integer;
Begin
Randomize;
Repeat
x1:=Random(GetMaxX);
y1:=Random(GetMaxY);
x2:=Random(GetMaxX – x1) + x1;
y2:=Random(GetMaxX – y1) + y1;
SetColor(RandColor);
Rectangle(x1,y1,x2,y2);
Delay(500);
Until KeyPressed;
End;
BEGIN
ThietLapDohoa;
DeMo;
CloseGraph;
END.

Bài tập 10.3: Vẽ một kim đồng hồ quay quanh tâm O(x0,y0).

Uses crt,Graph;
Var x0,y0:word;
Alpha,Beta,R:real;
Procedure VeDgt(x0,y0:word; R,Alpha:real);
Begin
Line(x0,y0,x0+Round(R*Cos(Pi*Alpha/180)),
y0-Round(R*Sin(Pi*Alpha/180)));
End;
BEGIN
ThietLapDoHoa;
x0:=GetMaxX div 2;
y0:=GetMaxY div 2;
R:=100;
Alpha:=90;
Beta:=6;
SetWriteMode(XORPut);
VeDgt(x0,y0,R,Alpha);
Repeat
VeDgt(x0,y0,R,Alpha);
Alpha:=Alpha - Beta;
VeDgt(x0,y0,R,Alpha);
Delay(250);
Until KeyPressed;
CloseGraph;
END.

Bài tập 10.4: Viết chương trình tạo Menu cho phép chọn và thực hiện các chức năng bằng cách di chuyển mũi tên trên các hộp sáng, các thủ tục thực hiện xong quay trỏ lại Menu chính. Nhấn ESC để thoát khỏi chương trình.

USES  crt,graph;
Const mau1 =15;
mau2 =8;
maumn=7;
XTop=200;
YTop=100;
Dy=32;
Dx=250;
Type MANG_MENU=Array[1..20] of string;{dung luu cac dong menu }
MANG_THUTUC=Array[1..20] of Procedure;{dung luu cac thu tuc}
var  DongMN:MANG_MENU;
ThuTuc:MANG_THUTUC;
SoDong:byte;
Procedure Wait;
Var ch:Char;
BEGIN
ch:=ReadKey;
END;
{$F+}
Procedure Modun1;
BEGIN
Line(50,50,200,300);
Wait;
END;
Procedure Modun2;
BEGIN
Circle(200,200,100);
Wait;
END;
Procedure Modun3;
Begin
Ellipse(200,300,0,360,100,150);
Wait;
End;
Procedure Modun4;
BEGIN
Rectangle(50,50,200,300);
Wait;
END;
Procedure Modun5;
BEGIN
OutTextXY(50,50,’Chao mung cac ban den voi chuong trinh do hoa’);
Wait;
END;
Procedure Modun6;
BEGIN
OutTextXY(50,50,’Day la Menu do hoa’);
Wait;
END;
Procedure Thoat;
BEGIN
Halt;
END;
{$F-}
Procedure ThietLapDoHoa;
var gd,gm:integer;
Begin
Gd:=0;
InitGraph(gd,gm,'C:\BP\BGI');
End;
Procedure Box(x1,y1,x2,y2:integer; MauVienTren,MauVienduoi,MauNen:byte);
{Ve nut menu}
Var i:Byte;
begin
setfillstyle(1,MauNen);
bar(x1,y1,x2,y2);
setcolor(MauVienTren);
For i:=0 to 1 do
Begin
moveto(x1-i,y2+i);
lineto(x1-i,y1-i);
lineto(x2+i,y1-i);
End;
setcolor(MauVienDuoi);
For i:=0 to 1 do
Begin
moveto(x2+i,y1-i);
lineto(x2+i,y2+i);
lineto(x1-i,y2+i);
End;
end;
Procedure Ve_menu(Xdau,Ydau,DeltaX,DeltaY:Word;
chon,SoDong:Byte;DongMN:MANG_MENU);
Var i:Byte;
Begin
for i:=1 to SoDong do
begin
if i=chon then
Box(Xdau,Ydau+i*DeltaY+6,Xdau+DeltaX,YDau+i*DeltaY+DeltaY,
mau2,mau1,maumn)
Else
Box(Xdau,Ydau+i*DeltaY+6,Xdau+DeltaX,YDau+i*DeltaY+DeltaY,
mau1,mau2,maumn);
OutTextxy(Xdau+20,Ydau+15+i*DeltaY,DongMN[i]);
end;
End;
Procedure PullDown(x,y,DeltaX,DeltaY:Word;SoDong:Byte;
DongMenu:MANG_MENU;ThuTuc:MANG_THUTUC);
Var sott,LuuSott,Chon,i:Byte;
OK:Boolean;
Function Select(Xdau,Ydau,DeltaX,DeltaY:Word;SoDong:Byte):Byte;
var ch:char; j:Byte;
Begin
While True do
Begin
If KeyPressed then
Begin
ch:=readkey;
case ch of
#13: Begin {ENTER}
select:=Sott;
Exit;
End;
#72:Begin
LuuSott:=Sott;
Sott:=Sott-1;
if Sott&lt;1 then Sott:=SoDong;
Select:=Sott;
Box(XTop,YTop+LuuSoTT*DeltaY+6,
Xdau+DeltaX,Ydau+LuuSoTT*DeltaY+DeltaY,
Mau1,Mau2,maumn);
Outtextxy(Xdau+20,Ydau+15+LuuSoTT*DeltaY,
DongMN[LuuSoTT]);
Box(Xdau,Ydau+SoTT*DeltaY+6,
Xdau+DeltaX,Ydau+SoTT*DeltaY+DeltaY,
Mau2,Mau1,maumn);
Outtextxy(Xdau+20,Ydau+15+SoTT*DeltaY,
DongMN[SoTT]);
End;
#80:
Begin
LuuSott:=Sott;
Sott:=Sott+1;
if Sott&gt;SoDong then Sott:=1;
Select:=Sott;
Box(Xdau,Ydau+LuuSoTT*DeltaY+6,
Xdau+DeltaX,Ydau+LuuSoTT*DeltaY+DeltaY,Mau1,Mau2,maumn);
Outtextxy(Xdau+20,Ydau+15+LuuSoTT*DeltaY,
DongMN[LuuSoTT]);
Box(Xdau,Ydau+SoTT*DeltaY+6,
Xdau+DeltaX,Ydau+SoTT*DeltaY+DeltaY,Mau2,Mau1,maumn);
Outtextxy(Xdau+20,Ydau+15+SoTT*DeltaY,
DongMN[SoTT]);
End;
#27: {ESC}
Begin
OK:=False; Exit;
End;
end; { of case key }
End;
End;
End;
Begin {PullDown}
Sott:=1;   OK:=TRUE;
Ve_menu(X,Y,DeltaX,DeltaY,Sott,SoDong,DongMenu);
While OK do  { lap khong dieu kien }
Begin
Chon:=select(x,y,DeltaX,DeltaY,SoDong);
For i:=1 to SoDong do
If (i=Chon)and OK Then
Begin
ClearDevice;
ThuTuc[i];
ClearDevice;
Ve_Menu(X,Y,DeltaX,DeltaY,Sott,SoDong,DongMenu);
End;
end;{ of While }
End;
BEGIN
SoDong:=7;
DongMN[1]:='VE DOAN THANG ';
DongMN[2]:='VE DUONG TRON';
DongMN[3]:='VE ELLIPSE';
DongMN[4]:='VE HINH CHU NHAT';
DongMN[5]:='VIET LOI CHAO';
DongMN[6]:='VIET DONG QUANG CAO';
DongMN[7]:='THOAT KHOI CHUONG TRINH';
ThuTuc[1]:=Modun1;
ThuTuc[2]:=Modun2;
ThuTuc[3]:=Modun3;
ThuTuc[4]:=Modun4;
ThuTuc[5]:=Modun5;
ThuTuc[6]:=Modun6;
ThuTuc[7]:=Thoat;
ThietLapDoHoa;
SetBKcolor(LightBlue);
PullDown(XTop,YTop,DX,DY,SoDong,DongMN,ThuTuc);
CloseGraph;
END.

Bài tập 10.5: Vẽ hai hìnhVẽ miệng cá đồ họa Pascal

Sau đó, viết chương trình thực hiện chuyển động của miệng cá.

Uses Crt,Graph;
Type ProType=Procedure;
Var Gd,Gm:integer;
page1,page2:word;
Hinh:Array[0..1] of ProType;
Xc,Yc,r:Integer;
i:Byte;
{$F+}
Procedure HinhCa1;
Begin
SetColor(15);
PieSlice(Xc,Yc,30,330,R); {Ve bung ca}
SetColor(0);
Circle(Xc + R div 2,Yc - R div 2,4); {Mat ca}
End;
Procedure HinhCa2;
Begin
SetColor(15);
PieSlice(Xc,Yc,15,345,R); {Ve bung ca}
SetColor(0);
Circle(Xc + R div 2 ,Yc - R div 2,4); {Mat ca}
End;
{$F-}
Begin
gd:=4;
InitGraph(gd,gm,’’);
Xc:=GetMaxX div 2;
Yc:=GetMaxY div 2;
R:=50; i:=0;
Hinh[0]:=HinhCa1;
Hinh[1]:=HinhCa2;
page1:=0; page2:=1;
Repeat
SetVisualPage(page1);
SetActivePage(page2);
i:=1-i;
Hinh[i]; Delay(200);
page1:=1-page1;
page2:=1-page2;
Until  KeyPressed;
CloseGraph;
End.

Bài tập 10.6: Viết chương trình tạo một dòng chữ chạy ngang qua màn hình.

Uses crt,graph;
Var gd,gm:integer;
Procedure Run(s:string);
var page:byte;x,y:integer;
Begin
page:=1;
x:=getmaxx;y:=getmaxy div 3;
Settextjustify(0,1);
Setwritemode(xorput);
Setactivepage(page);
Repeat
Outtextxy(x,y,s);
Setvisualpage(page);
page:=not page;
setactivepage(page);
delay(10);
Outtextxy(x+1,y,s);
x:=x-1;
if x&lt;-textwidth(s) then x:=getmaxx;
Until (keypressed) and (readkey=#27);
end;
Begin
gd:=4;
Initgraph(gd,gm,'C:\BP\bgi');
setcolor(14);
settextstyle(1,0,5);
Run('Pham Anh Phuong');
Closegraph;
End.

Bài tập 10.7: Viết chương trình vẽ mô hình chiếc đĩa bay chuyển động ngẫu nhiên trên màn hình.

Uses crt; Graph;
Const r = 20; StartX = 100; StartY = 50;
Procedure ThietLapDohoa;
Var Gd,Gm:Integer;
Begin
Gd:=0;
InitGraph(Gd,Gm,’D:\BP\BGI’);
End;
Procedure Move(Var x,y:Integer);
Var Step:Integer;
Begin
Step:=Random(2*r);
If Odd(Step) Then Step:=-Step;
x:=x+Step;
Step:=Random(r);
If Odd(Step) Then Step:=-Step;
y:=y+Step;
End;
Procedure VeDiaBay;
Begin
Ellipse(StartX,StartY,0,360,r,(r div 3)+2);
Ellipse(StartX,StartY-4,190,357,r,r div 3);
Line(StartX+7,StartY-6,StartX+10,StartY-12);
Line(StartX-7,StartY-6,StartX-10,StartY-12);
Circle(StartX+10,StartY-12,2);
Circle(StartX-10,StartY-12,2);
End;
Procedure Play;
Var x1,y1,x2,y2,size:Word;
x,y:Integer;
P:Pointer;
Begin
VeDiaBay;
x1:=StartX - (r+1);
y1:=StartY - 14;
x2:=StartX + r + 1;
y2:=StartY + (r div 3) + 3;
(* Lưu và xóa ảnh *)
size:=ImageSise(x1,y1,x2,y2);
GetMem(p,size);
GetImage(x1,y1,x2,y2,P^);
PutImage(x,y,P^,XORPut); { Xóa ảnh }
x:=GetMaxX div 2;
y:=GetMaxY div 2;
(* Di chuyển đĩa bay *)
Repeat
PutImage(x,y,P^,XORPut); { Vẽ đĩa bay }
Delay(200);
PutImage(x,y,P^,XORPut); { Xóa đĩa bay }
Move(x,y);
Until KeyPressed;
FreeMem(p,size);  { Giải phóng vùng nhớ }
End;
BEGIN
ThietLapDoHoa;
Play;
CloseGraph;
END.

Bài tập 10.8: Viết chương trình để vẽ đa giác đều có n đỉnh.

Ý tưởng:

Khi vẽ một đa giác đều N đỉnh, các đỉnh này nằm trên một đường tròn (O,R) đồng thời khoảng cách giữa hai đỉnh và tâm tạo thành một góc nhọn không đổi có giá trị là 2*Pi/N.

Giả sử đỉnh thứ nhất của đa giác nằm trên đường thẳng tạo với tâm một góc 00, đỉnh thứ hai tạo một góc 2*Pi/N và đỉnh thứ i sẽ tạo một góc là 2*Pi(i-1)/N.

Một cách tổng quát, ta tạo một mảng để chứa tọa độ các đỉnh.

Const              Max = <Giá trị>;

Type                Mang = ARRAY[1..Max] of PointType;

Var                  P:Mang;

Giả sử chọn P0: PointType là tọa độ tâm của đa giác thì đỉnh thứ i của đa giác sẽ tạo một góc là:                  Angle:=2*Pi*(i-1)/N

Nhưng nếu đa giác này có đỉnh đầu tiên tạo một góc bằng A0 thì:

Angle:=2*Pi*((i-1)/N + A0/360)

Và tọa độ các đỉnh này trên màn hình là:

P[i].x := P0.x + R*cos(Angle)

P[i].y := P0.y  – R*sin(Angle)

Ta xây dựng thủ tục để tự động lưu các đỉnh của đa giác đều vào mảng P. Trong đó: P0 là tọa độ tâm, A0 là góc bắt đầu, R là bán kính, N là số đỉnh (3<N<Max).

Uses Crt,Graph;
Const Max = 10;
Type Mang = Array[1..Max] of PointType;
Var    A0,R:real;
N:Byte;
P0:PointType;        P:Mang;
Procedure ThietLapDohoa;
Var Gd,Gm:Integer;
Begin
Gd:=0;
InitGraph(Gd,Gm,’D:\BP\BGI’);
End;
Procedure TaoDinh(R,A0:real;N:Byte;P0:PointType;Var P:MANG);
var    i:Byte;
Angle:real;
Begin
If (n&lt;3)or(n&gt;=Max) then
Begin
Writeln('Khong tao duoc tap dinh!');
Exit;
End;
For i:=1 to n do
With P[i] do
Begin
Angle:=2*Pi*((i-1)/n + A0/360);
x:=P0.x + Round(R*Cos(Angle));
y:=P0.y - Round(R*Sin(Angle));
End;
P[n+1]:=p[1];
End;
BEGIN
Write(‘Nhap so dinh cua da giac deu: n= ‘); Readln(N);
ThietLapDoHoa;
P0.x:=GetMaxX div 2;
P0.y:=GetMaxY div 2;
A0:=90;
R:=GetMaxY div 4;
TaoDinh(R,A0,5,P0,P);
DrawPoly(5,P);
CloseGraph;
END.

Bài tập 10.9: Viết chương trình vẽ đồ thị hàm số sau: f(x) = ax2 + bx + c.

Ý tưởng:

Bước 1: Xác định đoạn cần vẽ [Min,Max].

Bước 2: Đặt gốc tọa độ lên màn hình (x0,y0).

Chia tỉ lệ vẽ trên màn hình theo hệ sô k.

Chọn số gia dx trên đoạn cần vẽ.

Bước 3: Chọn điểm xuất phát: x = Min, tính f(x).

Đổi qua tọa độ màn hình và làm tròn:

x1:=x0 + Round(x.k);

y1:=y0 – Round(y.k);

Di chuyển đến (x1,y1): MOVETO(x1,y1);

Bước 4: Tăng x lên: x:=x + dx;

Đổi qua tọa độ màn hình và làm tròn:

x2:=x0 + Round(x.k);

y2:=y0 – Round(y.k);

Vẽ đến (x2,y2): LINETO(x2,y2);

Bước 5: Lặp lại bước 4 cho đến khi x > Max thì dừng.

Uses Crt,Graph;
var a,b,c,Max,Min:real;
Procedure ThietLapDohoa;
Var Gd,Gm:Integer;
Begin
Gd:=0;
InitGraph(Gd,Gm,’D:\BP\BGI’);
End;
Function F(x:real):real;
Begin
F:=a*x*x + b*x + c;
End;
Procedure VeDoThi(Min,Max:real);
var x1,y1:integer;
dx,x,k:real;
x0,y0:word;
Begin
x0:=GetMaxX div 2;
y0:=GetMaxY div 2;
K:=GetMaxX/30;
dx:=0.001;
x:=Min;
x1:=x0 + Round(x*k);
y1:=y0 - Round(F(x)*k);
Moveto(x1,y1);
While x&lt;Max do
Begin
x:=x+dx;
x1:=x0 + Round(x*k);
y1:=y0 - Round(F(x)*k);
LineTo(x1,y1);
End;
End;
BEGIN
Write(‘Nhap a= ‘); Readln(a);
Write(‘Nhap b= ‘); Readln(b);
Write(‘Nhap c= ‘); Readln(c);
ThietLapDoHoa;
Min:=-10; Max:=10;
{Vẽ trục tọa độ}
Line(GetMaxX Div 2,1,GetMaxX Div 2,GetMaxY);
Line(1,GetMaxY Div 2,GetMaxX,GetMaxY Div 2);
VeDoThi(Min,Max);
Repeat Until KeyPressed;
CloseGraph;
END.

Bài tập 10.10: Vẽ hình bông hoa.

Ý tưởng:

Dùng tọa độ cực. Giả sử ta có tọa độ cực trong đó:

Trục cực: Ox

Góc quay: α

thì tọa độ cực của một điểm trong mặt phẳng là cặp (x,y) với:

x = f(α).Cos(α)

y = f(α).Sin(α)

Trong đó: f(a) là phương trình do ta qui định.

Ví dụ:

f(α) = k.Cos(nα) : Hình bông hoa.

Vẽ hình bông hoa đồ họa Pascal

f(α) = a.α(a>0) : Đường xoắn ốc Acsimet.

f(α) = k.(1+Cos(α)): Hình trái tim.

Uses Crt,Graph;
var R,chuky:real;
Procedure ThietLapDohoa;
Var Gd,Gm:Integer;
Begin
Gd:=0;
InitGraph(Gd,Gm,’D:\BP\BGI’);
End;
Function F(R,Alpha:real):real; { Tính hàm f(a) }
Begin
F:=R*cos(19*Alpha/3)+5;
End;
Procedure VeHinh(ChuKy:real);
var x1,x2,y1,y2:integer;
a,Alpha,k:real;
x0,y0:word;
Begin
x0:=GetMaxX div 2;
y0:=GetMaxY div 2;
K:=GetMaxX/50;
a:=Pi/180;
Alpha:=0;
x1:=x0 + Round(F(R,Alpha)*k*cos(Alpha));
y1:=y0 - Round(F(R,Alpha)*k*sin(Alpha));
Moveto(x1,y1);
While Alpha&lt;ChuKy do
Begin
Alpha:=Alpha+a;
x1:=x0 + Round(F(R,Alpha)*k*cos(Alpha));
y1:=y0 - Round(F(R,Alpha)*k*sin(Alpha));
LineTo(x1,y1);
Delay(10);
End;
End;
BEGIN
ThietLapDoHoa;
R:=15; chuky:=4*Pi;
VeHinh(chuky);
repeat until KeyPressed;
CloseGraph;
END.

Bài tập 10.11: Viết chương trình vẽ cung Koch. Các bước phát sinh của cung Koch được thực hiện trong hình sau:Vẽ cung Koch đồ họa Pascal

  • Bắt đầu từ đường ngang K0 có độ dài bằng 1.
  • Để tạo cung bậc-1(gọi là K1), chia đường thành ba phần và thay đoạn giữa bằng tam giác đều có cạnh dài 1/3. Bây giờ, toàn bộ đường cong có độ dài 4/3.
  • Cung bậc-2 K2 có được bằng cánh dựng tiếp các tam giác đều từ 4 đoạn của K1. Vì mỗi đoạn có độ dài tăng 4/3 lần nên toàn bộ cung dài ra 4/3 lần.

Ý tưởng:

Từ hình (b) ta thấy rằng, đầu tiên hướng vẽ quay trái 600, rồi quay phải 1200, cuối cùng quay trái 600 để trở về hướng ban đầu.

Uses  Crt,Graph;
Var n:Integer;
Goc,length:real;
Procedure ThietLapDohoa;
Var gd,gm:integer;
Begin
gd:=0;
InitGraph(gd,gm,'D:\bp\bgi');
End;
Procedure   Koch(dir,len:real;n:integer);
const  rads=0.017453293;
Begin
If n&gt;0 Then
Begin
Koch(dir,len/3,n-1);
dir:=dir+60; {Quay phải 60 độ}
Koch(dir,len/3,n-1);
dir:=dir-120; {Quay trái 120 độ}
Koch(dir,len/3,n-1);
dir:=dir+60; {Quay phải 60 độ}
Koch(dir,len/3,n-1);
End
else LineRel(Round(len*cos(rads*dir)),Round(len*sin(rads*dir)));
end;
Begin
ThietLapDoHoa;
n:=4;=
Goc:=180;
Length:=150;
Moveto(300,200);
Koch(Goc,Length,n);
Repeat until  keypressed;
Closegraph;
END.

Vẽ C Cung đồ họa Pascal
Bài tập 10.12: Viết chương trình tạo ra C-cung dựa trên sự tinh chế tương tự của một đoạn thẳng theo hình sau:

Ý tưởng:

Để có dạng phát sinh kế tiếp, mỗi đoạn thẳng được thay bởi một “hình gãy” gồm 2 đoạn ngắn hơn tạo với nhau một góc 900. Các đoạn mới có độ dài bằng 1/  lần đoạn ở bước trước.

Xét hướng vẽ ở một đầu của đoạn thẳng. Để vẽ hình gãy, hướng vẽ quay trái 450, vẽ một đoạn, quay phải 900, vẽ đoạn thứ hai và sau đó trở về hướng cũ bằng cách quay góc 450.

Uses  graph,crt;
Procedure ThietLapDohoa;
Var    gd,gm,gr:integer;
Begin
gd:=0;
Initgraph(gd,gm,'D:\bp\bgi');
End;
PROCEDURE     VeC_Cung;
Var n:Integer;
Goc,length:real;
Procedure   Rong(dir,len:real;n:integer);
const  d=0.7071067;
rads=0.017453293;
begin
if n&gt;1 then
begin
dir:=dir+45;
Rong(dir,len*d,n-1);
dir:=dir-90;
Rong(dir,len*d,n-1);
dir:=dir+45;
end
else LineRel(Round(len*cos(rads*dir)),Round(len*sin(rads*dir)));
end;
Begin
n:=15;
Goc:=0;
Length:=130;
Moveto(200,200);
Rong(Goc,Length,n);
repeat until  keypressed;
End;
BEGIN
ThietLapDoHoa;
VeC_Cung;
Closegraph;
END.

C Cung đồ họa Pascal

Bài tập 10.13: Viết chương trình vẽ tập Mandelbrot – là một hình trong mặt phẳng phức. Tập Mandelbrot được phát sinh theo công thức sau:

z → z2 + c (*)

Tập hợp Mandelbrot là tập bao gồm những số phức c sao cho z2+c vẫn hữu hạn với mọi lần lặp.

Ý tưởng:

Ta chọn số phức cố định c và tính biểu thức z2+c với z là số phức biến đổi.

Nếu chọn z = 0 thì z2+c = c. Thay z vào công thức (*) ta được c2+c.

Tiếp tục thay z bằng giá trị mới, ta lại có: (c2+c)2+c, …

Cứ như vậy, ta thu được một dãy vô hạn các số z.

Uses crt,graph;
Const row=1;
col=1;
Var    x1,y1,x2,y2,kx,ky:real;
Gioihan:Byte;
x0,y0:word;
Diemduoi,Diemtren:Integer;
Procedure ThietLapDohoa;
Var    gd,gm,gr:integer;
Begin
gd:=0;
Initgraph(gd,gm,'D:\bp\bgi');
End;
Procedure KhoiTao;
Begin
Diemduoi:=GetMaxX;
Diemtren:=GetMaxY;
x1:=-2; y1:=-1.25;
x2:=0.5; y2:=1.25;
kx:=(x2-x1)/diemduoi;
ky:=(y2-y1)/diemtren;
Gioihan:=50;
End;
Procedure ManDelbrot;
var  dong,cot,dem:integer;
P0,Q0,Modun,x,y,Aux:real;
Begin
cot:=0;
While cot&lt;=diemduoi do
Begin
P0:=x1+cot*kx;
dong:=0;
While dong&lt;=(diemtren div 2) do
Begin
Q0:=y1+dong*ky;
x:=0; y:=0;
dem:=1; Modun:=1;
While (dem&lt;=gioihan)and(modun&lt;4) do
Begin
Aux:=x;
x:=x*x-y*y +P0;
y:=2*y*Aux + Q0;
Modun:=x*x + y*y;
dem:=dem+1;
End;
If Modun&lt;4 Then
Begin
PutPixel(cot,dong,3);
PutPixel(cot,diemtren-dong,3);
End;
dong:=dong+row;
End;
cot:=cot+col;
End;
End;
Begin
ThietLapDohoa;
KhoiTao;
Mandelbrot;
readln;
CloseGraph;
End.

Tập MandelBrot đồ họa Pascal

BÀI TẬP TỰ GIẢI

Bài tập 10.14: Viết chương trình vẽ bàn cờ quốc tế lên màn hình.

Bài tập 10.15: Viết chương trình vẽ một chiếc xe ô tô (theo hình dung của bạn) và cho nó chạy ngang qua màn hình.

Gợi ý:

Dùng kỹ thuật lật trong màn hình hoặc di chuyển vùng màn hình.

Bài tập 10.16: Viết chương trình vẽ lá cờ tổ quốc đang tung bay.

Gợi ý:

Dùng kỹ thuật lật trong màn hình.

Bài tập 10.17: Viết chương trình nhập vào n học sinh của một lớp học bao gồm 2 trường sau: Họ tên, điểm trung bình.

a/ Hãy thống kê số lượng học sinh giỏi, khá, trung bình và yếu.

b/ Vẽ biểu đồ thống kê số lượng học sinh giỏi, khá, trung bình và yếu theo 2 dạng: biểu đồ cột (column) và biểu đồ bánh tròn (Pie).

Bài tập 10.18: Viết chương trình để vẽ đồ thị của các hàm số sau:

a/ y = ax3 + bx2 + cx +d

b/ y = ax4 + bx3 + cx2 + dx + e

Bài tập 10.19: Hình vẽ cung Koch dựa trên 3 cạnh của tam giác đều như hình sau:

Cung- Koch

Bài tập 10.20: Viết chương trình để vẽ đường xoắn ốc.

Gợi ý:

Dùng tọa độ cực.

Bài tập 10.21: Viết chương trình vẽ cái đồng hồ đang hoạt động.

Bài tập 10.22: Viết chương trình mô phỏng chuyển động của trái đất xung quanh mặt trời và đồng thời chuyển động của mặt trăng xung quanh trái đất.

Gợi ý:

Dùng ma trận của phép quay.

Bài tập 10.23: Xây dựng một thư viện (Unit) chứa tất cả các bài tập trong chương này.

Bài tập 10.24: Viết chương trình tạo Menu đồ họa giống như các Menu trong môi trường WINDOWS (xem hình).

Tạo Menu Winddows đồ họa Pascal

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Free Web Hosting