Xây dựng và trực quan hóa trò chơi Sudoku bằng Pygame
Sudoku là một trò chơi giải đố sắp xếp số dựa trên logic, kết hợp. Mục tiêu là...
Category: Pygame
Trong bài viết này, chúng ta sẽ tạo mẫu Rhodonea Curve và Maurer Rose bằng Python! Trước khi tìm hiểu chính xác Rhodonea Curve hay Maurer Rose là gì , chúng ta cần chuẩn bị cấu trúc cơ bản của chương trình!
Trước khi tìm hiểu về đường cong Rhodonea hay mô hình hoa hồng Maurer, trước tiên chúng ta cần chuẩn bị cấu trúc cơ bản của chương trình. Để khi tái cấu trúc mã, chúng ta chỉ cần sửa đổi một hàm trong khi phần còn lại của chương trình vẫn giữ nguyên. Dưới đây là cấu trúc cơ bản của chương trình:
from math import sin
from math import cos
from math import radians
import pygame
# Chiều rộng và chiều cao của chương trình
(width, height) = (800, 600)
# Thiết lập cửa sổ và khởi tạo bề mặt màn hình
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Đồ thị hoa thị (Rose Curve) trong Python!')
# Màu nền của màn hình
screen.fill((250, 250, 205)) # màu lemonChiffon (vàng nhạt)
# Hàm vẽ đồ thị hoa thị
drawPattern()
# Lật màn hình đã vẽ với màn hình hiển thị (double-buffering)
# Cơ bản là làm mới màn hình sau khi vẽ xong
pygame.display.flip()
# Vòng lặp chính
while True :
# Duyệt qua các sự kiện trong hàng đợi sự kiện
for event in pygame.event.get() :
# Nếu người dùng đóng cửa sổ
if event.type == pygame.QUIT :
# Tắt pygame và thoát chương trình
pygame.quit()
quit()
# Cập nhật nội dung hiển thị trên màn hình
pygame.display.update()
Nếu bạn chạy mã, bạn sẽ nhận được lỗi drawPattern chưa được định nghĩa. Chúng ta sẽ định nghĩa nó sau. Nhưng bây giờ cứ để nguyên như vậy và chúng ta hãy cùng tìm hiểu đường cong Rhodonea là gì !
Những điều trên chỉ là lý thuyết, nếu bạn chưa hiểu hết khái niệm, bạn sẽ hiểu sau khi xem nó hoạt động . Chỉ cần thêm đoạn mã sau vào dòng 17 (ngay phía trên nơi chúng ta gọi drawPattern):
# Vẽ một đường hoa thị (rose) với n cánh và bán kính khoảng `size`
def drawRhodoneaCurve(n, size):
points =[]
for i in range(0, 361):
# Phương trình của đường hoa thị (Rhodonea curve)
r = size * sin(radians(n * i))
# Chuyển đổi sang tọa độ Đề các (Cartesian)
x = r * cos(radians(i))
y = r * sin(radians(i))
list.append(points, (width / 2 + x, height / 2 + y))
# Vẽ một tập hợp các đoạn thẳng nối các điểm trong danh sách
# Không khép kín đường, vẽ màu đen và đặt độ dày nét là 5
pygame.draw.lines(screen, (0, 0, 0), False, points, 5)
def drawPattern():
# Thử thay đổi các giá trị này theo ý bạn
drawRhodoneaCurve(12, 200)
Điều này sẽ tạo ra kết quả sau -
Giải thích
Chúng tôi tính toán các đỉnh (mỗi điểm quan trọng trên hoa hồng sau đó được kết nối bằng các cạnh đơn giản là các đoạn thẳng) bằng cách sử dụng công thức mà chúng tôi đã thảo luận ở phần trên
Chúng tôi lưu trữ một danh sách gọi là points chứa tất cả các đỉnh của hoa hồng và sau đó danh sách các đỉnh này được đưa vào pygame.draw.lines để vẽ một chuỗi các đường thẳng liên tục và ở đây chúng tôi sử dụng nó để vẽ chuỗi đa giác (vì hoa hồng chỉ là một chuỗi đa giác)
Lưu ý rằng chúng ta đang sử dụng phương thức radian ở đây. Điều này là do các góc được định dạng theo độ (chúng ta có thể sử dụng trực tiếp radian nhưng range chỉ chấp nhận số nguyên, còn đối với đường cong Maurer, dù sao chúng ta cũng phải sử dụng độ, vậy tại sao không bắt đầu từ bây giờ) - hy vọng là chúng ta không phải tự chuyển đổi vì Python3 cung cấp các hàm tích hợp degrees và radian .
Cũng lưu ý rằng chúng ta đang dịch chuyển tọa độ theo (chiều rộng/2, chiều cao/2). Điều này là do mặc định PyGame có tọa độ ở góc trên bên trái. Nhưng chúng ta muốn nó nằm ở giữa nên dịch chuyển nó bằng một nửa chiều rộng và chiều cao màn hình. Chúng ta có thể dịch chuyển toàn bộ hệ tọa độ nhưng cách này dễ hơn!
Lưu ý về việc làm cho chương trình tương tác hơn:
Chương trình hiện tại chưa thực sự tương tác, nhưng bạn có thể làm cho nó tương tác bằng cách tăng số lượng cánh hoa lên một lượng fractal mỗi khung hình, và tùy thuộc vào tốc độ tăng dần, bạn có thể đạt được kết quả khá ấn tượng. Việc làm cho chương trình tương tác nằm ngoài phạm vi (vì điều đó sẽ làm tăng đáng kể số lượng LOC và có lẽ cũng làm tăng độ phức tạp của chương trình, đồng thời vi phạm cấu trúc cơ bản mà chúng ta đã tạo ra lúc đầu), nhưng tôi đã thử nghiệm một chút và đây là kết quả của việc tạo biến n trước rồi tăng nó lên 0,1 ở mỗi khung hình!
Vì vậy, để tạo ra thứ gì đó từ những gì chúng ta vừa học, chúng ta ghi đè hàm drawPattern trước đó bằng hàm mới:-
# Vẽ một hoa thị Maurer (Maurer rose) với giá trị n và d, kích thước khoảng `size`
def drawMaurerRose(n, d, size):
points =[]
for i in range(0, 361):
# Phương trình của hoa thị Maurer
k = i * d
r = size * sin(radians(n * k))
# Chuyển sang tọa độ Đề các (Cartesian)
x = r * cos(radians(k))
y = r * sin(radians(k))
list.append(points, (width / 2 + x, height / 2 + y))
# Vẽ các đoạn thẳng nối các điểm trong danh sách
# Không khép kín đường, vẽ màu đen và đặt độ dày nét là 5
pygame.draw.lines(screen, (0, 0, 0), False, points, 5)
def drawPattern():
# Thử thay đổi các giá trị này theo ý bạn
drawMaurerRose(6, 79, 200)
Và bây giờ khi bạn chạy chương trình, bạn sẽ nhận được kết quả sau:
Giải thích:
Chỉ có những dòng được tô sáng là thay đổi, còn lại mọi thứ đều giống nhau -
Tên hàm đã được đổi từ drawRhodoneaCurve thành drawMaurerRose và hiện mong đợi một tham số bổ sung d!
Bây giờ chúng ta giới thiệu một biến k mới thực sự xuất phát từ công thức. Giá trị của nó ở mỗi lần lặp bằng i*d, vì vậy với d=1, hàm này hoàn toàn giống với drawRhodoneaCurve!!
Bây giờ chúng ta sử dụng k thay vì i và cần lưu ý rằng độ rộng của đường đã được thay đổi từ 5 thành 2 (nếu không, một số đường sẽ xuất hiện như một đường do độ dày của chúng lớn).
Và câu lệnh invoke tất nhiên cũng đã được thay đổi, giờ đây nó gọi hàm drawMaurerRose mới tạo với n=6 và d=71. Các giá trị được sao chép từ WikiPedia vì giá trị d ngẫu nhiên đôi khi có thể tạo ra những bông hoa hồng trông kỳ lạ!
Published on Jul 28, 2025
Sudoku là một trò chơi giải đố sắp xếp số dựa trên logic, kết hợp. Mục tiêu là điền các chữ số vào lưới 9x9 sao cho mỗi cột, mỗi hàng và mỗi ô lưới....
Thuật toán như Tìm kiếm Nhị phân có thể được hiểu dễ dàng bằng cách trực quan hóa. Bài viết này trình bày một chương trình trực quan hóa Thuật toá...
Thuật toán sắp xếp chèn có thể dễ dàng được hiểu bằng cách trực quan hóa. Trong bài viết này, một chương trình trực quan hóa thuật toán sắp xếp ch...
Thuật toán sắp xếp Heap có thể được hiểu dễ dàng bằng cách trực quan hóa. Bài viết này trình bày một chương trình trực quan hóa Thuật toán sắp xếp...
Thuật toán như Tìm kiếm Tam phân có thể được hiểu dễ dàng bằng cách trực quan hóa. Bài viết này trình bày một chương trình trực quan hóa Thuật toá...
Trong bài viết này, chúng ta sẽ xem cách hình dung thuật toán sắp xếp nổi bọt (bubble sort ) bằng PyGame. Cụ thể, khi khởi động ứng dụng PyGame,....