Trong các chương trước, ta đã sử dụng khá nhiều những HÀM rồi. Chẳng hạn như print() để “in” ra màn hình, input() để nhập dữ liệu từ bàn phím, forward() để “con rùa” nhích tới, circle() để vẽ vòng tròn, left() cho rùa quẹo trái, bgcolor() cho màu nền v.v..và v.v..Dạng tổng quát của những hàm đó là: tên hàm(các đối số). Đó là những chương trình conmà những lệnh lạc đã do Python viết sẵn và để trong “thư viện” mà chúng ta đã download và install lên máy mình. Khi lập trình, cần đến đâu thì “gọi’ chúng đến đó. Vậy tại sao chúng ta không lập ra những chương trình con của riêng mình để khi cần thì gọi chúng ra sử dụng không phải viết (coding) lại?.
Bạn còn nhớ chương trình RandomSpirals.py ở chương 6? Xin lập lại:
#RandomSpirals.py import random import turtle # vì phải vẽ nên phải “nhập cảng” con rùa t = turtle.Pen() turtle.bgcolor("black") colors = ["red", "yellow", "blue", "green", "orange", "purple", "white", "gray"] # danh sách (list) các màu for n in range(50): # Vẽ những vòng xoắn có kích thước/màu một cách ngẫu nhiên tại vị trí cũng ngẫu nhiên t.pencolor(random.choice(colors)) # Chọn 1 màu ngẫu nhiên size = random.randint(10,40) # chọn kích thước vòng xoắn 1 cách ngẫu nhiên trong khoảng từ 10 đến 40 pixels # Chọn ngẫu nhiên 1 vị trí toạ độ (x,y) trên màn hình x = random.randrange(-turtle.window_width()//2, turtle.window_width()//2) # hoành độ ngẫu nhiên y = random.randrange(-turtle.window_height()//2, turtle.window_height()//2) # tung độ ngẫu nhiên t.penup() t.setpos(x,y) # định vị trí “con rùa” vừa cho ngẫu nhiên bên trên t.pendown() for m in range(size): # vòng lặp vẽ vòng xoắn vuông t.forward(m*2) t.left(91)
Giả sử trong một chương trình khác, bạn cần đoạn chương trình vẽ những vòng xoắn vuông như trên, bạn chỉ cần cho nó một cái tên và trước cái tên ấy có chữ def (definition) rồi đưa nó vào chương trình chính của mình; nơi nào cần thì cứ gọi cái tên đó, không cần viết lại cái đoạn chương trình ấy nữa:
Ví dụ function của riêng bạn để vẽ vòng xoắn vuông:
def RandomSpirals(): t.pencolor(random.choice(colors)) # Chọn 1 màu ngẫu nhiên size = random.randint(10,40) # chọn kích thước vòng xoắn 1 cách ngẫu nhiên trong khoảng từ 10 đến 40 pixels # Chọn ngẫu nhiên 1 vị trí toạ độ (x,y) trên màn hình x = random.randrange(-turtle.window_width()//2, turtle.window_width()//2) # hoành độ ngẫu nhiên y = random.randrange(-turtle.window_height()//2, turtle.window_height()//2) # tung độ ngẫu nhiên t.penup() t.setpos(x,y) # định vị trí “con rùa” vừa cho ngẫu nhiên bên trên t.pendown() for m in range(size): # vòng lặp vẽ vòng xoắn vuông t.forward(m*2) t.left(91)
Chương trình chính sau đây có lắp function def RandomSpirals(): của riêng ta vào và khi cần thì call (gọi) nó:
# RandomSpiralsFunction.py import random import turtle t = turtle.Pen() t.speed(0) turtle.bgcolor("black") colors = ["red", "yellow", "blue", "green", "orange", "purple", "white", "gray"] def RandomSpirals(): # function này là của “cây nhà lá vườn” lắp vào t.pencolor(random.choice(colors)) size = random.randint(10,40) x = random.randrange(-turtle.window_width()//2, turtle.window_width()//2) y = random.randrange(-turtle.window_height()//2, turtle.window_height()//2) t.penup() t.setpos(x,y) t.pendown() for m in range(size): t.forward(m*2) t.left(91) for n in range(50): RandomSpirals() # chỉ gọi (call) 50 lần mà không phải viết lại cái hàm def RandomSpirals() đến 50 lần
Bài tập: Bạn/trẻ đổi function def() nói trên, cho vẽ 50 lần vòng xoắn tròn, dựa vào chương trình RandomSpirals của chương VI.
NHỮNG THÔNG SỐ (PARAMETERS HAY LÀ ARGUMENTS) CỦA HÀM (FUNCTION)
Có những hàm đôi khi không có thông số (đối số: arguments) như print() để in 1 dòng trống. Đối số có thể là một string (text) như print(“I love you”), cũng có thể là một số (number) như t.left(91), là những biến (variables) như setpos(x+15), y+60)….
Chương trình sau đây cho ta thấy các hàm nhận những đối số như thế nào. Chương trình muốn vẽ mặt một người cười, có cái đầu tròn vàng, đôi mắt xanh, và cái mồm đen cười, ở những vị trí (toạ độ) bất kỳ, ngẫu nhiên (random) trên màn hình. Muốn vậy, bạn thử vẽ nó trên giấy kẻ ô với hai trục x, y như sau:
Sau đó bạn lập trình như sau:
#RandomSmileys.py import random import turtle t = turtle.Pen() t.speed(0) t.hideturtle() turtle.bgcolor("black") def matcuoi(x,y): # function matcuoi của bạn với các đối số x và y t.penup() t.setpos(x,y) # vị trí toạ độ đầu tiên của “con rùa” t.pendown() # Vẽ cái đầu t.pencolor("yellow") # màu của cây bút con rùa t.fillcolor("yellow") # màu của cái đầu là vàng t.begin_fill() # bắt đầu tô t.circle(50) # cái đầu tròn, bán kính 50 pixels (dots) t.end_fill() # tô xong # t. làchữ tắt của turtle.Pen() # Vẽ mắt trái t.setpos(x-15, y+60) # toạ độ mắt trái xem hình t.fillcolor("blue") # mắt xanh lả bóng dừa hoang dại t.begin_fill() t.circle(10) # mắt tròn xoe, bán kính 10 pixels t.end_fill() # Vẽ mắt phải t.setpos(x+15, y+60) # toạ độ mắt phải, xem hình 7-1 t.begin_fill() t.circle(10) t.end_fill() # Vẽ cái miệng t.setpos(x-25, y+40) # toạ độ nơi bắt đầu vẽ t.pencolor("black") t.width(10) # bề dầy cây bút t.goto(x-10, y+20) # cây bút di chuyển để vẽ, xem hình 7-1 t.goto(x+10, y+20) t.goto(x+25, y+40) t.width(1) # cho bút trở lại kích thước bình thường là 1 pixel for n in range(50): # loop vẽ 50 cái mặt cười x = random.randrange(-turtle.window_width()//2, turtle.window_width()//2) # Phạm vi theo chiều ngang màn hình # và theo chiều cao màn hình y = random.randrange(-turtle.window_height()//2, turtle.window_height()//2) # dấu // là chia chỉ lấy số nguyên matcuoi(x,y) # gọi (call) function của ta
Chú thích: chữ đậm để lưu ý những hàm mới hoặc cần chú ý trong bài. # là để diễn giải dòng lệnh. Khi gõ chương trình không cần gõ những dòng # (comments) hay làm chữ đậm (bold). Qua bài này bạn thấy công dụng của nhiều functions hơn nữa và cách Python chuyển arguments cho chúng ra sao. Nhất là bạn thấy công dụng tiện lợi của hàm mà bạn “tự chế” DEF và cách gọi chúng ra xài như thế nào.
Sau đây là kết quả của “nụ cười sơn cước” khi Run->Run Module:
FUNCTION CỦA TA TRẢ KẾT QUẢ CHO CHƯƠNG TRÌNH
Các hàm của ta có thể được gọi đến để làm một số việc . Khi xong chúng trả kết quả về chương trình chính. Chẳng hạn ta có hàm đổi inch ra centimeter, hoặc hàm đổi pound (lb) ra kí lô (kg). Sau khi đổi xong chúng cho kết quả trở về chương trình chính khi chương trình này gọi nó. Biết rằng 1 inch=2.54 cm và 1lb=1/2.2 kg.
Chương trình sau đây là một ví dụ: một quả bóng bàn nặng 2.7 gram và đường kính 4 cm. Mỹ không xài hệ bách phân. Chiều dài họ tính bằng inch và sức nặng tính bằng pound (lb). Vậy khi họ cho chiều cao bằng inch ta phải chuyển ra cm và khi họ cho sức nặng bằng lb ta phải chuyển ra kg. Với chiều cao và sức nặng ấy sẽ cần bao nhiêu quả bóng chồng lên cao và bao nhiêu quả bóng cho sức nặng ấy?
# PingPongCalculator.py def convert_in2cm(inches): # function của ta đổi inch ra cm return inches * 2.54 # trả kết quả cho chương trình chính khi được gọi def convert_lb2kg(pounds): # function của ta đổi lb ra kg return pounds / 2.2 # trả kết quả cho chương trình chính khi được gọi height_in = int(input("Enter your height in inches: ")) # nhập chiều cao lấy số nguyên weight_lb = int(input("Enter your weight in pounds: ")) # nhập cân nặng và lấy số nguyên height_cm = convert_in2cm(height_in) # gọi function convert_in2cm() để nó tính dùm chiều cao từ inch ra cm weight_kg = convert_lb2kg(weight_lb) # gọi function convert_lb2kg() ping_pong_tall = round(height_cm / 4) # tính tròn (round) ping_pong_heavy = round(weight_kg * 1000 / 2.7) feet = height_in // 12 inch = height_in % 12 print("At", feet, "feet", inch, "inches tall, and", weight_lb, "pounds,") print("you measure", ping_pong_tall, "Ping-Pong balls tall, and ") print("you weigh the same as", ping_pong_heavy, "Ping-Pong balls!")
Chú thích: hàm của ta là convert_in2cm() và convert_lb2kg(). Sau khi tính toán chúng trả kết quả về chương trình chính bằng lệnh return khi được gọi.
CHƯƠNG TRÌNH TƯƠNG TÁC (INTERACT) VỚI NGƯỜI DÙNG MÁY
Đó là khi ta bấm con chuột (mouse click) hay nhấn một nút trên keyboard, hay chạm ngón tay lên màn hình thì chương trình sẽ đáp trả ra sao, làm những gì. Phần lớn các chương trình (còn gọi là phần mềm, software hay apps) đều có tính cách tương tác (interactive).
1) Tương tác bằng bấm chuột (mouse click)
Một function (hàm) của Python dùng bấm chuột để tương tác là: turtle.onscreenclick(t.setpos). t. là thay thế cho turtle.Pen(). Đối số (argument) trong hàm này không phải là một biến (variable) hay chuỗi (string) mà là một hàm khác nữa, hàm setpos (set position).
Hàm turtle.onscreenclick(t.setpos) có nghiã khi ta bấm chuột ở vị trí toạ độ nào (do hàm setpos) trên màn hình thì “con ruà” chạy đến đó, vừa chạy vừa vẽ một đường thẳng. Bạn xem một chương trình nhỏ sau đây sẽ rõ:
# TurtleDraw.py # tương tác bằng bấm chuột import turtle t = turtle.Pen() t.speed(0) turtle.onscreenclick(t.setpos) # hàm tương tác bằng bấm chuột turtle.done() # must have this function
Một kết quả sau khi Run:
Bài tập: Bạn thử dùng IDLE gõ chương trình này rồi thử Run và vẽ cái nhà. Cứ cho trẻ vẽ quậy.
Cũng với chương trình trên, bạn sửa lại cho nền đỏ, bút con rùa xanh dương, bề ngang 99 pixels rồi Run thử xem sao. Chương trình sửa lại như sau:
# TurtleDrawMax.py import turtle t = turtle.Pen() t.speed(0) # nhanh turtle.onscreenclick(t.setpos) # hàm tương tác bằng mouse click turtle.bgcolor("red") # nền đỏ t.pencolor("blue") # bút xanh dương t.width(100) turtle.done() # phải có lệnh này khi dứt
2) TƯƠNG TÁC BẰNG CÁC MŨI TÊN (ARROWS) TRÊN KEYBOARD
Tương tác kiểu này ta dùng các nút mũi tên (arrows) trên bàn phím.
Và dùng Hàm: turtle.onkeypress(argument1, argument2).
Argument1 là tên của function của ta ; Argument 2: là tên của key trong ngoặc kép. Trong chương trình dưới đây ta sử dụng 3 functions của mình để tương tác: def up() để di chuyển con rùa 50 pixels, def left() để con rùa quẹo trái 90 độ và def right() để rùa quẹo phải 90 độ.
# ArrowDraw.py import turtle t = turtle.Pen() t.speed(0) t.turtlesize(2,2,2) # size con ruà: horizontal stretch, vertical stretch, outline thickness def up(): t.forward(50) def left(): t.left(90) def right(): t.right(90) turtle.onkeypress(up, "Up") # gọi function up() turtle.onkeypress(left, "Left") # gọi function left() turtle.onkeypress(right, "Right") # gọi function right() turtle.listen() # báo computer phải “nghe” những gì bấm trên keyboard turtle.done() # bắt buộc phải có hàm này để dứt
Run thử sẽ thấy đại loại như hình vẽ sau:
3) TƯƠNG TÁC BẰNG BẤM CHUỘT Ở BẤT CỨ NƠI NÀO MỘT CÁCH NGẪU NHIÊN TRÊN MÀN HÌNH
Xem chư ơng trình dưới đây để thấy cách thức và hàm thực hiện.
Chú thích: Hàm turtle.onscreenclick(tên hàm của người sử dụng ) cho phép ta thực hiện hàm của người sử d ụng (là bạn/tr ẻ) mỗi khi ta click chu ột trên màn hình.
Những functions “tự tạo” của bạn (người sử dụng) như spiral(x,y) bạn đã biết trong các chương trước.
#ClickSpiral.py import random import turtle t = turtle.Pen() t.speed(0) turtle.bgcolor("black") colors = ["red", "yellow", "blue", "green", "orange", "purple", "white", "gray"] def spiral(x,y): t.pencolor(random.choice(colors)) size = random.randint(10,40) t.penup() t.setpos(x,y) t.pendown() for m in range(size): t.forward(m*2) t.left(91) # gọi hàm spiral mỗi khi bấm trên màn hình turtle.onscreenclick(spiral) turtle.done()
Bạn Run chương trình này và bấm nhiều chỗ trên màn hình sẽ thấy nó vẽ những vòng xoắn vuông ở những nơi ấy, đại loại như hình vẽ 7-5 dưới đây:
Thay vì bấm đâu cũng cho ra hình xoắn vuông, bạn thay vào đó là bấm đâu cũng thấy mặt cười duyên:
#ClickAndSmile.py import random import turtle t = turtle.Pen() t.speed(0) t.hideturtle() # dấu không thấy con rùa turtle.bgcolor("black") def matcuoi(x,y): # function vẽ cái mặt cười ở chương trình trước t.penup() t.setpos(x,y) t.pendown() # Vẽ cái mặt t.pencolor("yellow") t.fillcolor("yellow") t.begin_fill() t.circle(50) t.end_fill() # Vẽ mắt trái t.setpos(x-15, y+60) t.fillcolor("blue") t.begin_fill() t.circle(10) t.end_fill() # Vẽ mắt phải t.setpos(x+15, y+60) t.begin_fill() t.circle(10) t.end_fill() # Mouth t.setpos(x-25, y+40) t.pencolor("black") t.width(10) t.goto(x-10, y+20) t.goto(x+10, y+20) t.goto(x+25, y+40) t.width(1) turtle.onscreenclick(matcuoi) turtle.done()
Cho Run rồi bấm chuột nhiều nơi khác nhau trên màn hình sẽ thấy hình đại loại như sau:
BÀI TẬP TỔNG HỢP CHƯƠNG VII
Bạn/trẻ viết 1 chương trình có 2 functions của bạn để vẽ hình kính vạn hoa (cho tên là draw_kakeido), và function vẽ hình xoắn ốc vuông (cho tên là draw_spiral). Function draw_keiko sẽ gọi function draw_spiral để vẽ. Dùng turtle.onscreenclick để bấm bất cứ nơi nào trên màn hình để vẽ.
Bài giải mẫu:
#ClickKaleidoscope.py import random import turtle t = turtle.Pen() t.speed(1000) t.hideturtle() turtle.bgcolor("black") colors = ["red", "yellow", "blue", "green", "orange", "purple", "white", "gray"] def draw_kaleido(x,y): # function này của bạn lại gọi function draw_spiral(x,y, size) t.pencolor(random.choice(colors)) size = random.randint(10,40) # số cạnh là số nguyên ngẫu nhiên từ 10 đến 40 draw_spiral(x,y, size) draw_spiral(-x,y, size) draw_spiral(-x,-y, size) draw_spiral(x,-y, size) def draw_spiral(x,y, size): # function của bạn vẽ xoắn ốc vuông t.penup() t.setpos(x,y) t.pendown() for m in range(size): t.forward(m*2) t.left(92) turtle.onscreenclick(draw_kaleido) # khi bấm chuột sẽ gọi function vẽ kính vạn hoa draw_kakeido turtle.done() # Phải có lệnh này mới chạy được
HẾT CHƯƠNG VII